diff --git a/packages/frontend/src/features/menu/ClauseMenu.tsx b/packages/frontend/src/features/menu/ClauseMenu.tsx index eeec2809..4034068c 100644 --- a/packages/frontend/src/features/menu/ClauseMenu.tsx +++ b/packages/frontend/src/features/menu/ClauseMenu.tsx @@ -7,13 +7,15 @@ import { Divider, Flex, Stack, styled } from "#styled-system/jsx"; import { Fragment } from "react/jsx-runtime"; import { MenuTitle } from "./MenuTitle"; import type { ModalContentProps } from "./MenuButton"; -import { useEffect, useState } from "react"; +import { ReactNode, useEffect, useState } from "react"; import Button from "@codegouvfr/react-dsfr/Button"; import { css } from "#styled-system/css"; import { Clause_v2 } from "@cr-vif/electric-client/frontend"; import Input from "@codegouvfr/react-dsfr/Input"; import { FormProvider, useFieldArray, useForm, useFormContext } from "react-hook-form"; import { useMutation } from "@tanstack/react-query"; +import Select from "@codegouvfr/react-dsfr/Select"; +import { v4 } from "uuid"; export const ClauseMenu = ({ isNational, ...props }: { isNational: boolean } & ModalContentProps) => { const user = useUser()!; @@ -31,6 +33,14 @@ export const ClauseMenu = ({ isNational, ...props }: { isNational: boolean } & M if (!clausesQuery.updatedAt) return ; + if (isNational) + return ( + <> + + + + ); + return ( ({ ...c, text: c.text?.replaceAll("\\n", "\n") ?? "" })) ?? []} @@ -54,13 +64,17 @@ const getDiff = (baseClauses: Clause_v2[], modifiedClauses: Clause_v2[]) => { return { newClauses: newClauses, updatedClauses: updatedClauses, deletedClauses }; }; +type Mode = "view" | "add" | "edit"; const ClauseForm = ({ clauses, isNational, ...props }: { clauses: Clause_v2[]; isNational: boolean } & ModalContentProps) => { - const [isEditing, setIsEditing] = useState(false); + const [mode, setMode] = useState("view"); + + const isEditing = mode === "edit"; + const isAdding = mode === "add"; const form = useForm
({ defaultValues: { @@ -75,6 +89,7 @@ const ClauseForm = ({ const { fields } = useFieldArray({ name: "clauses", control: form.control, + keyName: "_id", }); const applyDiffMutation = useMutation( @@ -87,7 +102,7 @@ const ClauseForm = ({ } }, { - onSuccess: () => setIsEditing(false), + onSuccess: () => setMode("view"), }, ); @@ -97,70 +112,107 @@ const ClauseForm = ({ }; const fieldsWithIndex = fields.map((field, index) => ({ ...field, _index: index })); - const groupedByKey = groupBy(fieldsWithIndex, "key"); - const buttons = isEditing ? ( - <> - - - ) : ( + const buttons = + isEditing || isAdding ? ( + <> + + + ) : ( + <> + + + + ); + + return ( <> - + + {isAdding ? setMode("view")} isNational={isNational} /> : null} + + + + + ); +}; + +const ClauseTitle = ({ + isNational, + buttons, + ...props +}: { isNational: boolean; buttons?: ReactNode; isEditing?: boolean } & ModalContentProps) => ( + + Clauses {isNational ? "nationales" : "départementales"} + +); + +const ClauseList = ({ clauses, isEditing }: { clauses: ClauseWithIndex[]; isEditing: boolean }) => { + const groupedByKey = groupBy(clauses, "key"); return ( - -
- {buttons}}> - Clauses {isNational ? "nationales" : "départementales"} - - - {Object.entries(groupedByKey).map(([key, clauses], index) => ( - - - - {(clauseNameMap as any)[key] ?? key} - - {clauses.map((clause) => ( - - ))} - - {index < Object.keys(groupedByKey).length - 1 && } - - ))} - -
-
+ + {Object.entries(groupedByKey).map(([key, clauses], index) => ( + + + {(clauseNameMap as any)[key] ?? key} + {clauses.map((clause) => ( + + ))} + + {index < Object.keys(groupedByKey).length - 1 && } + + ))} + ); }; @@ -191,11 +243,32 @@ const ClauseView = ({ clause }: { clause: ClauseWithIndex }) => { const ClauseEdit = ({ clause }: { clause: ClauseWithIndex }) => { const form = useFormContext
(); + const deleteClauseMutation = useMutation( + async () => { + await db.clause_v2.delete({ where: { id: clause.id } }); + }, + { + onSuccess: () => {}, + }, + ); + return ( - - {clause.value} - + + + {clause.value} + + + { ); }; +const ClauseAdd = ({ onSuccess, isNational }: { onSuccess: () => void; isNational: boolean }) => { + const user = useUser()!; + const form = useForm({ + defaultValues: { key: "", value: "", text: "", id: v4(), udap_id: isNational ? "ALL" : user.udap_id }, + }); + const keyOptions = Object.entries(clauseNameMap) + .map(([key, label]) => ({ value: key, label })) + .filter(({ value }) => { + const isNationalClause = nationalClauses.includes(value); + return isNational ? isNationalClause : !isNationalClause; + }); + + const addClauseMutation = useMutation( + async (clause: Clause_v2) => { + await db.clause_v2.create({ data: clause }); + }, + { + onSuccess, + }, + ); + + return ( + addClauseMutation.mutate(data))} id="add-form"> + + + + + + + + + ); +}; + +const nationalClauses = ["type-espace", "decision"]; + const clauseNameMap = { "type-espace": "Type d'espace", decision: "Décision", diff --git a/packages/frontend/src/features/menu/MenuTitle.tsx b/packages/frontend/src/features/menu/MenuTitle.tsx index e70769e5..4c62675c 100644 --- a/packages/frontend/src/features/menu/MenuTitle.tsx +++ b/packages/frontend/src/features/menu/MenuTitle.tsx @@ -31,9 +31,9 @@ export const MenuTitle = ({ > {children} - + {buttons} - +