From 4ba6b376e6f6f6d8a6396eb0d8ab20b2b3ae3fde Mon Sep 17 00:00:00 2001 From: DarrellRoberts Date: Fri, 7 Aug 2026 23:21:21 +0200 Subject: [PATCH 1/5] adds new autocomplete editable field --- package.json | 2 +- public/locales/de/translations.json | 4 ++ public/locales/en/translations.json | 4 ++ .../OrganisationDetails.tsx | 13 +++- .../OrganisationDetailsDisplay.tsx | 1 - .../OrganisationDetailsEdit.tsx | 33 +++++++--- .../organisationDetailsSchema.ts | 9 ++- .../sections/ProfileHeader/agent/constants.ts | 14 +++-- src/components/Dashboard/common/statusMaps.ts | 2 + .../EditableField/EditableField.tsx | 61 ++++++++++++++++++- src/hooks/useGetOrganization.ts | 18 ++++++ yarn.lock | 8 +-- 12 files changed, 144 insertions(+), 25 deletions(-) create mode 100644 src/hooks/useGetOrganization.ts diff --git a/package.json b/package.json index b620d3e4..48eb674e 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "date-fns": "^4.1.0", "email-validator": "^2.0.4", "i18next": "^25.3.2", - "need4deed-sdk": "0.0.139", + "need4deed-sdk": "0.0.141", "next": "15.3.8", "react": "^19.0.0", "react-day-picker": "^9.13.0", diff --git a/public/locales/de/translations.json b/public/locales/de/translations.json index a55ef906..81790f41 100644 --- a/public/locales/de/translations.json +++ b/public/locales/de/translations.json @@ -1174,8 +1174,12 @@ "validation": { "required": "Dieses Feld ist erforderlich", "websiteInvalid": "Webseite muss mit http:// oder https:// beginnen", + "operatorInvalid": "Ungültiger Träger. Bitte aus der Liste auswählen", "clientLanguagesRequired": "Mindestens eine Sprache ist erforderlich" }, + "placeholders": { + "operatorPlaceholder": "Geben Sie die ersten drei Buchstaben des Trägers ein" + }, "addressStreet": "Straße", "addressPostcode": "PLZ" }, diff --git a/public/locales/en/translations.json b/public/locales/en/translations.json index 5bd0a631..5d58da68 100644 --- a/public/locales/en/translations.json +++ b/public/locales/en/translations.json @@ -1162,8 +1162,12 @@ "validation": { "required": "This field is required", "websiteInvalid": "Website must start with http:// or https://", + "operatorInvalid": "Operator invalid. Please select from the list", "clientLanguagesRequired": "At least one language is required" }, + "placeholders": { + "operatorPlaceholder": "Type the first three letters of the operator" + }, "addressStreet": "Street", "addressPostcode": "Postcode" }, diff --git a/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetails.tsx b/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetails.tsx index a73cff8c..9c7cc661 100644 --- a/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetails.tsx +++ b/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetails.tsx @@ -18,6 +18,7 @@ import { apiLanguagesToFormValues, toLanguagesForForm } from "./formatters"; import { OrganisationDetailsDisplay } from "./OrganisationDetailsDisplay"; import { OrganisationDetailsEdit } from "./OrganisationDetailsEdit"; import { createOrganisationDetailsSchema, OrganisationDetailsFormData } from "./organisationDetailsSchema"; +import { useGetOrganization } from "@/hooks/useGetOrganization"; type Props = { agent: ApiAgentProfileGet; @@ -35,12 +36,17 @@ export const OrganisationDetails = forwardRef(functio const { data: apiLanguages } = useApiLanguages(); const { data: apiAgentTypes = [] } = useApiAgentTypes(); const { data: apiServices = [] } = useApiServices(); + const { data: organizations = [] } = useGetOrganization(); const agentTypeMapping = useMemo(() => createMapping(apiAgentTypes), [apiAgentTypes]); const serviceMapping = useMemo(() => createMapping(apiServices), [apiServices]); + const organizationMapping = useMemo(() => createMapping(organizations), [organizations]); const details = agent.agentDetails; const languagesForForm = toLanguagesForForm(apiLanguages, i18n.language); - const schema = createOrganisationDetailsSchema(t); + const schema = createOrganisationDetailsSchema( + t, + organizations?.map((org) => org.title), + ); // organizationType/services come back from GET /agent as { id, title: {en,de} } // (both languages at once); resolve by id to the title already translated to @@ -51,7 +57,7 @@ export const OrganisationDetails = forwardRef(functio ...details, title: agent.title || "", website: details?.website || "", - operator: details?.operator || agent.operator || "", + operator: details?.operator, clientLanguages: apiLanguagesToFormValues(details?.clientLanguages), addressStreet: details?.addressStreet ?? "", addressPostcode: details?.addressPostcode ?? "", @@ -96,6 +102,7 @@ export const OrganisationDetails = forwardRef(functio const serviceIds = values.services .map((title) => serviceMapping.titleToId[title]) .filter((id): id is number => id !== undefined); + const organizationId = organizationMapping.titleToId[values.operator]; updateOrganization( { @@ -106,6 +113,7 @@ export const OrganisationDetails = forwardRef(functio addressPostcode: values.addressPostcode, ...(typeId !== undefined && { typeId }), serviceIds, + ...(organizationId !== undefined && { organizationId }), }, { onSuccess: () => { @@ -124,6 +132,7 @@ export const OrganisationDetails = forwardRef(functio languagesForForm={languagesForForm} organizationTypeOptions={apiAgentTypes.map((agentType) => agentType.title)} servicesOptions={apiServices.map((service) => service.title)} + operatorOptions={organizations?.map((org) => org.title)} onCancel={handleCancel} onSubmit={handleSubmit(onSubmit)} /> diff --git a/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetailsDisplay.tsx b/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetailsDisplay.tsx index 963ac48d..7ee60342 100644 --- a/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetailsDisplay.tsx +++ b/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetailsDisplay.tsx @@ -16,7 +16,6 @@ export const OrganisationDetailsDisplay = ({ rawClientLanguages, address }: Prop const { t } = useTranslation(); const { watch } = useFormContext(); const values = watch(); - return ( void; onSubmit: () => void; }; @@ -22,6 +24,7 @@ export const OrganisationDetailsEdit = ({ languagesForForm, organizationTypeOptions, servicesOptions, + operatorOptions, onCancel, onSubmit, }: Props) => { @@ -31,6 +34,16 @@ export const OrganisationDetailsEdit = ({ formState: { errors, isDirty, isValid }, } = useFormContext(); + const displayOperators = useCallback( + (value: string) => { + if (value.length >= 3) { + return operatorOptions.filter((op) => op.includes(value)); + } else { + return []; + } + }, + [operatorOptions], + ); return ( <> @@ -123,14 +136,18 @@ export const OrganisationDetailsEdit = ({ name="operator" control={control} render={({ field }) => ( - + <> + + )} /> string) => { +export const createOrganisationDetailsSchema = (t: (key: string) => string, validOperators: string[]) => { const required = t(`${i18nPrefix}.required`); return z.object({ @@ -26,7 +26,12 @@ export const createOrganisationDetailsSchema = (t: (key: string) => string) => { // Stores the translated title (like `district` elsewhere), resolved // back to an id at submit time via AgentType/Service option mappings. organizationType: z.string().min(1, required), - operator: z.string().min(1, required), + operator: z + .string() + .min(1, required) + .refine((val) => validOperators.includes(val), { + message: t(`${i18nPrefix}.operatorInvalid`), + }), services: z.array(z.string()).min(1, required), clientLanguages: z.array(languageObjectSchema).min(1, t(`${i18nPrefix}.clientLanguagesRequired`)), }); diff --git a/src/components/Dashboard/Profile/sections/ProfileHeader/agent/constants.ts b/src/components/Dashboard/Profile/sections/ProfileHeader/agent/constants.ts index c2324b82..62633abc 100644 --- a/src/components/Dashboard/Profile/sections/ProfileHeader/agent/constants.ts +++ b/src/components/Dashboard/Profile/sections/ProfileHeader/agent/constants.ts @@ -2,12 +2,14 @@ import { EMPTY_PLACEHOLDER_VALUE } from "@/config/constants"; import { TFunction } from "i18next"; import { AgentEngagementStatus, AgentTrustLevel, AgentVolunteerSearch, ApiAgentProfileGet } from "../../../types/agent"; -export const createEngagementStatusLabelMap = (t: TFunction): Record => ({ - [AgentEngagementStatus.NEW]: t("dashboard.agentProfile.status.engagement.new"), - [AgentEngagementStatus.ACTIVE]: t("dashboard.agentProfile.status.engagement.active"), - [AgentEngagementStatus.UNRESPONSIVE]: t("dashboard.agentProfile.status.engagement.unresponsive"), - [AgentEngagementStatus.INACTIVE]: t("dashboard.agentProfile.status.engagement.inactive"), -}); +export const createEngagementStatusLabelMap = (t: TFunction): Record => + // @ts-expect-error TODO - Add INCONTACT and TRIED_TO_CONTACT types + ({ + [AgentEngagementStatus.NEW]: t("dashboard.agentProfile.status.engagement.new"), + [AgentEngagementStatus.ACTIVE]: t("dashboard.agentProfile.status.engagement.active"), + [AgentEngagementStatus.UNRESPONSIVE]: t("dashboard.agentProfile.status.engagement.unresponsive"), + [AgentEngagementStatus.INACTIVE]: t("dashboard.agentProfile.status.engagement.inactive"), + }); export const AGENT_DIALOG_STATUSES = [AgentEngagementStatus.UNRESPONSIVE, AgentEngagementStatus.INACTIVE] as const; diff --git a/src/components/Dashboard/common/statusMaps.ts b/src/components/Dashboard/common/statusMaps.ts index f33beb84..35403b12 100644 --- a/src/components/Dashboard/common/statusMaps.ts +++ b/src/components/Dashboard/common/statusMaps.ts @@ -15,6 +15,7 @@ import { AgentEngagementStatusType, AgentTrustType, AgentVolunteerSearchType } f export type StatusValue = AgentEngagementStatusType | AgentVolunteerSearchType | AgentTrustType; +// @ts-expect-error - TODO: Add INCONTACT and TRIED_TO_CONTACT types export const statusColorMap: Record = { [AgentEngagementStatusType.ACTIVE]: "var(--color-green-100)", [AgentEngagementStatusType.UNRESPONSIVE]: "var(--color-grey-50)", @@ -30,6 +31,7 @@ export const statusColorMap: Record = { type IconComponent = React.ComponentType<{ size?: number; color?: string }>; +// @ts-expect-error - TODO: Add INCONTACT and TRIED_TO_CONTACT types export const statusIconMap: Record = { [AgentEngagementStatusType.ACTIVE]: ChartLineIcon, [AgentEngagementStatusType.UNRESPONSIVE]: PhoneXIcon, diff --git a/src/components/EditableField/EditableField.tsx b/src/components/EditableField/EditableField.tsx index dc8fbfe5..d74b33a1 100644 --- a/src/components/EditableField/EditableField.tsx +++ b/src/components/EditableField/EditableField.tsx @@ -264,7 +264,7 @@ const StepperValue = styled.span` user-select: none; `; -type EditableFieldType = "text" | "textarea" | "number" | "stepper" | "checkbox-list" | "radio-list"; +type EditableFieldType = "text" | "textarea" | "number" | "stepper" | "checkbox-list" | "radio-list" | "autocomplete"; export interface EditableFieldRef { getValue: () => T; @@ -555,6 +555,65 @@ export const EditableField = forwardRef(function EditableField )} + + {type === "autocomplete" && ( + + setOpen((o) => !o)}> + + { + const v = e.target.value as T; + setLocalValue(v); + setValue(v); + setOpen(true); + }} + style={{ border: "none", padding: 0 }} + /> + {Boolean(localValue) && ( + { + const v = "" as T; + setLocalValue(v); + setValue(v); + }} + style={{ alignSelf: "flex-start", marginTop: "0px", marginRight: "0px" }} + > + + + )} + + + + + + {open && options.length > 0 && ( + + {options.map((option) => { + const isSelected = localValue === option; + return ( + { + const v = option as T; + setLocalValue(v); + setValue(v); + setOpen(false); + }} + > + {}} /> + {option} + + ); + })} + + )} + + )} {error && (

diff --git a/src/hooks/useGetOrganization.ts b/src/hooks/useGetOrganization.ts new file mode 100644 index 00000000..84cc8b08 --- /dev/null +++ b/src/hooks/useGetOrganization.ts @@ -0,0 +1,18 @@ +import { ApiOrganizationGetList } from "need4deed-sdk"; +import { useGetQuery } from "./useGetQuery"; +import { apiPathOrganization, cacheTTL } from "@/config/constants"; + +export const useGetOrganization = () => { + const { data, isLoading, isError, error } = useGetQuery({ + queryKey: ["organization"], + apiPath: `${apiPathOrganization}`, + staleTime: cacheTTL, + }); + + return { + data, + isLoading, + isError, + error, + }; +}; diff --git a/yarn.lock b/yarn.lock index 41ba0761..05367518 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2412,10 +2412,10 @@ natural-compare@^1.4.0: resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -need4deed-sdk@0.0.139: - version "0.0.139" - resolved "https://registry.yarnpkg.com/need4deed-sdk/-/need4deed-sdk-0.0.139.tgz#34ca63577a104dcaa3353d3b1c6c9661da182c40" - integrity sha512-gU3wlLF4sUxz9azKUBcceuiOgUmt1Q6Km6sXvVWzSDbZa7BieXu9Xr2Lz7NQDVZxMM817nDt5y8CLfrKBexvrw== +need4deed-sdk@0.0.141: + version "0.0.141" + resolved "https://registry.yarnpkg.com/need4deed-sdk/-/need4deed-sdk-0.0.141.tgz#f8f62efc5f48e99f03e935a0e7dba3970d7ba7bd" + integrity sha512-zGjp4hiArKMfWumv/dhQqulMOf4FL9DxKTkorEzI/bHOE7BV2zoQqUa3zlt6RRI5CX1I8065PatiAB98ImCtkg== next@15.3.8: version "15.3.8" From a4f9e4db37befcaf2be77efa1e8f2957cc55b68c Mon Sep 17 00:00:00 2001 From: DarrellRoberts Date: Tue, 11 Aug 2026 10:33:18 +0200 Subject: [PATCH 2/5] adds hint to autocomplete & reverts initvalues for operator --- public/locales/de/translations.json | 4 +++- public/locales/en/translations.json | 4 +++- .../sections/OrganisationDetails/OrganisationDetails.tsx | 2 +- .../sections/OrganisationDetails/OrganisationDetailsEdit.tsx | 5 +++-- .../OrganisationDetails/organisationDetailsSchema.ts | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/public/locales/de/translations.json b/public/locales/de/translations.json index 81790f41..897f7844 100644 --- a/public/locales/de/translations.json +++ b/public/locales/de/translations.json @@ -1174,7 +1174,9 @@ "validation": { "required": "Dieses Feld ist erforderlich", "websiteInvalid": "Webseite muss mit http:// oder https:// beginnen", - "operatorInvalid": "Ungültiger Träger. Bitte aus der Liste auswählen", + "operatorRequired": "Es sind mindestens 3 Zeichen erforderlich.", + "operatorHint": "Geben Sie die ersten drei Buchstaben ein, damit die Liste angezeigt wird, und wählen Sie aus der Liste aus. Wenn die Liste nicht erscheint, ist der Träger ungültig.", + "operatorInvalid": "Ungültiger Träger. Bitte wählen Sie aus der Liste oder versuchen Sie es mit einem anderen Träger.", "clientLanguagesRequired": "Mindestens eine Sprache ist erforderlich" }, "placeholders": { diff --git a/public/locales/en/translations.json b/public/locales/en/translations.json index 5d58da68..9f9837c7 100644 --- a/public/locales/en/translations.json +++ b/public/locales/en/translations.json @@ -1162,7 +1162,9 @@ "validation": { "required": "This field is required", "websiteInvalid": "Website must start with http:// or https://", - "operatorInvalid": "Operator invalid. Please select from the list", + "operatorRequired": "A minimum of 3 characters is needed", + "operatorHint": "Type first three letters for the list to appear and select from the list. If the list doesn't appear, Operator is invalid.", + "operatorInvalid": "Operator invalid. Either select from the list or try another Operator", "clientLanguagesRequired": "At least one language is required" }, "placeholders": { diff --git a/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetails.tsx b/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetails.tsx index 9c7cc661..8b1c825e 100644 --- a/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetails.tsx +++ b/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetails.tsx @@ -57,7 +57,7 @@ export const OrganisationDetails = forwardRef(functio ...details, title: agent.title || "", website: details?.website || "", - operator: details?.operator, + operator: details?.operator || agent.operator || "", clientLanguages: apiLanguagesToFormValues(details?.clientLanguages), addressStreet: details?.addressStreet ?? "", addressPostcode: details?.addressPostcode ?? "", diff --git a/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetailsEdit.tsx b/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetailsEdit.tsx index 89ef5396..15f57d4d 100644 --- a/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetailsEdit.tsx +++ b/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetailsEdit.tsx @@ -36,8 +36,8 @@ export const OrganisationDetailsEdit = ({ const displayOperators = useCallback( (value: string) => { - if (value.length >= 3) { - return operatorOptions.filter((op) => op.includes(value)); + if (value?.length >= 3) { + return operatorOptions.filter((op) => op.includes(value.toLowerCase())); } else { return []; } @@ -146,6 +146,7 @@ export const OrganisationDetailsEdit = ({ errorMessage={errors.operator?.message} options={displayOperators(field.value)} placeholder={t(`${i18nPrefix}.placeholders.operatorPlaceholder`)} + hint={t(`dashboard.agentProfile.organisationDetails.validation.operatorHint`)} /> )} diff --git a/src/components/Dashboard/Profile/sections/OrganisationDetails/organisationDetailsSchema.ts b/src/components/Dashboard/Profile/sections/OrganisationDetails/organisationDetailsSchema.ts index 09cdd3e5..43daa8ff 100644 --- a/src/components/Dashboard/Profile/sections/OrganisationDetails/organisationDetailsSchema.ts +++ b/src/components/Dashboard/Profile/sections/OrganisationDetails/organisationDetailsSchema.ts @@ -28,7 +28,7 @@ export const createOrganisationDetailsSchema = (t: (key: string) => string, vali organizationType: z.string().min(1, required), operator: z .string() - .min(1, required) + .min(3, t(`${i18nPrefix}.operatorRequired`)) .refine((val) => validOperators.includes(val), { message: t(`${i18nPrefix}.operatorInvalid`), }), From e072dcd708013993dfcef1d6392e1a31ac0b483a Mon Sep 17 00:00:00 2001 From: arturasmckwcz Date: Wed, 26 Aug 2026 11:23:58 +0000 Subject: [PATCH 3/5] fix: remove error appreciations and gitignore claude local state --- .gitignore | 3 +++ src/components/Dashboard/common/statusMaps.ts | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index fe65afbc..8131447b 100644 --- a/.gitignore +++ b/.gitignore @@ -47,5 +47,8 @@ dev/ dev.* .env.local +# claude code local worktree scratch +.claude/worktrees/ + # prettier .prettierignore \ No newline at end of file diff --git a/src/components/Dashboard/common/statusMaps.ts b/src/components/Dashboard/common/statusMaps.ts index ed896b2f..2e7c3f0b 100644 --- a/src/components/Dashboard/common/statusMaps.ts +++ b/src/components/Dashboard/common/statusMaps.ts @@ -1,4 +1,3 @@ -import type React from "react"; import { BinocularsIcon, ChartLineIcon, @@ -12,10 +11,10 @@ import { StopCircleIcon, } from "@phosphor-icons/react"; import { AgentEngagementStatusType, AgentTrustType, AgentVolunteerSearchType } from "need4deed-sdk"; +import type React from "react"; export type StatusValue = AgentEngagementStatusType | AgentVolunteerSearchType | AgentTrustType; -// @ts-expect-error - TODO: Add INCONTACT and TRIED_TO_CONTACT types export const statusColorMap: Record = { [AgentEngagementStatusType.ACTIVE]: "var(--color-green-100)", [AgentEngagementStatusType.UNRESPONSIVE]: "var(--color-grey-50)", @@ -33,7 +32,6 @@ export const statusColorMap: Record = { type IconComponent = React.ComponentType<{ size?: number; color?: string }>; -// @ts-expect-error - TODO: Add INCONTACT and TRIED_TO_CONTACT types export const statusIconMap: Record = { [AgentEngagementStatusType.ACTIVE]: ChartLineIcon, [AgentEngagementStatusType.UNRESPONSIVE]: PhoneXIcon, From c233c0f699274472922c64aee2ebdc4283241c36 Mon Sep 17 00:00:00 2001 From: DarrellRoberts Date: Thu, 27 Aug 2026 17:51:21 +0200 Subject: [PATCH 4/5] adds additional lowercase guard & changes onclick handler --- .../OrganisationDetails/OrganisationDetailsEdit.tsx | 2 +- src/components/EditableField/EditableField.tsx | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetailsEdit.tsx b/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetailsEdit.tsx index 15f57d4d..ca944053 100644 --- a/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetailsEdit.tsx +++ b/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetailsEdit.tsx @@ -37,7 +37,7 @@ export const OrganisationDetailsEdit = ({ const displayOperators = useCallback( (value: string) => { if (value?.length >= 3) { - return operatorOptions.filter((op) => op.includes(value.toLowerCase())); + return operatorOptions.filter((op) => op.toLowerCase().includes(value.toLowerCase())); } else { return []; } diff --git a/src/components/EditableField/EditableField.tsx b/src/components/EditableField/EditableField.tsx index a5b1e6f4..a998e9ce 100644 --- a/src/components/EditableField/EditableField.tsx +++ b/src/components/EditableField/EditableField.tsx @@ -562,7 +562,12 @@ export const EditableField = forwardRef(function EditableField - setOpen((o) => !o)}> + { + if (value) setOpen(true); + }} + > )} - - {open && options.length > 0 && ( From 15cb761f6baacb4aa82109980110afcc83cd81c3 Mon Sep 17 00:00:00 2001 From: DarrellRoberts Date: Wed, 2 Sep 2026 12:36:57 +0200 Subject: [PATCH 5/5] adds onblur, local val & removes strict zod validation --- .../OrganisationDetails/OrganisationDetails.tsx | 5 +---- .../OrganisationDetails/organisationDetailsSchema.ts | 9 ++------- src/components/EditableField/EditableField.tsx | 12 ++++++++---- src/hooks/useGetOrganization.ts | 1 + 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetails.tsx b/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetails.tsx index 8b1c825e..96b8caae 100644 --- a/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetails.tsx +++ b/src/components/Dashboard/Profile/sections/OrganisationDetails/OrganisationDetails.tsx @@ -43,10 +43,7 @@ export const OrganisationDetails = forwardRef(functio const details = agent.agentDetails; const languagesForForm = toLanguagesForForm(apiLanguages, i18n.language); - const schema = createOrganisationDetailsSchema( - t, - organizations?.map((org) => org.title), - ); + const schema = createOrganisationDetailsSchema(t); // organizationType/services come back from GET /agent as { id, title: {en,de} } // (both languages at once); resolve by id to the title already translated to diff --git a/src/components/Dashboard/Profile/sections/OrganisationDetails/organisationDetailsSchema.ts b/src/components/Dashboard/Profile/sections/OrganisationDetails/organisationDetailsSchema.ts index 43daa8ff..264e149c 100644 --- a/src/components/Dashboard/Profile/sections/OrganisationDetails/organisationDetailsSchema.ts +++ b/src/components/Dashboard/Profile/sections/OrganisationDetails/organisationDetailsSchema.ts @@ -9,7 +9,7 @@ const languageObjectSchema = z.object({ const urlRegex = /^https?:\/\/.+/; -export const createOrganisationDetailsSchema = (t: (key: string) => string, validOperators: string[]) => { +export const createOrganisationDetailsSchema = (t: (key: string) => string) => { const required = t(`${i18nPrefix}.required`); return z.object({ @@ -26,12 +26,7 @@ export const createOrganisationDetailsSchema = (t: (key: string) => string, vali // Stores the translated title (like `district` elsewhere), resolved // back to an id at submit time via AgentType/Service option mappings. organizationType: z.string().min(1, required), - operator: z - .string() - .min(3, t(`${i18nPrefix}.operatorRequired`)) - .refine((val) => validOperators.includes(val), { - message: t(`${i18nPrefix}.operatorInvalid`), - }), + operator: z.string().min(1, required), services: z.array(z.string()).min(1, required), clientLanguages: z.array(languageObjectSchema).min(1, t(`${i18nPrefix}.clientLanguagesRequired`)), }); diff --git a/src/components/EditableField/EditableField.tsx b/src/components/EditableField/EditableField.tsx index a998e9ce..405ee519 100644 --- a/src/components/EditableField/EditableField.tsx +++ b/src/components/EditableField/EditableField.tsx @@ -565,7 +565,7 @@ export const EditableField = forwardRef(function EditableField { - if (value) setOpen(true); + if (localValue) setOpen((o) => !o); }} > @@ -579,15 +579,19 @@ export const EditableField = forwardRef(function EditableField {Boolean(localValue) && ( { + onClick={(e) => { + e.stopPropagation(); const v = "" as T; setLocalValue(v); setValue(v); + setOpen(false); }} style={{ alignSelf: "flex-start", marginTop: "0px", marginRight: "0px" }} > @@ -597,7 +601,7 @@ export const EditableField = forwardRef(function EditableField - {open && options.length > 0 && ( + {open && ( {options.map((option) => { const isSelected = localValue === option; @@ -612,7 +616,7 @@ export const EditableField = forwardRef(function EditableField - {}} /> + {}} /> {option} ); diff --git a/src/hooks/useGetOrganization.ts b/src/hooks/useGetOrganization.ts index 84cc8b08..6deb1967 100644 --- a/src/hooks/useGetOrganization.ts +++ b/src/hooks/useGetOrganization.ts @@ -7,6 +7,7 @@ export const useGetOrganization = () => { queryKey: ["organization"], apiPath: `${apiPathOrganization}`, staleTime: cacheTTL, + addLang: false, }); return {