diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java index e64f69a..82810c8 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java @@ -10,6 +10,7 @@ import fr.titionfire.ffsaf.data.repository.CombRepository; import fr.titionfire.ffsaf.net2.ServerCustom; import fr.titionfire.ffsaf.net2.data.SimpleClubModel; import fr.titionfire.ffsaf.net2.request.SReqClub; +import fr.titionfire.ffsaf.rest.data.ClubMapData; import fr.titionfire.ffsaf.rest.data.DeskMember; import fr.titionfire.ffsaf.rest.data.RenewAffData; import fr.titionfire.ffsaf.rest.data.SimpleClubList; @@ -25,6 +26,7 @@ import io.quarkus.hibernate.reactive.panache.common.WithSession; import io.quarkus.panache.common.Page; import io.quarkus.panache.common.Sort; import io.quarkus.vertx.VertxContextSupport; +import io.smallrye.mutiny.Multi; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.enterprise.context.ApplicationScoped; @@ -121,7 +123,8 @@ public class ClubService { } public Uni getOfUser(SecurityCtx securityCtx) { - return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult().invoke(Unchecked.consumer(m -> { + return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult() + .invoke(Unchecked.consumer(m -> { if (m == null || m.getClub() == null) throw new DNotFoundException("Club non trouvé"); })) @@ -143,7 +146,8 @@ public class ClubService { TypeReference> typeRef = new TypeReference<>() { }; - return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult().invoke(Unchecked.consumer(m -> { + return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult() + .invoke(Unchecked.consumer(m -> { if (m == null || m.getClub() == null) throw new DNotFoundException("Club non trouvé"); if (!securityCtx.isInClubGroup(m.getClub().getId())) @@ -279,4 +283,31 @@ public class ClubService { .toList())) .map(o -> data); } + + public Uni> getMapData() { + return repository.list("international", false).toMulti().flatMap(list -> Multi.createFrom().iterable(list)) + .call(clubModel -> Mutiny.fetch(clubModel.getContact())) + .map(clubModel -> { + ClubMapData data = new ClubMapData(); + + data.setName(clubModel.getName()); + data.setUuid(clubModel.getClubId()); + if (clubModel.getTraining_location() != null) { + try { + MAPPER.readTree(clubModel.getTraining_location()).forEach(l -> { + ClubMapData.Location loc = new ClubMapData.Location(); + loc.setLat(l.get("lat").asDouble()); + loc.setLng(l.get("lng").asDouble()); + loc.setAddr(l.get("text").asText()); + data.training_location.add(loc); + }); + } catch (JsonProcessingException ignored) { + } + } + data.setTraining_day_time(clubModel.getTraining_day_time()); + data.setContact(clubModel.getContact()); + + return data; + }).collect().asList(); + } } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/ClubEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/ClubEndpoints.java index e3e473c..3c49cd8 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/ClubEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/ClubEndpoints.java @@ -3,10 +3,7 @@ package fr.titionfire.ffsaf.rest; import fr.titionfire.ffsaf.data.model.ClubModel; import fr.titionfire.ffsaf.domain.service.ClubService; import fr.titionfire.ffsaf.net2.data.SimpleClubModel; -import fr.titionfire.ffsaf.rest.data.DeskMember; -import fr.titionfire.ffsaf.rest.data.RenewAffData; -import fr.titionfire.ffsaf.rest.data.SimpleClub; -import fr.titionfire.ffsaf.rest.data.SimpleClubList; +import fr.titionfire.ffsaf.rest.data.*; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.rest.exception.DInternalError; import fr.titionfire.ffsaf.rest.from.FullClubForm; @@ -315,4 +312,10 @@ public class ClubEndpoints { })); } + @GET + @Path("get_map_data") + public Uni> getMapData() { + return clubService.getMapData(); + } + } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/data/ClubMapData.java b/src/main/java/fr/titionfire/ffsaf/rest/data/ClubMapData.java new file mode 100644 index 0000000..01c030c --- /dev/null +++ b/src/main/java/fr/titionfire/ffsaf/rest/data/ClubMapData.java @@ -0,0 +1,27 @@ +package fr.titionfire.ffsaf.rest.data; + +import fr.titionfire.ffsaf.utils.Contact; +import io.quarkus.runtime.annotations.RegisterForReflection; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Data +@RegisterForReflection +public class ClubMapData { + public String name; + public String uuid; + public List training_location = new ArrayList<>(); + public String training_day_time; + public Map contact; + + @Data + @RegisterForReflection + public static class Location { + public double lat; + public double lng; + public String addr; + } +} diff --git a/src/main/webapp/public/club-maps.html b/src/main/webapp/public/club-maps.html new file mode 100644 index 0000000..f166e7c --- /dev/null +++ b/src/main/webapp/public/club-maps.html @@ -0,0 +1,22 @@ + + + + + Où pratiquer le MSF ? + + + + + + +
+ +
+ + + + \ No newline at end of file diff --git a/src/main/webapp/public/club-maps.js b/src/main/webapp/public/club-maps.js new file mode 100644 index 0000000..3cea2db --- /dev/null +++ b/src/main/webapp/public/club-maps.js @@ -0,0 +1,134 @@ +const div_map = document.getElementById('map'); +//const div_info = document.getElementById('club_map_data'); + +const api_url = "http://localhost:5173"; + +let map = L.map('map').setView([46.631196, 2.456000], 6); + +L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { + maxZoom: 19, + attribution: '© OpenStreetMap' +}).addTo(map); + +const getMeta = async (url) => { + const img = new Image(); + img.src = url; + await img.decode(); + return img +}; + +function timeNumberToSting(nbMin) { + return String(Math.floor(nbMin / 60)).padStart(2, '0') + ":" + String(nbMin % 60).padStart(2, '0') +} + +const sortHoraire = (a, b) => { + if (a.day === b.day) + return a.time_start - b.time_start; + return a.day - b.day; +} + +//let last_info_show = null; + +async function getData() { + const response = await fetch(`${api_url}/api/club/get_map_data`); + if (!response.ok) { + throw new Error(`Response status: ${response.status}`); + } + + const data = await response.json(); + for (const d of data) { + console.log(d); + + if (d.training_location.length === 0) + continue; + + let icon = null; + if (d.uuid !== null) { + console.log("logo"); + + const img = await getMeta(`http://localhost:5173/api/club/${d.uuid}/logo`); + let ratio = img.naturalHeight / img.naturalWidth; + + icon = L.icon({ + iconUrl: `http://localhost:5173/api/club/${d.uuid}/logo`, + + iconSize: [50, 50 * ratio], // size of the icon + //shadowSize: [50, 64], // size of the shadow + iconAnchor: [25, 50 * ratio], // point of the icon which will correspond to marker's location + //shadowAnchor: [4, 62], // the same for the shadow + popupAnchor: [0, -50 * ratio] // point from which the popup should open relative to the iconAnchor + }); + } + + for (const m of d.training_location) { + console.log(m); + let marker; + if (icon === null) + marker = L.marker([m.lat, m.lng]); + else + marker = L.marker([m.lat, m.lng], {icon: icon}); + marker.addTo(map); + + const div_info = document.createElement("div"); + let tmp = document.createElement("h3"); + tmp.textContent = d.name; + div_info.appendChild(tmp); + + div_info.appendChild(document.createTextNode(`Adresse: `)); + div_info.appendChild(document.createElement("br")); + for (const m of d.training_location) { + div_info.appendChild(document.createTextNode(m.addr)); + div_info.appendChild(document.createElement("br")); + } + div_info.appendChild(document.createElement("br")); + + div_info.appendChild(document.createTextNode(`Horaire: `)); + div_info.appendChild(document.createElement("br")); + if (!d.training_day_time || JSON.parse(d.training_day_time).length === 0) { + div_info.appendChild(document.createTextNode("Pas d'horaire disponible")); + div_info.appendChild(document.createElement("br")); + } else { + for (const m of JSON.parse(d.training_day_time).sort(sortHoraire)) { + console.log(m); + let days = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"]; + + div_info.appendChild(document.createTextNode(`${days[m.day]}: ${timeNumberToSting(m.time_start)} - ${timeNumberToSting(m.time_end)}`)); + div_info.appendChild(document.createElement("br")); + } + } + div_info.appendChild(document.createElement("br")); + + div_info.appendChild(document.createTextNode(`Contact: `)); + div_info.appendChild(document.createElement("br")); + if (d.contact === null || Object.keys(d.contact).length === 0) { + div_info.appendChild(document.createTextNode("Pas de contact disponible")); + div_info.appendChild(document.createElement("br")); + } else { + for (const [key, value] of Object.entries(d.contact)) { + div_info.appendChild(document.createTextNode(`${key.charAt(0).toUpperCase() + key.slice(1).toLowerCase()}: ${value}`)); + div_info.appendChild(document.createElement("br")); + } + } + marker.bindPopup(div_info.innerHTML); + + //marker.on('click', e => { + //console.log("click"); + //if (div_map.style.height !== "95vh" && last_info_show === d.name) { + //div_map.style.height = "95vh"; + //div_info.style.minHeight = "0"; + //div_info.replaceChildren(); + //} else { + //div_map.style.height = "80vh"; + //div_info.style.minHeight = "15vh"; + //div_info.replaceChildren(); + + //last_info_show = d.name; + //} + //}) + } + } +} + +getData().then(() => console.log("end loading")); + +console.log("test"); \ No newline at end of file