diff --git a/components/bal/commune-editor.tsx b/components/bal/commune-editor.tsx new file mode 100644 index 00000000..b992c895 --- /dev/null +++ b/components/bal/commune-editor.tsx @@ -0,0 +1,132 @@ +import { useState, useContext, useCallback, useEffect } from "react"; +import { Pane, Button, Label } from "evergreen-ui"; + +import BalDataContext from "@/contexts/bal-data"; + +import useValidationMessage from "@/hooks/validation-messages"; + +import Form from "@/components/form"; +import FormInput from "@/components/form-input"; +import LanguesRegionalesForm from "@/components/langues-regionales-form"; +import { + BaseLocale, + BasesLocalesService, + UpdateBaseLocaleDTO, +} from "@/lib/openapi-api-bal"; +import LayoutContext from "@/contexts/layout"; + +interface CommuneEditorProps { + initialValue?: BaseLocale; + closeForm: () => void; + onSubmitted?: () => void; +} + +function CommuneEditor({ initialValue, closeForm }: CommuneEditorProps) { + const [isLoading, setIsLoading] = useState(false); + const [communeNomsAlt, setCommuneNomsAlt] = useState( + initialValue?.communeNomsAlt + ); + const { reloadBaseLocale } = useContext(BalDataContext); + const { getValidationMessage, setValidationMessages } = + useValidationMessage(); + const { toaster } = useContext(LayoutContext); + + const onFormSubmit = useCallback( + async (e) => { + e.preventDefault(); + setValidationMessages(null); + setIsLoading(true); + + try { + const body: UpdateBaseLocaleDTO = { + communeNomsAlt: + Object.keys(communeNomsAlt).length > 0 ? communeNomsAlt : null, + }; + + const submit = toaster( + async () => + BasesLocalesService.updateBaseLocale(initialValue.id, body), + "Le nom de la commune en langue régional a bien été modifié", + "Le nom de la commune en langue régional n’a pas pu être modifiée", + (err) => { + setValidationMessages(err.body.message); + } + ); + + await submit(); + await reloadBaseLocale(); + closeForm(); + } catch (err) { + console.error(err); + } finally { + setIsLoading(false); + } + }, + [ + initialValue, + communeNomsAlt, + closeForm, + setValidationMessages, + toaster, + reloadBaseLocale, + ] + ); + + const onFormCancel = useCallback( + (e) => { + e.preventDefault(); + closeForm(); + }, + [closeForm] + ); + + // Reset validation messages on changes + useEffect(() => { + setValidationMessages(null); + }, [communeNomsAlt, setValidationMessages]); + + return ( +
+ + + + + + + + + + + {closeForm && ( + + )} + +
+ ); +} + +export default CommuneEditor; diff --git a/components/bal/toponyme-editor.tsx b/components/bal/toponyme-editor.tsx index f7bd912e..804ad50a 100644 --- a/components/bal/toponyme-editor.tsx +++ b/components/bal/toponyme-editor.tsx @@ -219,7 +219,7 @@ function ToponymeEditor({ diff --git a/components/bal/voie-editor.tsx b/components/bal/voie-editor.tsx index 38e85d83..6b9f4a9c 100644 --- a/components/bal/voie-editor.tsx +++ b/components/bal/voie-editor.tsx @@ -203,7 +203,7 @@ function VoieEditor({ diff --git a/components/langues-regionales-form/index.tsx b/components/langues-regionales-form/index.tsx index 43db64d7..7719bef5 100644 --- a/components/langues-regionales-form/index.tsx +++ b/components/langues-regionales-form/index.tsx @@ -1,10 +1,11 @@ -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useContext, useEffect, useState } from "react"; import { reduce, uniqueId } from "lodash"; -import { Button, AddIcon } from "evergreen-ui"; +import { Button, AddIcon, Text, ErrorIcon, Pane } from "evergreen-ui"; import languesRegionales from "@ban-team/shared-data/langues-regionales.json"; import LanguageField from "./language-field"; +import BalDataContext from "@/contexts/bal-data"; function objectToArray(obj) { if (obj) { @@ -25,21 +26,43 @@ function languagesArrayToObj(arr) { ); } +function getInitialValue(initialValue: any, autoOpen: boolean) { + if (initialValue) { + return objectToArray(initialValue); + } else if (autoOpen) { + return [{ code: "", value: "", id: uniqueId() }]; + } + return []; +} + interface LanguesRegionalesFormProps { initialValue?: any; validationMessage?: string; handleLanguages: (value: any) => void; + autoOpen?: boolean; } function LanguesRegionalesForm({ initialValue, validationMessage, handleLanguages, + autoOpen = false, }: LanguesRegionalesFormProps) { - const [nomAlt, setNomAlt] = useState(objectToArray(initialValue)); + const { baseLocale } = useContext(BalDataContext); + const [nomAlt, setNomAlt] = useState(getInitialValue(initialValue, autoOpen)); const onAddForm = () => { - setNomAlt((prev) => [...prev, { code: null, value: "", id: uniqueId() }]); + let code: string = null; + if ( + baseLocale.communeNomsAlt && + Object.keys(baseLocale.communeNomsAlt).length > 0 && + !nomAlt.some( + ({ code }) => code === Object.keys(baseLocale.communeNomsAlt)[0] + ) + ) { + code = Object.keys(baseLocale.communeNomsAlt)[0]; + } + setNomAlt((prev) => [...prev, { code, value: "", id: uniqueId() }]); }; const onLanguageChange = useCallback( @@ -77,7 +100,6 @@ function LanguesRegionalesForm({ availableLanguages={languesRegionales.filter( ({ code }) => !nomAlt.map(({ code }) => code).includes(code) )} - validationMessage={validationMessage} onChange={(value) => onLanguageChange(value, language.id)} onDelete={() => onRemoveLanguage(language.id)} /> @@ -95,6 +117,20 @@ function LanguesRegionalesForm({ > Ajouter une langue régionale + + + {validationMessage && ( + + + {validationMessage} + + )} + ); } diff --git a/components/langues-regionales-form/language-field.tsx b/components/langues-regionales-form/language-field.tsx index 048f5cdb..2b5392d6 100644 --- a/components/langues-regionales-form/language-field.tsx +++ b/components/langues-regionales-form/language-field.tsx @@ -21,7 +21,6 @@ interface LanguageFieldProps { value: string; }; availableLanguages: Array<{ code: string; label: string }>; - validationMessage: string; onChange: (value: { code: string; value: string }) => void; onDelete: (code: string) => void; } @@ -29,7 +28,6 @@ interface LanguageFieldProps { function LanguageField({ initialValue, availableLanguages, - validationMessage, onChange, onDelete, }: LanguageFieldProps) { @@ -105,7 +103,6 @@ function LanguageField({ isRequired={false} placeholder={`Nom en ${codeISO ? languageLabel : "langue régionale"}`} value={input} - validationMessage={validationMessage} onChange={handleLanguageChange} isDisabled={!codeISO} /> diff --git a/components/sidebar/header.tsx b/components/sidebar/header.tsx index 3e6d3dd9..ad2e6638 100644 --- a/components/sidebar/header.tsx +++ b/components/sidebar/header.tsx @@ -1,20 +1,51 @@ -import React from "react"; -import { Heading, Pane, Text } from "evergreen-ui"; +import React, { useContext } from "react"; +import { + Button, + EditIcon, + Heading, + IconButton, + Pane, + Text, +} from "evergreen-ui"; -import { ExtendedVoieDTO } from "@/lib/openapi-api-bal"; +import { BaseLocale, ExtendedVoieDTO } from "@/lib/openapi-api-bal"; import { CommuneType } from "@/types/commune"; +import LanguagePreview from "../bal/language-preview"; +import TokenContext from "@/contexts/token"; +import BalDataContext from "@/contexts/bal-data"; interface HeaderSideBarProps { + baseLocale: BaseLocale; commune: CommuneType; voies: ExtendedVoieDTO[]; + openForm: () => void; } -function HeaderSideBar({ commune, voies }: HeaderSideBarProps) { +function HeaderSideBar({ + baseLocale, + commune, + voies, + openForm, +}: HeaderSideBarProps) { + const { token } = useContext(TokenContext); + const { editingId, isEditing, numeros } = useContext(BalDataContext); return ( {commune.nom} - {commune.code} + {!isEditing && token && ( + + )} + {baseLocale.communeNomsAlt && ( + + )} {voies && ( {voies.length} voie{voies.length > 1 ? "s" : ""} diff --git a/lib/openapi-api-bal/models/BaseLocale.ts b/lib/openapi-api-bal/models/BaseLocale.ts index fc65dc2a..15b6a90f 100644 --- a/lib/openapi-api-bal/models/BaseLocale.ts +++ b/lib/openapi-api-bal/models/BaseLocale.ts @@ -15,6 +15,7 @@ export type BaseLocale = { updatedAt: string; deletedAt: string; nom: string; + communeNomsAlt: Record; commune: string; emails: Array; token: string; diff --git a/lib/openapi-api-bal/models/ExtendedBaseLocaleDTO.ts b/lib/openapi-api-bal/models/ExtendedBaseLocaleDTO.ts index 7eeb47a3..3cb72759 100644 --- a/lib/openapi-api-bal/models/ExtendedBaseLocaleDTO.ts +++ b/lib/openapi-api-bal/models/ExtendedBaseLocaleDTO.ts @@ -15,6 +15,7 @@ export type ExtendedBaseLocaleDTO = { updatedAt: string; deletedAt: string; nom: string; + communeNomsAlt: Record; commune: string; emails: Array; token: string; diff --git a/lib/openapi-api-bal/models/UpdateBaseLocaleDTO.ts b/lib/openapi-api-bal/models/UpdateBaseLocaleDTO.ts index 9e7f4ad7..1f894963 100644 --- a/lib/openapi-api-bal/models/UpdateBaseLocaleDTO.ts +++ b/lib/openapi-api-bal/models/UpdateBaseLocaleDTO.ts @@ -5,6 +5,7 @@ export type UpdateBaseLocaleDTO = { nom?: string; + communeNomsAlt?: Record | null; emails?: Array; }; diff --git a/pages/bal/[balId]/index.tsx b/pages/bal/[balId]/index.tsx index dbdab0a0..8c5ccdc4 100644 --- a/pages/bal/[balId]/index.tsx +++ b/pages/bal/[balId]/index.tsx @@ -33,6 +33,7 @@ import MapContext from "@/contexts/map"; import LayoutContext from "@/contexts/layout"; import ToponymesList from "@/components/bal/toponymes-list"; import ConvertVoieWarning from "@/components/convert-voie-warning"; +import CommuneEditor from "@/components/bal/commune-editor"; interface BaseLocalePageProps { selectedTab: TabsEnum; @@ -41,6 +42,7 @@ interface BaseLocalePageProps { function BaseLocalePage({ commune }: BaseLocalePageProps) { const [editedItem, setEditedItem] = useState(null); + const [isCommuneFormOpen, setIsCommuneFormOpen] = useState(false); const [isFormOpen, setIsFormOpen] = useState(false); const [toConvert, setToConvert] = useState(null); const [onConvertLoading, setOnConvertLoading] = useState(false); @@ -174,7 +176,14 @@ function BaseLocalePage({ commune }: BaseLocalePageProps) { }} onConfirm={onConvert} /> - + { + setIsCommuneFormOpen(true); + }} + /> + {isCommuneFormOpen && ( + { + setIsCommuneFormOpen(false); + }} + /> + )} + {isFormOpen && selectedTab === TabsEnum.VOIES && (