diff --git a/package.json b/package.json index 7cf5876..763ca95 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "platine-management", "private": true, - "version": "1.0.18", + "version": "1.0.19", "type": "module", "scripts": { "dev": "vite", diff --git a/src/hooks/useFetchQuery.ts b/src/hooks/useFetchQuery.ts index 148d7f3..1240762 100644 --- a/src/hooks/useFetchQuery.ts +++ b/src/hooks/useFetchQuery.ts @@ -80,6 +80,7 @@ export function useInfiniteFetchQuery v.setFilter); } +export function useGetSearchFilter() { + return useSearchFilter(v => v); +} + export function useSearchFilterParams(name: K): State[K] { return useSearchFilter(v => v[name]); } + +/* + Hook to manage filter states more efficiently + + example: + const { onSubmit, onReset, inputProps } = useSearchForm("contacts", { + identifier: "", + name: "", + email: "", + city: "", + function: "", + }); + +
+ + + ... + +*/ + +export function useSearchForm(key: K, initialValue: State[K]) { + const [value, setValue] = useState(initialValue); + const setFilter = useSetSearchFilter(); + + const onSubmit: FormEventHandler = e => { + e.preventDefault(); + setFilter(key, value); + }; + + const onReset: FormEventHandler = e => { + e.preventDefault(); + setFilter(key, base[key]); + setValue(base[key]); + }; + + return { + value, + onSubmit, + onReset, + inputProps: (name: keyof State[K]) => ({ + id: name, + name: name, + value: value[name], + onChange: (e: any) => setValue({ ...value, [name]: e.target.value }), + }), + handler: (name: keyof State[K]) => { + return (e: any) => setValue({ ...value, [name]: e.target.value }); + }, + }; +} diff --git a/src/pages/ContactPage.tsx b/src/pages/ContactPage.tsx index c1683d2..2894c8b 100644 --- a/src/pages/ContactPage.tsx +++ b/src/pages/ContactPage.tsx @@ -21,7 +21,7 @@ enum Tab { const TabNames = { [Tab.Infos]: "Infos contact", - [Tab.Surveys]: "Interrogation(s)", + [Tab.Surveys]: "Questionnaire(s)", [Tab.Ids]: "Gestion des identifiants", [Tab.Permissions]: "Gestion des droits", }; diff --git a/src/pages/Search/SearchContacts.tsx b/src/pages/Search/SearchContacts.tsx index 30216e6..e7d92ba 100644 --- a/src/pages/Search/SearchContacts.tsx +++ b/src/pages/Search/SearchContacts.tsx @@ -29,13 +29,15 @@ export const SearchContacts = () => { hasNextPage, fetchNextPage, isLoading, + count, } = useInfiniteFetchQuery(endpoint, { query: { ...useSearchFilterParams("contacts"), pageSize: 20, sort: "identifier" }, }); const [tab, setTab] = useState("me"); + return ( - + setTab(v)}> Mes contacts @@ -44,6 +46,7 @@ export const SearchContacts = () => { Tout + {count && résultat: {count} contact(s)} {isLoading && ( diff --git a/src/pages/Search/SearchSurveyUnits.tsx b/src/pages/Search/SearchSurveyUnits.tsx index c3c7db8..9c0f42f 100644 --- a/src/pages/Search/SearchSurveyUnits.tsx +++ b/src/pages/Search/SearchSurveyUnits.tsx @@ -1,5 +1,4 @@ import { Box, CardActionArea, CircularProgress, Stack } from "@mui/material"; -import { FilterListBySelector } from "../../ui/Search/FilterListBySelector.tsx"; import { Row } from "../../ui/Row"; import { useInfiniteFetchQuery } from "../../hooks/useFetchQuery.ts"; import ToggleButtonGroup from "@mui/material/ToggleButtonGroup"; @@ -24,6 +23,7 @@ export const SearchSurveyUnits = () => { hasNextPage, fetchNextPage, isLoading, + count, } = useInfiniteFetchQuery(endpoint, { query: useSearchFilterParams("surveyUnits"), }); @@ -40,7 +40,7 @@ export const SearchSurveyUnits = () => { Tout - + {count && résultat: {count} unité(s) enquêtée(s)} {isLoading && ( diff --git a/src/theme.tsx b/src/theme.tsx index 0050851..fd5e429 100644 --- a/src/theme.tsx +++ b/src/theme.tsx @@ -104,6 +104,7 @@ declare module "@mui/material/SvgIcon" { headerSinglePage: true; cardTitle: true; smallIcon: true; + linkIcon: true; } interface SvgIconPropsColorOverrides { yellow: true; @@ -305,6 +306,12 @@ export const theme = createTheme({ fontSize: 20, }, }, + { + props: { fontSize: "linkIcon" }, + style: { + fontSize: 14, + }, + }, ], }, MuiTab: { @@ -405,6 +412,7 @@ export const theme = createTheme({ styleOverrides: { root: { background: "#FFF", + color: palette.text.secondary, }, sizeSmall: { ...typography.bodyMedium, diff --git a/src/ui/AddressInformations.tsx b/src/ui/AddressInformations.tsx index 9075dda..272f411 100644 --- a/src/ui/AddressInformations.tsx +++ b/src/ui/AddressInformations.tsx @@ -14,25 +14,22 @@ export const AddressInformations = ({ identificationName, address }: Props) => { const isCodeBoxDisplayed = address?.zipCode || address?.cityName || address?.cedexCode || address?.cedexName; - const isSupplementDisplayed = address?.addressSupplement || address?.specialDistribution; return ( {identificationName && ( {identificationName.toUpperCase()} )} + {address?.addressSupplement && {address?.addressSupplement}} {isStreetBoxDisplayed && ( {address?.streetNumber} {address?.repetitionIndex} {address?.streetType} {address?.streetName} )} - {isSupplementDisplayed && ( - - {address?.addressSupplement} {address?.specialDistribution} - - )} + {address?.specialDistribution && {address?.specialDistribution}} {isCodeBoxDisplayed && ( - {address?.zipCode} {address?.cityName} {address?.cedexCode} {address?.cedexName} + {address?.zipCode} {address?.cityName?.toLocaleUpperCase()} {address?.cedexCode} + {address?.cedexName?.toLocaleUpperCase()} )} {address?.countryName} diff --git a/src/ui/Contact/AddRightsForm.tsx b/src/ui/Contact/AddRightsForm.tsx index 23d31a7..de051c1 100644 --- a/src/ui/Contact/AddRightsForm.tsx +++ b/src/ui/Contact/AddRightsForm.tsx @@ -83,18 +83,21 @@ export const AddRightsForm = ({ contact }: Props) => { setFieldsData({ ...fieldsData, idSource: e.target.value })} /> setFieldsData({ ...fieldsData, year: e.target.value })} /> setFieldsData({ ...fieldsData, periodicity: e.target.value })} diff --git a/src/ui/Contact/CollectStateHistory.tsx b/src/ui/Contact/CollectStateHistory.tsx index df99789..b5063b2 100644 --- a/src/ui/Contact/CollectStateHistory.tsx +++ b/src/ui/Contact/CollectStateHistory.tsx @@ -1,4 +1,4 @@ -import { Table, TableBody, TableCell, TableHead, TableRow } from "@mui/material"; +import { IconButton, Table, TableBody, TableCell, TableHead, TableRow } from "@mui/material"; import Button from "@mui/material/Button"; import Dialog from "@mui/material/Dialog"; import DialogActions from "@mui/material/DialogActions"; @@ -6,8 +6,10 @@ import DialogContent from "@mui/material/DialogContent"; import DialogTitle from "@mui/material/DialogTitle"; import TableContainer from "@mui/material/TableContainer"; import { CollectStateSelect, collectStates } from "./CollectStateSelect"; -import { useFetchQuery } from "../../hooks/useFetchQuery"; +import { useFetchMutation, useFetchQuery } from "../../hooks/useFetchQuery"; import { Row } from "../Row"; +import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline"; +import { useState } from "react"; type Props = { onClose: () => void; @@ -18,23 +20,46 @@ type Props = { }; export const CollectStateHistory = ({ onClose, open, questioningId, surveyName, onSelect }: Props) => { - const { data: states } = useFetchQuery("/api/questionings/{id}/questioning-events", { + const [dialog, setDialog] = useState(); + + const { data: states, refetch } = useFetchQuery("/api/questionings/{id}/questioning-events", { urlParams: { id: parseInt(questioningId), }, }); + const { mutateAsync, isPending } = useFetchMutation( + "/api/questionings/questioning-events/{id}", + "delete", + ); + if (!states) { return; } + const onValidate = async (value: string) => { + await onSelect(value); + refetch(); + }; + + const onDelete = async (id?: number) => { + if (!id) { + return; + } + await mutateAsync({ + urlParams: { id }, + }); + setDialog(undefined); + refetch(); + }; + const sortedStates = states.sort((a, b) => b.eventDate!.localeCompare(a.eventDate!)); return ( - Historique {surveyName} + Historique {surveyName} Date Heure Statut + Supprimer @@ -63,6 +89,24 @@ export const CollectStateHistory = ({ onClose, open, questioningId, surveyName, {date} {hour} {collectStates.find(cs => cs.value === state.type)?.label} + {state.type && ["VALPAP", "HC", "REFUSAL", "WASTE"].includes(state.type) && ( + + setDialog(state.id)} + disabled={isPending} + > + + + setDialog(undefined)} + onDelete={() => onDelete(state.id)} + open={dialog === state.id} + state={state.type} + /> + + )} ); })} @@ -78,3 +122,34 @@ export const CollectStateHistory = ({ onClose, open, questioningId, surveyName, ); }; + +type DeleteDialogProps = { + onClose: () => void; + onDelete: () => void; + open: boolean; + state: string; +}; + +const DeleteDialog = ({ onClose, open, state, onDelete }: DeleteDialogProps) => { + return ( + + + Êtes-vous sûr de vouloir supprimer l'état "{collectStates.find(s => s.value === state)?.label}" ? + + + + + + + ); +}; diff --git a/src/ui/Contact/CollectStateSelect.tsx b/src/ui/Contact/CollectStateSelect.tsx index cf88efe..011b7cb 100644 --- a/src/ui/Contact/CollectStateSelect.tsx +++ b/src/ui/Contact/CollectStateSelect.tsx @@ -1,7 +1,8 @@ import MenuItem from "@mui/material/MenuItem"; import Box from "@mui/material/Box"; -import { Button, Menu } from "@mui/material"; +import { Button, Dialog, DialogActions, DialogContent, Menu } from "@mui/material"; import { useState } from "react"; +import { useToggle } from "react-use"; export const collectStates = [ { label: "Questionnaire papier réceptionné", value: "VALPAP" }, @@ -20,13 +21,16 @@ const options = collectStates.filter(state => ); type Props = { - onSelect: (value: string) => void; + onValidate: (value: string) => void; }; -export const CollectStateSelect = ({ onSelect }: Props) => { +export const CollectStateSelect = ({ onValidate }: Props) => { const [anchorEl, setAnchorEl] = useState(null); + const [selectedState, setSelectedState] = useState(""); const open = Boolean(anchorEl); + const [openDialog, toggleDialog] = useToggle(false); + const onClick = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; @@ -36,7 +40,14 @@ export const CollectStateSelect = ({ onSelect }: Props) => { const handleSelect = (value: string) => { setAnchorEl(null); - onSelect(value); + setSelectedState(value); + toggleDialog(); + }; + + const handleValidate = () => { + toggleDialog(); + onValidate(selectedState); + setSelectedState(""); }; return ( @@ -65,6 +76,45 @@ export const CollectStateSelect = ({ onSelect }: Props) => { ))} + {selectedState !== "" && ( + + )} ); }; + +type ValidationDialogProps = { + onClose: () => void; + onValidate: () => void; + open: boolean; + state: string; +}; + +const ValidationDialog = ({ onClose, open, state, onValidate }: ValidationDialogProps) => { + return ( + + + Êtes-vous sûr de vouloir ajouter l'état "{collectStates.find(s => s.value === state)?.label}" ? + + + + + + + ); +}; diff --git a/src/ui/Contact/ContactFormDialog.tsx b/src/ui/Contact/ContactFormDialog.tsx index d34ba66..d5de938 100644 --- a/src/ui/Contact/ContactFormDialog.tsx +++ b/src/ui/Contact/ContactFormDialog.tsx @@ -23,12 +23,12 @@ export const addressSchema = z .string() .nullable() .transform(val => (val === null ? "" : val)) - .optional(), //TODO: use real repetition index + .optional(), streetType: z .string() .nullable() .transform(val => (val === null ? "" : val)) - .optional(), // TODO: use real street type + .optional(), streetName: z.string().optional(), addressSupplement: z .string() @@ -40,17 +40,80 @@ export const addressSchema = z .nullable() .transform(val => (val === null ? "" : val)) .optional(), - cityName: z.string().optional(), - zipCode: z.string().optional(), - deliveryOffice: z.string().optional(), // TODO: add in api + cedexName: z + .string() + .nullable() + .transform(val => (val === null ? "" : val)), cedexCode: z .string() .nullable() - .transform(val => (val === null ? "" : val)) - .optional(), + .transform(val => (val === null ? "" : val)), + cityName: z + .string() + .nullable() + .transform(val => (val === null ? "" : val)), + zipCode: z + .string() + .nullable() + .transform(val => (val === null ? "" : val)), countryName: z.string().optional().or(z.literal("")), }) - .optional(); + .superRefine(({ cedexCode, zipCode, cityName, cedexName }, refinementContext) => { + if ((cedexCode === undefined || cedexCode === "") && (zipCode === undefined || zipCode === "")) { + refinementContext.addIssue({ + code: z.ZodIssueCode.custom, + message: "Code cedex ou code postal requis", + path: ["zipCode"], + }); + return refinementContext.addIssue({ + code: z.ZodIssueCode.custom, + message: "Code cedex ou code postal requis", + path: ["cedexCode"], + }); + } + + if (cedexCode && cedexCode !== "" && zipCode && zipCode !== "") { + refinementContext.addIssue({ + code: z.ZodIssueCode.custom, + message: "Impossible de remplir code postal et code cedex", + path: ["zipCode"], + }); + return refinementContext.addIssue({ + code: z.ZodIssueCode.custom, + message: "Impossible de remplir code postal et code cedex", + path: ["cedexCode"], + }); + } + + if (cedexName && cedexName !== "" && cityName && cityName !== "") { + refinementContext.addIssue({ + code: z.ZodIssueCode.custom, + message: "Impossible de remplir commune et bureau distributeur", + path: ["cityName"], + }); + return refinementContext.addIssue({ + code: z.ZodIssueCode.custom, + message: "Impossible de remplir commune et bureau distributeur", + path: ["cedexName"], + }); + } + + if (cedexCode !== undefined && cedexCode !== "" && (cedexName === undefined || cedexName === "")) { + return refinementContext.addIssue({ + code: z.ZodIssueCode.custom, + message: "Champs requis", + path: ["cedexName"], + }); + } + + if (zipCode !== undefined && zipCode !== "" && (cityName === undefined || cityName === "")) { + return refinementContext.addIssue({ + code: z.ZodIssueCode.custom, + message: "Champs requis", + path: ["cityName"], + }); + } + }); const schema = z.object({ civility: z.enum(["Female", "Male", "Undefined"]), @@ -65,6 +128,7 @@ const schema = z.object({ .optional(), secondPhone: z.string().optional().or(z.literal("")), identificationName: z.string().optional(), + usualCompanyName: z.string().optional(), address: addressSchema, }); @@ -80,7 +144,7 @@ export const streetTypeEnum = ["rue", "avenue"]; // TODO: use real street type export const styles = { Grid: { display: "grid", - gridTemplateColumns: "1fr 1px 1fr 1fr", + gridTemplateColumns: "1fr 1px 1fr ", gap: "40px", }, }; @@ -89,7 +153,7 @@ export const ContactFormDialog = ({ open, onClose, contact, onSave }: Props) => const defaultValues = contact.address?.countryName ? contact : { ...contact, address: { ...contact.address, countryName: "France" } }; - const { register, control, errors, handleSubmit } = useForm(schema, { + const { register, control, errors, handleSubmit, reset } = useForm(schema, { defaultValues: defaultValues, }); @@ -103,15 +167,19 @@ export const ContactFormDialog = ({ open, onClose, contact, onSave }: Props) => onSave(); }); + const handleClose = () => { + reset(defaultValues); + onClose(); + }; console.log({ errors }); return ( - +
Modification des coordonnées - + - - - + - toggle(v)}> @@ -74,7 +96,7 @@ export const ContactSurveysContent = ({ contact }: Props) => { - + ); }; @@ -104,15 +126,18 @@ function filterSurveys( } type FiltersProps = { + searchValue: string; + stateValue: string; onSelect: (e: SelectChangeEvent) => void; onSearch: (e: React.ChangeEvent) => void; }; -export const Filters = ({ onSelect, onSearch }: FiltersProps) => { +export const Filters = ({ searchValue, stateValue, onSelect, onSearch }: FiltersProps) => { return ( { ), }} + value={searchValue} name="name" id="name" label="Rechercher dans le tableau" diff --git a/src/ui/Contact/ContactSurveysFilterSelect.tsx b/src/ui/Contact/ContactSurveysFilterSelect.tsx index 84224f3..b44581b 100644 --- a/src/ui/Contact/ContactSurveysFilterSelect.tsx +++ b/src/ui/Contact/ContactSurveysFilterSelect.tsx @@ -5,7 +5,7 @@ import Select, { SelectChangeEvent } from "@mui/material/Select"; type Props = { options: { label: string; value: string }[]; - defaultValue?: string; + value?: string; placeholderLabel?: string; label: string; name: string; @@ -14,7 +14,7 @@ type Props = { export const ContactSurveysFilterSelect = ({ options, - defaultValue, + value, label, placeholderLabel, name, @@ -32,7 +32,7 @@ export const ContactSurveysFilterSelect = ({ label={label} name={name} fullWidth - defaultValue={defaultValue ?? placeholderLabel ?? ""} + value={value ?? placeholderLabel ?? ""} onChange={onFilterChange} id={`select-${name}`} size="small" diff --git a/src/ui/Contact/ContactSurveysTable.tsx b/src/ui/Contact/ContactSurveysTable.tsx index d6b0213..249c124 100644 --- a/src/ui/Contact/ContactSurveysTable.tsx +++ b/src/ui/Contact/ContactSurveysTable.tsx @@ -43,7 +43,7 @@ export const columns: readonly Column[] = [ type Props = { surveys?: APISchemas["AccreditationDetailDto"][]; - onSelectState: () => void; + refetchState: () => void; isLoading: boolean; }; @@ -72,7 +72,7 @@ export const ContactSurveysTable = (props: Props) => { ); })} diff --git a/src/ui/Contact/ContactSurveysTableRow.tsx b/src/ui/Contact/ContactSurveysTableRow.tsx index 3fb71ce..e21b056 100644 --- a/src/ui/Contact/ContactSurveysTableRow.tsx +++ b/src/ui/Contact/ContactSurveysTableRow.tsx @@ -13,12 +13,14 @@ import OpenInNewIcon from "@mui/icons-material/OpenInNew"; import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown"; import IconButton from "@mui/material/IconButton"; import { Link } from "../Link"; +import ArrowOutwardIcon from "@mui/icons-material/ArrowOutward"; +import { Typography } from "@mui/material"; type Props = { survey: APISchemas["AccreditationDetailDto"]; - onSelectState: () => void; + refetchState: () => void; }; -export const ContactSurveysTableRow = ({ survey, onSelectState }: Props) => { +export const ContactSurveysTableRow = ({ survey, refetchState }: Props) => { const [openCollectStateHistory, setOpenCollectStateHistory] = useState(); @@ -40,7 +42,6 @@ export const ContactSurveysTableRow = ({ survey, onSelectState }: Props) => { payload: { "source": "platine-gestion" }, }, }); - onSelectState(); }; return ( @@ -50,15 +51,16 @@ export const ContactSurveysTableRow = ({ survey, onSelectState }: Props) => { key={`row-${survey.partition}-${survey.identificationName}`} sx={{ borderBottom: `solid 1px ${theme.palette.text.hint}` }} > - {columns.map(column => { + {columns.map((column, index) => { return ( ); })} @@ -85,6 +87,7 @@ type ContactSurveysTableCellProps = { openCollectStateHistory: APISchemas["AccreditationDetailDto"] | undefined; setOpenCollectStateHistory: (survey?: APISchemas["AccreditationDetailDto"]) => void; onSelectCollectState: (type: string, questioningId?: string) => void; + refetchState: () => void; }; const ContactSurveysTableCell = ({ @@ -93,6 +96,7 @@ const ContactSurveysTableCell = ({ openCollectStateHistory, setOpenCollectStateHistory, onSelectCollectState, + refetchState, }: ContactSurveysTableCellProps) => { const value = survey[columnId as keyof typeof survey]; @@ -101,7 +105,7 @@ const ContactSurveysTableCell = ({ survey.questioningId !== undefined && openCollectStateHistory === survey; return ( - + {isCollectStateHistoryVisible && ( setOpenCollectStateHistory(undefined)} + onClose={() => { + refetchState(); + setOpenCollectStateHistory(undefined); + }} open={true} questioningId={survey.questioningId!} surveyName={survey.partition ?? ""} @@ -131,7 +138,7 @@ const ContactSurveysTableCell = ({ if (columnId === "actions") { return ( - + {survey.questioningUrl && ( @@ -142,25 +149,29 @@ const ContactSurveysTableCell = ({ } if (columnId === "main") { - return {value === true ? "Principal" : "Secondaire"}; + return {value === true ? "Principal" : "Secondaire"}; } if (columnId === "partioningClosingDate") { - return ( - {new Date(Date.parse(value as string)).toLocaleDateString()} - ); + return {new Date(Date.parse(value as string)).toLocaleDateString()}; } if (columnId === "surveyUnitId" || columnId === "sourceWording") { return ( - + - {value} + + {value} + + ); diff --git a/src/ui/Contact/PasswordCard.tsx b/src/ui/Contact/PasswordCard.tsx index 62c6bb1..439df91 100644 --- a/src/ui/Contact/PasswordCard.tsx +++ b/src/ui/Contact/PasswordCard.tsx @@ -11,6 +11,7 @@ import { SelectWithOptions } from "../Form/SelectWithOptions.tsx"; export const PasswordCard = () => { const [open, setOpen] = useState(false); + const [optionSelected, setOptionSelected] = useState(""); const handleClickOpen = () => { setOpen(true); @@ -18,6 +19,7 @@ export const PasswordCard = () => { const onClose = () => { setOpen(false); + setOptionSelected(""); }; const onSubmit = (event: React.FormEvent) => { @@ -28,7 +30,10 @@ export const PasswordCard = () => { onClose(); }; - const options = ["mail", "phone"]; // TODO: use real options + const options = [ + { label: "email", value: "mail" }, + { label: "téléphone", value: "phone" }, + ]; // TODO: use real options const style = { root: { @@ -57,6 +62,8 @@ export const PasswordCard = () => { > setOptionSelected(e.target.value)} options={options} label={"Choisissez le mode d'envoi"} name={"password"} diff --git a/src/ui/Form/AddressFormFields.tsx b/src/ui/Form/AddressFormFields.tsx index fb21d30..6607055 100644 --- a/src/ui/Form/AddressFormFields.tsx +++ b/src/ui/Form/AddressFormFields.tsx @@ -14,6 +14,7 @@ type Props = { repetitionIndexValue?: string; streetTypeValue?: string; countryValue: string; + type?: "contact" | "surveyUnit"; }; const styles = { @@ -30,16 +31,46 @@ export const AddressFormFields = ({ repetitionIndexValue, streetTypeValue, countryValue, + type = "surveyUnit", }: Props) => { const [country, setCountry] = useState(countryValue); return ( - + + + { + setCountry(e.target.value as string); + }} + /> + + {type === "surveyUnit" ? ( + + ) : ( + + )} - + {country === "FRANCE" ? ( )} + {country === "FRANCE" ? ( + + ) : ( + + )} - {country === "FRANCE" ? ( - - ) : ( - - )} - - - - - - - - + { - setCountry(e.target.value as string); - }} + sx={{ width: "180px" }} + label="Commune" + error={errors.address?.cityName?.message} + {...register("address.cityName")} /> - + + + + + ); diff --git a/src/ui/Form/SelectWithOptions.tsx b/src/ui/Form/SelectWithOptions.tsx index 4514c1a..db23f33 100644 --- a/src/ui/Form/SelectWithOptions.tsx +++ b/src/ui/Form/SelectWithOptions.tsx @@ -6,6 +6,7 @@ export type Props = { options: Option[]; label: string; name: string; + value?: string | number; onChange?: (e: SelectChangeEvent) => void; }; @@ -17,11 +18,24 @@ const getLabel = (o: Option) => { return typeof o === "string" ? o : o.label; }; -export function SelectWithOptions({ options, label, name, onChange }: Props) { +const getSelectedLabel = (selected: string, options: Option[]) => { + if (typeof options[0] === "string") { + return selected; + } + + const option = options.find((o: Option) => typeof o !== "string" && o.value === selected) as { + label: string; + value: string; + }; + return option.label; +}; + +export function SelectWithOptions({ options, label, name, onChange, value }: Props) { return ( +