From 96429402fccca5a8b52c9b2a3eb6b4e065c99718 Mon Sep 17 00:00:00 2001 From: pprevautel Date: Fri, 12 Jul 2024 10:05:25 +0200 Subject: [PATCH] feat: mise en palce de l'outil de recherche --- assets/@types/app_espaceco.ts | 33 ++++++++ assets/@types/espaceco.ts | 2 +- assets/espaceco/api/community.ts | 4 +- .../pages/communities/ManageCommunity.tsx | 3 + .../pages/communities/SearchCommunity.tsx | 2 +- .../pages/communities/management/Search.tsx | 80 +++++++++++++++++++ .../management/ZoomAndCentering.tsx | 38 +++++++++ assets/i18n/i18n.ts | 3 +- assets/i18n/languages/en.tsx | 3 + assets/i18n/languages/fr.tsx | 3 + assets/modules/espaceco/RQKeys.ts | 5 +- .../SldStyleValidationErrorsTr.tsx | 2 +- 12 files changed, 170 insertions(+), 8 deletions(-) create mode 100644 assets/espaceco/pages/communities/management/Search.tsx create mode 100644 assets/espaceco/pages/communities/management/ZoomAndCentering.tsx diff --git a/assets/@types/app_espaceco.ts b/assets/@types/app_espaceco.ts index 0359da8f..65394f35 100644 --- a/assets/@types/app_espaceco.ts +++ b/assets/@types/app_espaceco.ts @@ -7,3 +7,36 @@ export type GetResponse = { export const arrCommunityListFilters = ["public", "iam_member", "affiliation"]; export type CommunityListFilter = (typeof arrCommunityListFilters)[number]; + +export type Address = { + country: string; + city: string; + x: number; + y: number; + zipcode: string; + street: string; + classification: number; + kind: string; + fulltext: string; + metropole: boolean; +}; + +export type Poi = { + country: string; + city: string; + x: number; + y: number; + zipcode: string; + zipcodes: string[]; + poiType: string[]; + street: string; + classification: number; + kind: string; + fulltext: string; + metropole: boolean; +}; + +export type SearchResult = { + status: string; + results: (Address | Poi)[]; +}; diff --git a/assets/@types/espaceco.ts b/assets/@types/espaceco.ts index f222de4a..6243f9e2 100644 --- a/assets/@types/espaceco.ts +++ b/assets/@types/espaceco.ts @@ -8,7 +8,7 @@ export interface CommunityResponseDTO { email: string | null; attributes: object[]; default_comment: string | null; - position: string; + position: string | null; zoom: number; all_members_can_valid: boolean; open_without_affiliation: boolean; diff --git a/assets/espaceco/api/community.ts b/assets/espaceco/api/community.ts index 4eaa8738..9249cffe 100644 --- a/assets/espaceco/api/community.ts +++ b/assets/espaceco/api/community.ts @@ -29,12 +29,12 @@ const getAsMember = (queryParams: Record, signal: AbortSignal) }; const getCommunity = (communityId: number) => { - const url = SymfonyRouting.generate("cartesgouvfr_api_espaceco_community_get_community", { communityId: communityId }); + const url = SymfonyRouting.generate("cartesgouvfr_api_espaceco_community_get_community", { communityId }); return jsonFetch(url); }; const updateLogo = (communityId: number, formData: FormData) => { - const url = SymfonyRouting.generate("cartesgouvfr_api_espaceco_community_update_logo", { communityId: communityId }); + const url = SymfonyRouting.generate("cartesgouvfr_api_espaceco_community_update_logo", { communityId }); return jsonFetch( url, { diff --git a/assets/espaceco/pages/communities/ManageCommunity.tsx b/assets/espaceco/pages/communities/ManageCommunity.tsx index 471d5b47..8adb9037 100644 --- a/assets/espaceco/pages/communities/ManageCommunity.tsx +++ b/assets/espaceco/pages/communities/ManageCommunity.tsx @@ -14,6 +14,7 @@ import Tabs from "@codegouvfr/react-dsfr/Tabs"; import Description from "./management/Description"; import { CommunityResponseDTO } from "../../../@types/espaceco"; import { CartesApiException } from "../../../modules/jsonFetch"; +import ZoomAndCentering from "./management/ZoomAndCentering"; type ManageCommunityProps = { communityId: number; @@ -69,6 +70,8 @@ const ManageCommunity: FC = ({ communityId }) => { switch (selectedTabId) { case "tab1": return ; + case "tab3": + return ; default: return

`Content of ${selectedTabId}`

; } diff --git a/assets/espaceco/pages/communities/SearchCommunity.tsx b/assets/espaceco/pages/communities/SearchCommunity.tsx index 7ea8ed44..ac2128d6 100644 --- a/assets/espaceco/pages/communities/SearchCommunity.tsx +++ b/assets/espaceco/pages/communities/SearchCommunity.tsx @@ -22,7 +22,7 @@ const SearchCommunity: FC = ({ filter, onChange }) => { const [search, setSearch] = useDebounceValue("", 500); const searchQuery = useQuery({ - queryKey: RQKeys.search(search, filter), + queryKey: RQKeys.searchCommunities(search, filter), queryFn: ({ signal }) => api.community.searchByName(search, filter, signal), enabled: search.length > 3, }); diff --git a/assets/espaceco/pages/communities/management/Search.tsx b/assets/espaceco/pages/communities/management/Search.tsx new file mode 100644 index 00000000..7bd8b599 --- /dev/null +++ b/assets/espaceco/pages/communities/management/Search.tsx @@ -0,0 +1,80 @@ +import { fr } from "@codegouvfr/react-dsfr"; +import MuiDsfrThemeProvider from "@codegouvfr/react-dsfr/mui"; +import Autocomplete from "@mui/material/Autocomplete"; +import TextField from "@mui/material/TextField"; +import { useQuery } from "@tanstack/react-query"; +import { declareComponentKeys } from "i18nifty"; +import { FC } from "react"; +import { useDebounceValue } from "usehooks-ts"; +import { SearchResult } from "../../../../@types/app_espaceco"; +import { Translations, useTranslation } from "../../../../i18n/i18n"; +import RQKeys from "../../../../modules/espaceco/RQKeys"; +import { jsonFetch } from "../../../../modules/jsonFetch"; + +type SearchProps = { + filter: Record; + onChange?: (value: string | null) => void; +}; + +const autocompleteUrl = "https://data.geopf.fr/geocodage/completion"; + +const Search: FC = ({ filter, onChange }) => { + const { t } = useTranslation("Search"); + + const [text, setText] = useDebounceValue("", 500); + + const searchQuery = useQuery({ + queryKey: RQKeys.searchAddress(text), + queryFn: ({ signal }) => { + const qParams = new URLSearchParams({ text: text, ...filter }).toString(); + return jsonFetch(`${autocompleteUrl}?${qParams}`, { signal }); + }, + enabled: text.length >= 3, + staleTime: 10 * 1000, + }); + console.log(searchQuery.data); + + return ( +
+ {t("position_hint")} + + option.fulltext} + options={searchQuery.data?.results ?? []} + renderInput={(params) => ( + + )} + isOptionEqualToValue={(option, v) => option.fulltext === v.fulltext} + onInputChange={(_, v) => setText(v)} + // onChange={(_, v) => onChange(v)} + /> + +
+ ); +}; + +export default Search; + +// traductions +export const { i18n } = declareComponentKeys<"position_hint" | "no_results" | "loading">()("Search"); + +export const SearchFrTranslations: Translations<"fr">["Search"] = { + position_hint: "Fixer la position et définissez le niveau de zoom (utilisez votre souris ou la barre de recherche ci-dessous", + no_results: "Aucun résultat", + loading: "Recherche en cours ...", +}; + +export const SearchEnTranslations: Translations<"en">["Search"] = { + position_hint: "Fix the position and set the zoom level (use your mouse or the search bar below", + no_results: "No results", + loading: "Searching ...", +}; diff --git a/assets/espaceco/pages/communities/management/ZoomAndCentering.tsx b/assets/espaceco/pages/communities/management/ZoomAndCentering.tsx new file mode 100644 index 00000000..2e2015a8 --- /dev/null +++ b/assets/espaceco/pages/communities/management/ZoomAndCentering.tsx @@ -0,0 +1,38 @@ +import { FC } from "react"; +import { CommunityResponseDTO } from "../../../../@types/espaceco"; +import WKT from "ol/format/WKT"; +import { fr } from "@codegouvfr/react-dsfr"; +import Input from "@codegouvfr/react-dsfr/Input"; +import { useTranslation } from "../../../../i18n/i18n"; +import Search from "./Search"; + +type ZoomAndCenteringProps = { + community: CommunityResponseDTO; +}; + +const ZoomAndCentering: FC = ({ community }) => { + let point; + if (community.position) { + const feature = new WKT().readFeature(community.position, { + dataProjection: "EPSG:4326", + }); + point = feature.getGeometry().getCoordinates(); + } + console.log(point); + + return ( +
+
+ {" "} +
+
+
+ ); +}; + +export default ZoomAndCentering; diff --git a/assets/i18n/i18n.ts b/assets/i18n/i18n.ts index 7eab0422..2c700584 100644 --- a/assets/i18n/i18n.ts +++ b/assets/i18n/i18n.ts @@ -52,7 +52,8 @@ export type ComponentKey = | typeof import("../entrepot/pages/service/wms-vector/UploadStyleFile").i18n | typeof import("../espaceco/pages/communities/CommunityListTr").i18n | typeof import("../espaceco/pages/communities/ManageCommunityTr").i18n - | typeof import("../espaceco/pages/communities/management/validationTr").i18n; + | typeof import("../espaceco/pages/communities/management/validationTr").i18n + | typeof import("../espaceco/pages/communities/management/Search").i18n; export type Translations = GenericTranslations; export type LocalizedString = Parameters[0]; diff --git a/assets/i18n/languages/en.tsx b/assets/i18n/languages/en.tsx index 97bc6053..0e7d0138 100644 --- a/assets/i18n/languages/en.tsx +++ b/assets/i18n/languages/en.tsx @@ -27,6 +27,7 @@ import { PermissionsEnTranslations } from "../../entrepot/pages/users/permission import { CommunityListEnTranslations } from "../../espaceco/pages/communities/CommunityListTr"; import { ManageCommunityEnTranslations } from "../../espaceco/pages/communities/ManageCommunityTr"; import { ManageCommunityValidationsEnTranslations } from "../../espaceco/pages/communities/management/validationTr"; +import { SearchEnTranslations } from "../../espaceco/pages/communities/management/Search"; import { TMSStyleFilesManagerEnTranslations } from "../../modules/Style/TMSStyleFilesManager"; import { contactEnTranslations } from "../../pages/assistance/contact/Contact"; import { mapboxStyleValidationEnTranslations } from "../../validations/MapboxStyleValidator"; @@ -35,6 +36,7 @@ import { BreadcrumbEnTranslations } from "../Breadcrumb"; import { commonEnTranslations } from "../Common"; import { RightsEnTranslations } from "../Rights"; import { StyleEnTranslations } from "../Style"; + import type { Translations } from "../i18n"; export const translations: Translations<"en"> = { @@ -75,4 +77,5 @@ export const translations: Translations<"en"> = { CommunityList: CommunityListEnTranslations, ManageCommunity: ManageCommunityEnTranslations, ManageCommunityValidations: ManageCommunityValidationsEnTranslations, + Search: SearchEnTranslations, }; diff --git a/assets/i18n/languages/fr.tsx b/assets/i18n/languages/fr.tsx index de206d00..c7da52d4 100644 --- a/assets/i18n/languages/fr.tsx +++ b/assets/i18n/languages/fr.tsx @@ -27,6 +27,7 @@ import { PermissionsFrTranslations } from "../../entrepot/pages/users/permission import { CommunityListFrTranslations } from "../../espaceco/pages/communities/CommunityListTr"; import { ManageCommunityFrTranslations } from "../../espaceco/pages/communities/ManageCommunityTr"; import { ManageCommunityValidationsFrTranslations } from "../../espaceco/pages/communities/management/validationTr"; +import { SearchEnTranslations, SearchFrTranslations } from "../../espaceco/pages/communities/management/Search"; import { TMSStyleFilesManagerFrTranslations } from "../../modules/Style/TMSStyleFilesManager"; import { contactFrTranslations } from "../../pages/assistance/contact/Contact"; import { mapboxStyleValidationFrTranslations } from "../../validations/MapboxStyleValidator"; @@ -35,6 +36,7 @@ import { BreadcrumbFrTranslations } from "../Breadcrumb"; import { commonFrTranslations } from "../Common"; import { RightsFrTranslations } from "../Rights"; import { StyleFrTranslations } from "../Style"; + import type { Translations } from "../i18n"; export const translations: Translations<"fr"> = { @@ -75,4 +77,5 @@ export const translations: Translations<"fr"> = { CommunityList: CommunityListFrTranslations, ManageCommunity: ManageCommunityFrTranslations, ManageCommunityValidations: ManageCommunityValidationsFrTranslations, + Search: SearchFrTranslations, }; diff --git a/assets/modules/espaceco/RQKeys.ts b/assets/modules/espaceco/RQKeys.ts index 5dae8416..0262a072 100644 --- a/assets/modules/espaceco/RQKeys.ts +++ b/assets/modules/espaceco/RQKeys.ts @@ -3,8 +3,8 @@ import { CommunityListFilter } from "../../@types/app_espaceco"; const RQKeys = { community: (communityId: number): string[] => ["community", communityId.toString()], community_list: (page: number, limit: number): string[] => ["communities", page.toString(), limit.toString()], - search: (search: string, filter: CommunityListFilter): string[] => { - return ["search", "community", filter, search]; + searchCommunities: (search: string, filter: CommunityListFilter): string[] => { + return ["searchCommunities", filter, search]; }, communities_as_member: (pending: boolean, page: number, limit: number): string[] => [ "communities_as_member", @@ -12,6 +12,7 @@ const RQKeys = { page.toString(), limit.toString(), ], + searchAddress: (search: string): string[] => ["searchAddress", search], }; export default RQKeys; diff --git a/assets/validations/SldStyleValidationErrorsTr.tsx b/assets/validations/SldStyleValidationErrorsTr.tsx index d9c23540..a4700b30 100644 --- a/assets/validations/SldStyleValidationErrorsTr.tsx +++ b/assets/validations/SldStyleValidationErrorsTr.tsx @@ -1,4 +1,4 @@ -import { declareComponentKeys } from "i18nifty/declareComponentKeys"; +import { declareComponentKeys } from "i18nifty"; import { Translations } from "../i18n/i18n"; export const { i18n } = declareComponentKeys<