diff --git a/src/pages/ContactPage.tsx b/src/pages/ContactPage.tsx index 2894c8b..66986e3 100644 --- a/src/pages/ContactPage.tsx +++ b/src/pages/ContactPage.tsx @@ -9,20 +9,17 @@ import { Breadcrumbs } from "../ui/Breadcrumbs.tsx"; import { ContactInfosTab } from "./Contact/ContactInfosTab.tsx"; import { PageTab } from "../ui/PageTab.tsx"; import { ContactSurveysContent } from "../ui/Contact/ContactSurveys.tsx"; -import { IdsManagement } from "../ui/Contact/IdsManagement.tsx"; import { RightsManagement } from "../ui/Contact/RightsManagement.tsx"; enum Tab { Infos = "Infos", Surveys = "Surveys", - Ids = "Ids", Permissions = "Permissions", } const TabNames = { [Tab.Infos]: "Infos contact", [Tab.Surveys]: "Questionnaire(s)", - [Tab.Ids]: "Gestion des identifiants", [Tab.Permissions]: "Gestion des droits", }; @@ -78,11 +75,10 @@ export function ContactPage() { ))} - + {currentTab === Tab.Infos && } {currentTab === Tab.Surveys && } - {currentTab === Tab.Ids && } {currentTab === Tab.Permissions && } diff --git a/src/pages/CreateContactPage.tsx b/src/pages/CreateContactPage.tsx index 7596c75..40ed9d2 100644 --- a/src/pages/CreateContactPage.tsx +++ b/src/pages/CreateContactPage.tsx @@ -1,3 +1,115 @@ +import Stack from "@mui/material/Stack"; +import { useState } from "react"; +import { Row } from "../ui/Row"; +import PersonAddAltOutlinedIcon from "@mui/icons-material/PersonAddAltOutlined"; +import Typography from "@mui/material/Typography"; +import { Step, StepLabel, Stepper, Divider, Card, CircularProgress } from "@mui/material"; +import { InformationsForm } from "../ui/Contact/CreateContact/InformationsForm"; +import { RightsManagementForm } from "../ui/Contact/CreateContact/RightsManagementForm"; +import { Breadcrumbs } from "../ui/Breadcrumbs"; +import { useLocation } from "react-router-dom"; +import { useFetchQuery } from "../hooks/useFetchQuery"; +const steps = ["Informations du contact", "Gestion des droits"]; + export const CreateContactPage = () => { - return <>Page create contact; + const { state: surveyUnitId } = useLocation(); + const [activeStep, setActiveStep] = useState(0); + const [contactData, setContactData] = useState(); + + const [rights, setRights] = useState<{ + idSource?: string; + year?: string; + periodicity?: string; + }>({ + idSource: undefined, + year: undefined, + periodicity: undefined, + }); + + const { + data: surveyUnit, + isLoading, + isSuccess, + } = useFetchQuery("/api/survey-units/{id}", { + urlParams: { + id: surveyUnitId, + }, + }); + + if (isLoading) { + return ( + + + + ); + } + + const handleNext = () => { + setActiveStep(prevActiveStep => prevActiveStep + 1); + }; + + const handleBack = () => { + setActiveStep(prevActiveStep => prevActiveStep - 1); + }; + + const handleSubmitStep = async (data: any) => { + if (activeStep === 0) { + setContactData(data); + } + + if (activeStep === 1) { + setRights(data); + } + + handleNext(); + }; + + const breadcrumbs = [ + { href: "/", title: "Accueil" }, + { href: "/search", title: "Recherche" }, + "Nouveau contact", + ]; + + return ( + + + + + + + + Nouveau contact + + + + {steps.map(label => { + return ( + + {label} + + ); + })} + + + + + {activeStep === 0 && ( + + )} + + {activeStep === 1 && ( + + )} + + + + ); }; diff --git a/src/routes.tsx b/src/routes.tsx index fbe5ecc..1c0dcac 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -13,6 +13,7 @@ import { SurveyUnitPage } from "./pages/SurveyUnitPage.tsx"; import { CreateContactPage } from "./pages/CreateContactPage.tsx"; import { UnauthorizedPage } from "./pages/UnauthorizedPage.tsx"; import { LogoutPage } from "./pages/Logout.tsx"; +import { AddRightsManagement } from "./ui/Contact/AddRightsManagement.tsx"; export const routes: RouteObject[] = [ { @@ -43,10 +44,14 @@ export const routes: RouteObject[] = [ ], }, { path: "surveys/:id", element: }, - { path: "contacts/:id", element: }, + { + path: "contacts/:id", + element: , + }, + { path: "contacts/:id/rights-management", element: }, + { path: "contacts/create-contact", element: }, { path: "survey-units/:id", element: }, { path: "reglages", element: }, - { path: "contacts/createContact", element: }, { path: "", element: }, ], }, diff --git a/src/theme.tsx b/src/theme.tsx index fd5e429..8572aa8 100644 --- a/src/theme.tsx +++ b/src/theme.tsx @@ -100,6 +100,7 @@ declare module "@mui/material/InputBase" { declare module "@mui/material/SvgIcon" { interface SvgIconPropsSizeOverrides { cardMedia: true; + headerNewContact: true; tabTitle: true; headerSinglePage: true; cardTitle: true; @@ -281,6 +282,12 @@ export const theme = createTheme({ fontSize: 60, }, }, + { + props: { fontSize: "headerNewContact" }, + style: { + fontSize: 40, + }, + }, { props: { fontSize: "tabTitle" }, style: { diff --git a/src/ui/Contact/AddRightsManagement.tsx b/src/ui/Contact/AddRightsManagement.tsx new file mode 100644 index 0000000..b74158b --- /dev/null +++ b/src/ui/Contact/AddRightsManagement.tsx @@ -0,0 +1,69 @@ +import Card from "@mui/material/Card"; +import { TitleWithIconAndDivider } from "../TitleWithIconAndDivider"; +import { BinocularIcon } from "../Icon/BinocularIcon"; +import { Row } from "../Row"; +import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; +import { CircularProgress, Divider, Typography } from "@mui/material"; +import { Stack } from "@mui/system"; +import GroupAddOutlinedIcon from "@mui/icons-material/GroupAddOutlined"; +import { AssociateSurveysTable } from "./AssociateSurveysTable"; +import LibraryAddOutlinedIcon from "@mui/icons-material/LibraryAddOutlined"; +import { useParams } from "react-router-dom"; +import { useFetchQuery } from "../../hooks/useFetchQuery"; +import { ContactHeader } from "./ContactHeader"; +import { AssociateAnotherAccount } from "./AssociateAnotherAccount"; +import { AddRightsForm } from "./AddRightsForm"; + +export const AddRightsManagement = () => { + const { id } = useParams(); + const { data: contact } = useFetchQuery("/api/contacts/{id}", { + urlParams: { + id: id!, + }, + }); + + if (!contact) { + return ( + + + + ); + } + return ( + <> + + + + + + + + + La liste des questionnaires auxquelles le répondant peut accéder avec son identifiant{" "} + {id} peut être élargie à des questionnaires rattachés à son adresse + courriel et figurant dans la liste ci-dessous + + + + + + + + + + + + + + + ); +}; diff --git a/src/ui/Contact/AssociateSurveysTable.tsx b/src/ui/Contact/AssociateSurveysTable.tsx index 6da38be..e99aeee 100644 --- a/src/ui/Contact/AssociateSurveysTable.tsx +++ b/src/ui/Contact/AssociateSurveysTable.tsx @@ -7,7 +7,6 @@ import TableCell from "@mui/material/TableCell"; import TableBody from "@mui/material/TableBody"; import Checkbox from "@mui/material/Checkbox"; import { useState } from "react"; -import Box from "@mui/system/Box"; import Button from "@mui/material/Button"; import TableFooter from "@mui/material/TableFooter"; import { LoadingCell } from "./ContactSurveysTable"; @@ -60,60 +59,58 @@ export const AssociateSurveysTable = () => { console.log(selectedIds); }; return ( - - - - - - {surveysMock.map(survey => { - return ( - - {columns.map(column => { - const value = survey[column.id as keyof typeof survey]; + +
+ + + {surveysMock.map(survey => { + return ( + + {columns.map(column => { + const value = survey[column.id as keyof typeof survey]; - if (column.id === "action") { - return ( - - onChange(survey.id)} - /> - - ); - } + if (column.id === "action") { + return ( + + onChange(survey.id)} + /> + + ); + } - if (column.id === "role") { - return ( - - {value} - - ); - } + if (column.id === "role") { + return ( + + {value} + + ); + } - return {value ?? "NO DATA"}; - })} - - ); - })} - {isLoading && } - - - - - - - - -
-
-
+ return {value ?? "NO DATA"}; + })} + + ); + })} + {isLoading && } + + + + + + + + + + ); }; diff --git a/src/ui/Contact/ContactFormDialog.tsx b/src/ui/Contact/ContactFormDialog.tsx index d5de938..89bb5e2 100644 --- a/src/ui/Contact/ContactFormDialog.tsx +++ b/src/ui/Contact/ContactFormDialog.tsx @@ -1,5 +1,5 @@ import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Divider } from "@mui/material"; -import { z } from "zod"; +import { Schema, z } from "zod"; import { useForm } from "../../hooks/useForm.ts"; import { APISchemas } from "../../types/api.ts"; import { Field } from "../Form/Field.tsx"; @@ -8,6 +8,8 @@ import { Row } from "../Row.tsx"; import StarIcon from "@mui/icons-material/Star"; import { useFetchMutation } from "../../hooks/useFetchQuery.ts"; import { AddressFormFields } from "../Form/AddressFormFields.tsx"; +import { UseFormRegister, UseFormReturn } from "react-hook-form"; +import { theme } from "../../theme.tsx"; type Props = { open: boolean; @@ -22,40 +24,45 @@ export const addressSchema = z repetitionIndex: z .string() .nullable() - .transform(val => (val === null ? "" : val)) + .transform(val => val ?? "") .optional(), streetType: z .string() .nullable() - .transform(val => (val === null ? "" : val)) + .transform(val => val ?? "") .optional(), - streetName: z.string().optional(), + streetName: z + .string() + .optional() + .transform(val => val ?? ""), addressSupplement: z .string() .nullable() - .transform(val => (val === null ? "" : val)) + .transform(val => val ?? "") .optional(), specialDistribution: z .string() .nullable() - .transform(val => (val === null ? "" : val)) + .transform(val => val ?? "") .optional(), cedexName: z .string() + .optional() .nullable() - .transform(val => (val === null ? "" : val)), + .transform(val => val ?? ""), cedexCode: z .string() + .optional() .nullable() - .transform(val => (val === null ? "" : val)), + .transform(val => val ?? ""), cityName: z .string() .nullable() - .transform(val => (val === null ? "" : val)), + .transform(val => val ?? ""), zipCode: z .string() .nullable() - .transform(val => (val === null ? "" : val)), + .transform(val => val ?? ""), countryName: z.string().optional().or(z.literal("")), }) .superRefine(({ cedexCode, zipCode, cityName, cedexName }, refinementContext) => { @@ -115,7 +122,7 @@ export const addressSchema = z } }); -const schema = z.object({ +export const schema = z.object({ civility: z.enum(["Female", "Male", "Undefined"]), lastName: z.string().min(3), firstName: z.string().min(3), @@ -124,7 +131,7 @@ const schema = z.object({ phone: z .string() .nullable() - .transform(val => (val === null ? "" : val)) + .transform(val => val ?? "") .optional(), secondPhone: z.string().optional().or(z.literal("")), identificationName: z.string().optional(), @@ -132,7 +139,7 @@ const schema = z.object({ address: addressSchema, }); -const civilities = [ +export const civilities = [ { label: "Madame", value: "Female" }, { label: "Monsieur", value: "Male" }, ]; @@ -152,7 +159,7 @@ export const styles = { export const ContactFormDialog = ({ open, onClose, contact, onSave }: Props) => { const defaultValues = contact.address?.countryName ? contact - : { ...contact, address: { ...contact.address, countryName: "France" } }; + : { ...contact, address: { ...contact.address, countryName: "FRANCE" } }; const { register, control, errors, handleSubmit, reset } = useForm(schema, { defaultValues: defaultValues, }); @@ -179,47 +186,18 @@ export const ContactFormDialog = ({ open, onClose, contact, onSave }: Props) => Modification des coordonnées - - - - - - - - - - - - - - - + - + + + @@ -234,3 +212,46 @@ export const ContactFormDialog = ({ open, onClose, contact, onSave }: Props) => ); }; + +type ContactInformationFormProps = { + errors: any; + register: UseFormRegister>; + control: UseFormReturn["control"]; +}; + +export const ContactInformationForm = ({ errors, register, control }: ContactInformationFormProps) => { + return ( + + + + + + + + + + + + + + + + ); +}; diff --git a/src/ui/Contact/ContactRightsDeleteDialog.tsx b/src/ui/Contact/ContactRightsDeleteDialog.tsx index e53145e..28752a5 100644 --- a/src/ui/Contact/ContactRightsDeleteDialog.tsx +++ b/src/ui/Contact/ContactRightsDeleteDialog.tsx @@ -1,4 +1,3 @@ -import { useNavigate } from "react-router-dom"; import { DeletePrimaryWithoutSecondaryDialog, DeleteSecondaryContactRightsDialog, @@ -7,14 +6,6 @@ import { import { DialogProps } from "./ContactRightsEditDialog"; export const ContactRightsDeleteDialog = ({ survey, contact, onAlert, onClose }: DialogProps) => { - const navigate = useNavigate(); - - const onDeletePrimaryContact = (selectedContact: string) => { - if (selectedContact === "newContact") { - navigate("/contacts/createContact"); - } - }; - if (survey.main === false) { return ( ); }; diff --git a/src/ui/Contact/ContactRightsDialogs.tsx b/src/ui/Contact/ContactRightsDialogs.tsx index 3476510..4d5cb34 100644 --- a/src/ui/Contact/ContactRightsDialogs.tsx +++ b/src/ui/Contact/ContactRightsDialogs.tsx @@ -1,6 +1,5 @@ import Typography from "@mui/material/Typography"; import { FormDialog } from "./FormDialog"; -import { useNavigate } from "react-router-dom"; import Stack from "@mui/material/Stack"; import { FormEventHandler, useState } from "react"; import FormControl from "@mui/material/FormControl"; @@ -8,6 +7,8 @@ import RadioGroup from "@mui/material/RadioGroup"; import FormControlLabel from "@mui/material/FormControlLabel"; import Radio from "@mui/material/Radio"; import { APISchemas } from "../../types/api"; +import { useToggle } from "react-use"; +import { CreateContactDialog } from "./CreateContact/CreateContactDialog"; export type CommonContactRightsProps = { open: boolean; @@ -55,20 +56,18 @@ export const DeleteSecondaryContactRightsDialog = ({ }; export const DeletePrimaryWithoutSecondaryDialog = ({ open, onClose }: CommonContactRightsProps) => { - const navigate = useNavigate(); + const [hasDialog, toggleDialog] = useToggle(false); - const goToCreateContactForm = () => { - onClose(); - navigate("/contacts/createContact"); + const goToCreateContactForm: FormEventHandler = e => { + e.preventDefault(); + toggleDialog(); }; return ( { - goToCreateContactForm(); - }} + onSubmit={goToCreateContactForm} title={"Suppression des droits"} submitButtonLabel="Créer un contact" > @@ -79,6 +78,13 @@ export const DeletePrimaryWithoutSecondaryDialog = ({ open, onClose }: CommonCon Voulez vous créer un nouveau contact principal ?
+ { + toggleDialog(); + onClose(); + }} + /> ); }; @@ -87,7 +93,6 @@ type PrimaryContactRightsProps = CommonContactRightsProps & { type?: string; contactIdentifier: string; secondaryContacts: APISchemas["ContactFirstLoginDto"][]; - onChangePrimaryContact: (selectedContact: string) => void; }; export const PrimaryContactRightsDialog = ({ @@ -95,18 +100,22 @@ export const PrimaryContactRightsDialog = ({ secondaryContacts, type = "edit", contactIdentifier, - onChangePrimaryContact, onClose, }: PrimaryContactRightsProps) => { const [selectedContact, setSelectedContact] = useState(""); + const [hasDialog, toggleDialog] = useToggle(false); const handleChange = (event: React.ChangeEvent) => { setSelectedContact(event.target.value); }; - const onSubmit = (selectedContact: string) => { - onChangePrimaryContact(selectedContact); - onClose(); + const onSubmit: FormEventHandler = e => { + e.preventDefault(); + + if (selectedContact === "newContact") { + toggleDialog(); + } + // add logic for other options }; return ( @@ -116,9 +125,7 @@ export const PrimaryContactRightsDialog = ({ setSelectedContact(""); onClose(); }} - onSubmit={() => { - onSubmit(selectedContact); - }} + onSubmit={onSubmit} title={type === "edit" ? "Modifier en contact secondaire" : "Suppression des droits"} submitButtonLabel="Valider" > @@ -168,6 +175,13 @@ export const PrimaryContactRightsDialog = ({ + { + toggleDialog(); + onClose(); + }} + /> ); }; @@ -209,7 +223,7 @@ export const EditSecondaryToPrimaryDialog = ({ {primaryContactIdentifier} est contact principal pour cette même unité enquêtée, il sera - automatiquement modifier en contact secondaire + automatiquement modifié en contact secondaire @@ -217,12 +231,11 @@ export const EditSecondaryToPrimaryDialog = ({ }; export const EditPrimaryWithoutSecondaryDialog = ({ open, onClose }: CommonContactRightsProps) => { - const navigate = useNavigate(); + const [hasDialog, toggleDialog] = useToggle(false); const goToCreateContactForm: FormEventHandler = e => { e.preventDefault(); - onClose(); - navigate("/contacts/createContact"); + toggleDialog(); }; return ( @@ -237,6 +250,13 @@ export const EditPrimaryWithoutSecondaryDialog = ({ open, onClose }: CommonConta Une enquête doit avoir un contact principal. Voulez vous créer un nouveau contact principal ? + { + toggleDialog(); + onClose(); + }} + /> ); }; diff --git a/src/ui/Contact/ContactRightsEditDialog.tsx b/src/ui/Contact/ContactRightsEditDialog.tsx index 725ff14..eeb9869 100644 --- a/src/ui/Contact/ContactRightsEditDialog.tsx +++ b/src/ui/Contact/ContactRightsEditDialog.tsx @@ -1,4 +1,3 @@ -import { useNavigate } from "react-router-dom"; import { EditPrimaryWithoutSecondaryDialog, EditSecondaryToPrimaryDialog, @@ -27,15 +26,6 @@ export type DialogProps = { }; export const ContactRightsEditDialog = ({ survey, contact, onAlert, onClose }: DialogProps) => { - const navigate = useNavigate(); - - const onEditPrimaryContact = (selectedContact: string) => { - // TODO: add logic - if (selectedContact === "newContact") { - navigate("/contacts/createContact"); - } - }; - if (survey.main === false) { return ( ); }; diff --git a/src/ui/Contact/CreateContact/AddressForm.tsx b/src/ui/Contact/CreateContact/AddressForm.tsx new file mode 100644 index 0000000..73bff0b --- /dev/null +++ b/src/ui/Contact/CreateContact/AddressForm.tsx @@ -0,0 +1,115 @@ +import { Box, Checkbox, FormControlLabel } from "@mui/material"; +import Stack from "@mui/material/Stack"; +import Typography from "@mui/material/Typography"; +import { UseFormRegister } from "react-hook-form"; +import { Schema, z } from "zod"; +import { Field } from "../../Form/Field"; +import { repetitionIndexEnum, streetTypeEnum, styles } from "../ContactFormDialog"; +import { countries } from "../../../constants/countries"; +import { Row } from "../../Row"; + +type Props = { + errors: any; + register: UseFormRegister>; +}; + +export const AddressForm = ({ errors, register }: Props) => { + const onCheck = () => {}; + return ( + + Adresse du contact + + } + onChange={onCheck} + label="L’adresse du contact est identique à l’adresse de l’unité enquêtée" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/src/ui/Contact/CreateContact/CreateContactDialog.tsx b/src/ui/Contact/CreateContact/CreateContactDialog.tsx new file mode 100644 index 0000000..af16bfe --- /dev/null +++ b/src/ui/Contact/CreateContact/CreateContactDialog.tsx @@ -0,0 +1,273 @@ +import Dialog from "@mui/material/Dialog"; +import { useForm } from "../../../hooks/useForm"; +import { APISchemas } from "../../../types/api"; +import { + ContactInformationForm, + repetitionIndexEnum, + schema, + streetTypeEnum, + styles, +} from "../ContactFormDialog"; +import DialogTitle from "@mui/material/DialogTitle"; +import DialogContent from "@mui/material/DialogContent"; +import DialogActions from "@mui/material/DialogActions"; +import Button from "@mui/material/Button"; +import { UseFormRegister, UseFormReturn } from "react-hook-form"; +import { Schema, z } from "zod"; +import { useState } from "react"; +import Box from "@mui/material/Box"; +import Divider from "@mui/material/Divider"; +import FormControlLabel from "@mui/material/FormControlLabel"; +import Checkbox from "@mui/material/Checkbox"; +import { Field } from "../../Form/Field"; +import { countries } from "../../../constants/countries"; +import Stack from "@mui/material/Stack"; +import { Row } from "../../Row"; + +type Props = { + open: boolean; + onClose: () => void; + surveyUnit?: APISchemas["SurveyUnitDto"]; +}; + +export const CreateContactDialog = ({ open, onClose, surveyUnit }: Props) => { + const defaultValues = { + firstName: "", + lastName: "", + email: "", + function: "", + phone: "", + address: { countryName: "FRANCE" }, + }; + + const [country, setCountry] = useState(defaultValues?.address?.countryName); + + const { register, control, errors, reset, handleSubmit, setValue } = useForm(schema, { + defaultValues: defaultValues, + }); + + const onAddressChecked = () => { + setValue("usualCompanyName", surveyUnit?.identificationName); + setValue("address", { + cedexCode: "", + cedexName: "", + cityName: "", + zipCode: "", + streetName: "", + ...surveyUnit?.address, + }); + + setCountry(surveyUnit?.address?.countryName ?? "FRANCE"); + }; + + const handleClose = () => { + reset(defaultValues); + setCountry("FRANCE"); + onClose(); + }; + + const onChangeCountry = (value: string) => { + setCountry(value); + setValue("address.countryName", value); + }; + + const onSubmit = handleSubmit(data => { + console.log(data); + handleClose(); + }); + return ( + +
+ Informations du contact + + + + + + + +
+
+ ); +}; + +type FormContentProps = { + errors: any; + register: UseFormRegister>; + control: UseFormReturn["control"]; + contact?: Omit; + country: string; + onChangeCountry: (value: string) => void; + surveyUnitId?: string; + onAddressChecked?: (e: React.ChangeEvent) => void; +}; + +export const FormContent = ({ + errors, + register, + control, + contact, + country, + onChangeCountry, + surveyUnitId, + onAddressChecked, +}: FormContentProps) => { + return ( + + + + + {surveyUnitId !== undefined && ( + } + label="L’adresse du contact est identique à l’adresse de l’unité enquêtée" + /> + )} + + + + onChangeCountry(e.target.value as string)} + /> + + + + + + + + + {country === "FRANCE" ? ( + + ) : ( + + )} + + + {country === "FRANCE" ? ( + + ) : ( + + )} + + + + + + + + + + + + + + + + ); +}; diff --git a/src/ui/Contact/CreateContact/InformationsForm.tsx b/src/ui/Contact/CreateContact/InformationsForm.tsx new file mode 100644 index 0000000..2ae0693 --- /dev/null +++ b/src/ui/Contact/CreateContact/InformationsForm.tsx @@ -0,0 +1,83 @@ +import { Button, Stack } from "@mui/material"; +import Typography from "@mui/material/Typography"; +import { schema } from "../ContactFormDialog"; +import { useForm } from "../../../hooks/useForm"; +import { Row } from "../../Row"; + +import { APISchemas } from "../../../types/api"; +import { FormContent } from "./CreateContactDialog"; +import { useState } from "react"; +import { useNavigate } from "react-router-dom"; + +type Props = { + handleSubmitStep: (data: any) => void; + contact?: Omit; + surveyUnit?: APISchemas["SurveyUnitDto"]; +}; + +export const InformationsForm = ({ handleSubmitStep, contact, surveyUnit }: Props) => { + const navigate = useNavigate(); + const defaultValues = + contact?.address?.countryName && contact.address.countryName !== "" + ? contact + : { ...contact, address: { ...contact?.address, countryName: "FRANCE" } }; + + const { register, control, errors, handleSubmit, setValue } = useForm(schema, { + defaultValues: defaultValues, + }); + + const onSubmit = handleSubmit(data => { + handleSubmitStep(data); + }); + + const [country, setCountry] = useState(defaultValues?.address?.countryName ?? "FRANCE"); + + const onAddressChecked = () => { + setValue("usualCompanyName", surveyUnit?.identificationName); + setValue("address", { + cedexCode: "", + cedexName: "", + cityName: "", + zipCode: "", + streetName: "", + ...surveyUnit?.address, + }); + + setCountry(surveyUnit?.address?.countryName ?? "FRANCE"); + }; + + const onChangeCountry = (value: string) => { + setCountry(value); + setValue("address.countryName", value); + }; + + return ( + + + Informations du contact + +
+ + + + + + + + +
+ ); +}; diff --git a/src/ui/Contact/CreateContact/RightsManagementForm.tsx b/src/ui/Contact/CreateContact/RightsManagementForm.tsx new file mode 100644 index 0000000..4850f11 --- /dev/null +++ b/src/ui/Contact/CreateContact/RightsManagementForm.tsx @@ -0,0 +1,78 @@ +import Stack from "@mui/material/Stack"; +import Typography from "@mui/material/Typography"; +import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; +import { Row } from "../../Row"; +import { Button, InputLabel, TextField } from "@mui/material"; +import { useNavigate } from "react-router-dom"; + +type Props = { + handleSubmitStep: (event: React.FormEvent) => void; + handleBack: () => void; + rights: { idSource?: string; year?: string; periodicity?: string }; +}; + +export const RightsManagementForm = ({ handleSubmitStep, handleBack, rights }: Props) => { + const navigate = useNavigate(); + + const isButtonDisabled = rights.periodicity === ""; + + return ( + + + Ajouter des droits + + + + + La sélection d’une source, d’un millésime et d’une période
est nécessaire pour l’ajout + de droits +
+
+
+ + + + Source + + + + + + Millésime + + + + + + Période + + + + + + + + + + + + +
+
+ ); +}; diff --git a/src/ui/Contact/IdsManagement.tsx b/src/ui/Contact/IdsManagement.tsx deleted file mode 100644 index 16e6f4c..0000000 --- a/src/ui/Contact/IdsManagement.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import Card from "@mui/material/Card"; -import { TitleWithIconAndDivider } from "../TitleWithIconAndDivider"; -import { BinocularIcon } from "../Icon/BinocularIcon"; -import { APISchemas } from "../../types/api"; -import { Row } from "../Row"; -import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; -import { Typography } from "@mui/material"; -import { Stack } from "@mui/system"; -import GroupAddOutlinedIcon from "@mui/icons-material/GroupAddOutlined"; -import { AssociateSurveysTable } from "./AssociateSurveysTable"; -import { AssociateAnotherAccount } from "./AssociateAnotherAccount"; - -type Props = { - contact: APISchemas["ContactFirstLoginDto"]; -}; - -export const IdsManagement = ({ contact }: Props) => { - return ( - - - - - - - La liste des enquêtes auxquelles le répondant peut accéder avec son identifiant{" "} - {contact.identifier} peut être élargie à des enquêtes rattachées à son - adresse courriel et figurant dans la liste ci-dessous - - - - - - - - - - ); -}; diff --git a/src/ui/Contact/RightsManagement.tsx b/src/ui/Contact/RightsManagement.tsx index 8c1c5bb..e85e2c5 100644 --- a/src/ui/Contact/RightsManagement.tsx +++ b/src/ui/Contact/RightsManagement.tsx @@ -1,10 +1,7 @@ import Stack from "@mui/material/Stack"; import { APISchemas } from "../../types/api"; import Card from "@mui/material/Card"; -import { TitleWithIconAndDivider } from "../TitleWithIconAndDivider"; -import LibraryAddOutlinedIcon from "@mui/icons-material/LibraryAddOutlined"; import ChangeCircleOutlinedIcon from "@mui/icons-material/ChangeCircleOutlined"; -import { AddRightsForm } from "./AddRightsForm"; import { Row } from "../Row"; import { useState } from "react"; import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; @@ -13,6 +10,9 @@ import { UpdateContactRightsTable } from "./UpdateContactRightsTable"; import { ContactRightsEditDialog, mockedDataSurveyType } from "./ContactRightsEditDialog"; import { ContactRightsDeleteDialog } from "./ContactRightsDeleteDialog"; import { Alert } from "../Alert"; +import Button from "@mui/material/Button"; +import Divider from "@mui/material/Divider"; +import { Link } from "../Link"; type Props = { contact: APISchemas["ContactFirstLoginDto"]; @@ -29,50 +29,58 @@ export const RightsManagement = ({ contact }: Props) => { }; return ( - - - - - - - - - - - Suppression des droits : un contact principal ne peut pas être supprimé s’il n’y a pas de - contact secondaire pouvant devenir principal à sa place
- Modification des droits : un contact principal peut devenir secondaire uniquement dans le cas - ou un autre contact de l‘enquête peut devenir principal -
+ + + + + + + Modifier la liste des questionnaires du contact + + + - {message && ( - setMessage(undefined)} /> - )} - + + + + + + + Suppression des droits : un contact principal ne peut pas être supprimé s’il n’y a pas de + contact secondaire pouvant devenir principal à sa place
+ Modification des droits : un contact principal peut devenir secondaire uniquement dans le cas + ou un autre contact de l‘enquête peut devenir principal +
+
+ {message && ( + setMessage(undefined)} /> + )} + - {dialog?.type === "edit" && ( - - )} - {dialog?.type === "delete" && ( - - )} -
-
+ {dialog?.type === "edit" && ( + + )} + {dialog?.type === "delete" && ( + + )} + ); }; diff --git a/src/ui/Form/AddressFormFields.tsx b/src/ui/Form/AddressFormFields.tsx index 6607055..1b6e687 100644 --- a/src/ui/Form/AddressFormFields.tsx +++ b/src/ui/Form/AddressFormFields.tsx @@ -33,7 +33,7 @@ export const AddressFormFields = ({ countryValue, type = "surveyUnit", }: Props) => { - const [country, setCountry] = useState(countryValue); + const [country, setCountry] = useState(countryValue ?? "FRANCE"); return ( diff --git a/src/ui/Form/Field.tsx b/src/ui/Form/Field.tsx index 03ad722..3e07750 100644 --- a/src/ui/Form/Field.tsx +++ b/src/ui/Form/Field.tsx @@ -15,7 +15,7 @@ import TextField, { TextFieldProps } from "@mui/material/TextField"; import { FormControl, FormHelperText, InputLabel, MenuItem, Select, SelectProps } from "@mui/material"; type Props = Pick & - Pick & { + Pick & { type?: "radios" | "radiostack" | "switch" | "text" | "select"; error?: string; control?: UseFormReturn["control"]; @@ -122,7 +122,51 @@ export function uncontrolledField(props: Props, ref: any) { ); } -export function controlledField({ type, name, options, error }: Props, field: any) { +export function controlledField( + { type, name, options, error, label, selectoptions, value, onChange }: Props, + field: any, +) { + if (!type || type === "text") { + return ( + + ); + } + if (type === "select" && selectoptions) { + const labelId = `label-${name}`; + + return ( + + + {label} + + + + ); + } if (type === "switch") { return ; } diff --git a/src/ui/Link.tsx b/src/ui/Link.tsx index 0db1e2f..fab803d 100644 --- a/src/ui/Link.tsx +++ b/src/ui/Link.tsx @@ -3,6 +3,7 @@ import { Link as RouterLink } from "react-router-dom"; type Props = LinkProps & { to: string; + state?: string; }; export const Link = (props: Props) => { diff --git a/src/ui/PageTab.tsx b/src/ui/PageTab.tsx index 7852526..2c4490d 100644 --- a/src/ui/PageTab.tsx +++ b/src/ui/PageTab.tsx @@ -13,9 +13,6 @@ export const PageTab = ({ label, ...props }: Props) => { paddingY: 3, typography: "titleSmall", letterSpacing: 0.4, - // todo remove backgroundColor after demo - backgroundColor: - label === "Gestion des identifiants" || label === "Gestion des droits" ? "text.hint" : "white", }} {...props} /> diff --git a/src/ui/SurveyUnit/SurveyUnitContacts.tsx b/src/ui/SurveyUnit/SurveyUnitContacts.tsx index cd35a4a..e4f3d00 100644 --- a/src/ui/SurveyUnit/SurveyUnitContacts.tsx +++ b/src/ui/SurveyUnit/SurveyUnitContacts.tsx @@ -119,7 +119,7 @@ export const SurveyUnitContacts = ({ surveyUnit }: Props) => { variant="contained" endIcon={} > - + Créer un nouveau contact diff --git a/src/ui/SurveyUnit/SurveyUnitFormDialog.tsx b/src/ui/SurveyUnit/SurveyUnitFormDialog.tsx index b8245bb..0bc89bf 100644 --- a/src/ui/SurveyUnit/SurveyUnitFormDialog.tsx +++ b/src/ui/SurveyUnit/SurveyUnitFormDialog.tsx @@ -23,7 +23,7 @@ const schema = z.object({ export const SurveyUnitFormDialog = ({ open, onClose, surveyUnit, onSave }: Props) => { const defaultValues = surveyUnit.address?.countryName ? surveyUnit - : { ...surveyUnit, address: { ...surveyUnit.address, countryName: "France" } }; + : { ...surveyUnit, address: { ...surveyUnit.address, countryName: "FRANCE" } }; const { register, errors, handleSubmit } = useForm(schema, { defaultValues: defaultValues, }); diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index ee62647..e410c35 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -1,18 +1,18 @@ /// type ImportMetaEnv = { // Auto-generated by `npx vite-envs update-types` and hot-reloaded by the `vite-env` plugin - VITE_API_ENDPOINT: string - VITE_AUTH_TYPE: string - VITE_OIDC_CLIENT_ID: string - VITE_OIDC_ISSUER: string - VITE_IDENTITY_PROVIDER: string - VITE_ADMIN_LDAP_ROLE: string - VITE_USER_LDAP_ROLE: string - VITE_APP_URL: string - BASE_URL: string - MODE: string - DEV: boolean - PROD: boolean + VITE_API_ENDPOINT: string; + VITE_AUTH_TYPE: string; + VITE_OIDC_CLIENT_ID: string; + VITE_OIDC_ISSUER: string; + VITE_IDENTITY_PROVIDER: string; + VITE_ADMIN_LDAP_ROLE: string; + VITE_USER_LDAP_ROLE: string; + VITE_APP_URL: string; + BASE_URL: string; + MODE: string; + DEV: boolean; + PROD: boolean; // @user-defined-start /* * Here you can define your own special variables @@ -23,18 +23,18 @@ type ImportMetaEnv = { */ SSR: boolean; // @user-defined-end -} +}; interface ImportMeta { // Auto-generated by `npx vite-envs update-types` - url: string + url: string; - readonly hot?: import('vite-envs/types/hot').ViteHotContext + readonly hot?: import("vite-envs/types/hot").ViteHotContext; - readonly env: ImportMetaEnv + readonly env: ImportMetaEnv; - glob: import('vite-envs/types/importGlob').ImportGlobFunction + glob: import("vite-envs/types/importGlob").ImportGlobFunction; } type ObjectKeys = T extends object