@open-mercato/core 0.6.4-develop.3929.1.fcf7afece2 → 0.6.4-develop.3944.1.4100aa7fbe

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/customers/backend/customers/deals/create/page.js +3 -61
  3. package/dist/modules/customers/backend/customers/deals/create/page.js.map +2 -2
  4. package/dist/modules/customers/components/detail/DealForm.js +2 -0
  5. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  6. package/dist/modules/customers/components/detail/create/CreateDealForm.js +233 -0
  7. package/dist/modules/customers/components/detail/create/CreateDealForm.js.map +7 -0
  8. package/dist/modules/customers/components/detail/create/DealAssociationsField.js +209 -0
  9. package/dist/modules/customers/components/detail/create/DealAssociationsField.js.map +7 -0
  10. package/dist/modules/customers/components/detail/create/DealAssociationsSection.js +67 -0
  11. package/dist/modules/customers/components/detail/create/DealAssociationsSection.js.map +7 -0
  12. package/dist/modules/customers/components/detail/create/DealCreateSidebar.js +73 -0
  13. package/dist/modules/customers/components/detail/create/DealCreateSidebar.js.map +7 -0
  14. package/dist/modules/customers/components/detail/create/DealCurrencyField.js +92 -0
  15. package/dist/modules/customers/components/detail/create/DealCurrencyField.js.map +7 -0
  16. package/dist/modules/customers/components/detail/create/DealCustomAttributes.js +81 -0
  17. package/dist/modules/customers/components/detail/create/DealCustomAttributes.js.map +7 -0
  18. package/dist/modules/customers/components/detail/create/DealDetailsFields.js +171 -0
  19. package/dist/modules/customers/components/detail/create/DealDetailsFields.js.map +7 -0
  20. package/dist/modules/customers/components/detail/create/DealFormField.js +24 -0
  21. package/dist/modules/customers/components/detail/create/DealFormField.js.map +7 -0
  22. package/dist/modules/customers/components/detail/create/DealSectionCard.js +29 -0
  23. package/dist/modules/customers/components/detail/create/DealSectionCard.js.map +7 -0
  24. package/dist/modules/customers/components/detail/create/DealTipsCard.js +19 -0
  25. package/dist/modules/customers/components/detail/create/DealTipsCard.js.map +7 -0
  26. package/dist/modules/customers/components/detail/create/PipelineSelect.js +41 -0
  27. package/dist/modules/customers/components/detail/create/PipelineSelect.js.map +7 -0
  28. package/dist/modules/customers/components/detail/create/PipelineStageSelect.js +49 -0
  29. package/dist/modules/customers/components/detail/create/PipelineStageSelect.js.map +7 -0
  30. package/dist/modules/customers/components/detail/create/SuffixInput.js +21 -0
  31. package/dist/modules/customers/components/detail/create/SuffixInput.js.map +7 -0
  32. package/dist/modules/customers/components/detail/create/dealCustomFieldControl.js +270 -0
  33. package/dist/modules/customers/components/detail/create/dealCustomFieldControl.js.map +7 -0
  34. package/dist/modules/customers/components/detail/create/dealFormTypes.js +17 -0
  35. package/dist/modules/customers/components/detail/create/dealFormTypes.js.map +7 -0
  36. package/dist/modules/customers/components/detail/create/dealNumericInput.js +16 -0
  37. package/dist/modules/customers/components/detail/create/dealNumericInput.js.map +7 -0
  38. package/dist/modules/customers/components/detail/create/useDealCustomFields.js +93 -0
  39. package/dist/modules/customers/components/detail/create/useDealCustomFields.js.map +7 -0
  40. package/dist/modules/customers/components/detail/create/useDealPipelines.js +59 -0
  41. package/dist/modules/customers/components/detail/create/useDealPipelines.js.map +7 -0
  42. package/dist/modules/customers/components/formConfig.js +4 -2
  43. package/dist/modules/customers/components/formConfig.js.map +2 -2
  44. package/dist/modules/dictionaries/components/DictionaryEntrySelect.js +5 -2
  45. package/dist/modules/dictionaries/components/DictionaryEntrySelect.js.map +2 -2
  46. package/package.json +7 -7
  47. package/src/modules/customers/backend/customers/deals/create/page.tsx +3 -64
  48. package/src/modules/customers/components/detail/DealForm.tsx +2 -0
  49. package/src/modules/customers/components/detail/create/CreateDealForm.tsx +254 -0
  50. package/src/modules/customers/components/detail/create/DealAssociationsField.tsx +253 -0
  51. package/src/modules/customers/components/detail/create/DealAssociationsSection.tsx +72 -0
  52. package/src/modules/customers/components/detail/create/DealCreateSidebar.tsx +79 -0
  53. package/src/modules/customers/components/detail/create/DealCurrencyField.tsx +108 -0
  54. package/src/modules/customers/components/detail/create/DealCustomAttributes.tsx +118 -0
  55. package/src/modules/customers/components/detail/create/DealDetailsFields.tsx +171 -0
  56. package/src/modules/customers/components/detail/create/DealFormField.tsx +39 -0
  57. package/src/modules/customers/components/detail/create/DealSectionCard.tsx +40 -0
  58. package/src/modules/customers/components/detail/create/DealTipsCard.tsx +26 -0
  59. package/src/modules/customers/components/detail/create/PipelineSelect.tsx +55 -0
  60. package/src/modules/customers/components/detail/create/PipelineStageSelect.tsx +70 -0
  61. package/src/modules/customers/components/detail/create/SuffixInput.tsx +20 -0
  62. package/src/modules/customers/components/detail/create/dealCustomFieldControl.tsx +310 -0
  63. package/src/modules/customers/components/detail/create/dealFormTypes.ts +29 -0
  64. package/src/modules/customers/components/detail/create/dealNumericInput.ts +20 -0
  65. package/src/modules/customers/components/detail/create/useDealCustomFields.ts +118 -0
  66. package/src/modules/customers/components/detail/create/useDealPipelines.ts +80 -0
  67. package/src/modules/customers/components/formConfig.tsx +3 -0
  68. package/src/modules/customers/i18n/de.json +26 -0
  69. package/src/modules/customers/i18n/en.json +26 -0
  70. package/src/modules/customers/i18n/es.json +26 -0
  71. package/src/modules/customers/i18n/pl.json +26 -0
  72. package/src/modules/dictionaries/components/DictionaryEntrySelect.tsx +12 -1
@@ -1,4 +1,4 @@
1
- [build:core] found 2615 entry points
1
+ [build:core] found 2634 entry points
2
2
  [build:core] built successfully
3
3
  [build:core:generated] found 172 entry points
4
4
  [build:core:generated] built successfully
@@ -1,13 +1,9 @@
1
1
  "use client";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
- import { useRouter, useSearchParams } from "next/navigation";
4
+ import { useSearchParams } from "next/navigation";
5
5
  import { Page, PageBody } from "@open-mercato/ui/backend/Page";
6
- import { flash } from "@open-mercato/ui/backend/FlashMessages";
7
- import { createCrud } from "@open-mercato/ui/backend/utils/crud";
8
- import { useT } from "@open-mercato/shared/lib/i18n/context";
9
- import { DealForm } from "../../../../components/detail/DealForm.js";
10
- import { useCurrencyDictionary } from "../../../../components/detail/hooks/useCurrencyDictionary.js";
6
+ import { CreateDealForm } from "../../../../components/detail/create/CreateDealForm.js";
11
7
  const DEFAULT_RETURN_TO = "/backend/customers/deals";
12
8
  function resolveReturnTo(value) {
13
9
  if (!value) return DEFAULT_RETURN_TO;
@@ -15,66 +11,12 @@ function resolveReturnTo(value) {
15
11
  return value;
16
12
  }
17
13
  function CreateDealPage() {
18
- const t = useT();
19
- const router = useRouter();
20
14
  const searchParams = useSearchParams();
21
15
  const returnTo = React.useMemo(
22
16
  () => resolveReturnTo(searchParams?.get("returnTo") ?? null),
23
17
  [searchParams]
24
18
  );
25
- const [isSubmitting, setIsSubmitting] = React.useState(false);
26
- useCurrencyDictionary();
27
- const handleCancel = React.useCallback(() => {
28
- router.push(returnTo);
29
- }, [router, returnTo]);
30
- const handleSubmit = React.useCallback(
31
- async ({ base, custom }) => {
32
- if (isSubmitting) return;
33
- setIsSubmitting(true);
34
- try {
35
- const payload = {
36
- title: base.title,
37
- status: base.status ?? void 0,
38
- pipelineStage: base.pipelineStage ?? void 0,
39
- pipelineId: base.pipelineId ?? void 0,
40
- pipelineStageId: base.pipelineStageId ?? void 0,
41
- valueAmount: typeof base.valueAmount === "number" ? base.valueAmount : void 0,
42
- valueCurrency: base.valueCurrency ?? void 0,
43
- probability: typeof base.probability === "number" ? base.probability : void 0,
44
- expectedCloseAt: base.expectedCloseAt ?? void 0,
45
- description: base.description ?? void 0,
46
- personIds: Array.isArray(base.personIds) && base.personIds.length ? base.personIds : void 0,
47
- companyIds: Array.isArray(base.companyIds) && base.companyIds.length ? base.companyIds : void 0
48
- };
49
- if (Object.keys(custom).length) payload.customFields = custom;
50
- await createCrud("customers/deals", payload, {
51
- errorMessage: t("customers.deals.create.error", "Failed to create deal.")
52
- });
53
- flash(t("customers.people.detail.deals.success", "Deal created."), "success");
54
- router.push(returnTo);
55
- } catch (err) {
56
- const message = err instanceof Error ? err.message : t("customers.deals.create.error", "Failed to create deal.");
57
- flash(message, "error");
58
- throw err instanceof Error ? err : new Error(message);
59
- } finally {
60
- setIsSubmitting(false);
61
- }
62
- },
63
- [isSubmitting, returnTo, router, t]
64
- );
65
- return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
66
- DealForm,
67
- {
68
- mode: "create",
69
- onSubmit: handleSubmit,
70
- onCancel: handleCancel,
71
- isSubmitting,
72
- submitLabel: t("customers.deals.create.submit", "Create deal"),
73
- embedded: false,
74
- title: t("customers.deals.create.title", "Create deal"),
75
- backHref: returnTo
76
- }
77
- ) }) });
19
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(CreateDealForm, { returnTo }) }) });
78
20
  }
79
21
  export {
80
22
  CreateDealPage as default
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/customers/backend/customers/deals/create/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { createCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { DealForm, type DealFormSubmitPayload } from '../../../../components/detail/DealForm'\nimport { useCurrencyDictionary } from '../../../../components/detail/hooks/useCurrencyDictionary'\n\nconst DEFAULT_RETURN_TO = '/backend/customers/deals'\n\n/**\n * Only honor `returnTo` when it points back into the deals area of the backoffice.\n * Without the prefix guard, this would be a textbook open-redirect: an attacker could\n * craft `/backend/customers/deals/create?returnTo=https://evil.example.com` and the\n * page would happily navigate the operator off-product after a successful save.\n */\nfunction resolveReturnTo(value: string | null | undefined): string {\n if (!value) return DEFAULT_RETURN_TO\n if (!value.startsWith('/backend/customers/deals')) return DEFAULT_RETURN_TO\n return value\n}\n\nexport default function CreateDealPage() {\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const returnTo = React.useMemo(\n () => resolveReturnTo(searchParams?.get('returnTo') ?? null),\n [searchParams],\n )\n const [isSubmitting, setIsSubmitting] = React.useState(false)\n useCurrencyDictionary()\n\n const handleCancel = React.useCallback(() => {\n router.push(returnTo)\n }, [router, returnTo])\n\n const handleSubmit = React.useCallback(\n async ({ base, custom }: DealFormSubmitPayload) => {\n if (isSubmitting) return\n setIsSubmitting(true)\n try {\n const payload: Record<string, unknown> = {\n title: base.title,\n status: base.status ?? undefined,\n pipelineStage: base.pipelineStage ?? undefined,\n pipelineId: base.pipelineId ?? undefined,\n pipelineStageId: base.pipelineStageId ?? undefined,\n valueAmount: typeof base.valueAmount === 'number' ? base.valueAmount : undefined,\n valueCurrency: base.valueCurrency ?? undefined,\n probability: typeof base.probability === 'number' ? base.probability : undefined,\n expectedCloseAt: base.expectedCloseAt ?? undefined,\n description: base.description ?? undefined,\n personIds: Array.isArray(base.personIds) && base.personIds.length ? base.personIds : undefined,\n companyIds: Array.isArray(base.companyIds) && base.companyIds.length ? base.companyIds : undefined,\n }\n if (Object.keys(custom).length) payload.customFields = custom\n\n await createCrud('customers/deals', payload, {\n errorMessage: t('customers.deals.create.error', 'Failed to create deal.'),\n })\n flash(t('customers.people.detail.deals.success', 'Deal created.'), 'success')\n router.push(returnTo)\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : t('customers.deals.create.error', 'Failed to create deal.')\n flash(message, 'error')\n throw err instanceof Error ? err : new Error(message)\n } finally {\n setIsSubmitting(false)\n }\n },\n [isSubmitting, returnTo, router, t],\n )\n\n return (\n <Page>\n <PageBody>\n <DealForm\n mode=\"create\"\n onSubmit={handleSubmit}\n onCancel={handleCancel}\n isSubmitting={isSubmitting}\n submitLabel={t('customers.deals.create.submit', 'Create deal')}\n embedded={false}\n title={t('customers.deals.create.title', 'Create deal')}\n backHref={returnTo}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
- "mappings": ";AAmFQ;AAjFR,YAAY,WAAW;AACvB,SAAS,WAAW,uBAAuB;AAC3C,SAAS,MAAM,gBAAgB;AAC/B,SAAS,aAAa;AACtB,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AACrB,SAAS,gBAA4C;AACrD,SAAS,6BAA6B;AAEtC,MAAM,oBAAoB;AAQ1B,SAAS,gBAAgB,OAA0C;AACjE,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,CAAC,MAAM,WAAW,0BAA0B,EAAG,QAAO;AAC1D,SAAO;AACT;AAEe,SAAR,iBAAkC;AACvC,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,UAAU;AACzB,QAAM,eAAe,gBAAgB;AACrC,QAAM,WAAW,MAAM;AAAA,IACrB,MAAM,gBAAgB,cAAc,IAAI,UAAU,KAAK,IAAI;AAAA,IAC3D,CAAC,YAAY;AAAA,EACf;AACA,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAS,KAAK;AAC5D,wBAAsB;AAEtB,QAAM,eAAe,MAAM,YAAY,MAAM;AAC3C,WAAO,KAAK,QAAQ;AAAA,EACtB,GAAG,CAAC,QAAQ,QAAQ,CAAC;AAErB,QAAM,eAAe,MAAM;AAAA,IACzB,OAAO,EAAE,MAAM,OAAO,MAA6B;AACjD,UAAI,aAAc;AAClB,sBAAgB,IAAI;AACpB,UAAI;AACF,cAAM,UAAmC;AAAA,UACvC,OAAO,KAAK;AAAA,UACZ,QAAQ,KAAK,UAAU;AAAA,UACvB,eAAe,KAAK,iBAAiB;AAAA,UACrC,YAAY,KAAK,cAAc;AAAA,UAC/B,iBAAiB,KAAK,mBAAmB;AAAA,UACzC,aAAa,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AAAA,UACvE,eAAe,KAAK,iBAAiB;AAAA,UACrC,aAAa,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AAAA,UACvE,iBAAiB,KAAK,mBAAmB;AAAA,UACzC,aAAa,KAAK,eAAe;AAAA,UACjC,WAAW,MAAM,QAAQ,KAAK,SAAS,KAAK,KAAK,UAAU,SAAS,KAAK,YAAY;AAAA,UACrF,YAAY,MAAM,QAAQ,KAAK,UAAU,KAAK,KAAK,WAAW,SAAS,KAAK,aAAa;AAAA,QAC3F;AACA,YAAI,OAAO,KAAK,MAAM,EAAE,OAAQ,SAAQ,eAAe;AAEvD,cAAM,WAAW,mBAAmB,SAAS;AAAA,UAC3C,cAAc,EAAE,gCAAgC,wBAAwB;AAAA,QAC1E,CAAC;AACD,cAAM,EAAE,yCAAyC,eAAe,GAAG,SAAS;AAC5E,eAAO,KAAK,QAAQ;AAAA,MACtB,SAAS,KAAK;AACZ,cAAM,UACJ,eAAe,QACX,IAAI,UACJ,EAAE,gCAAgC,wBAAwB;AAChE,cAAM,SAAS,OAAO;AACtB,cAAM,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO;AAAA,MACtD,UAAE;AACA,wBAAgB,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,IACA,CAAC,cAAc,UAAU,QAAQ,CAAC;AAAA,EACpC;AAEA,SACE,oBAAC,QACC,8BAAC,YACC;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,MACA,aAAa,EAAE,iCAAiC,aAAa;AAAA,MAC7D,UAAU;AAAA,MACV,OAAO,EAAE,gCAAgC,aAAa;AAAA,MACtD,UAAU;AAAA;AAAA,EACZ,GACF,GACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useSearchParams } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CreateDealForm } from '../../../../components/detail/create/CreateDealForm'\n\nconst DEFAULT_RETURN_TO = '/backend/customers/deals'\n\n/**\n * Only honor `returnTo` when it points back into the deals area of the backoffice.\n * Without the prefix guard, this would be a textbook open-redirect: an attacker could\n * craft `/backend/customers/deals/create?returnTo=https://evil.example.com` and the\n * page would happily navigate the operator off-product after a successful save.\n */\nfunction resolveReturnTo(value: string | null | undefined): string {\n if (!value) return DEFAULT_RETURN_TO\n if (!value.startsWith('/backend/customers/deals')) return DEFAULT_RETURN_TO\n return value\n}\n\nexport default function CreateDealPage() {\n const searchParams = useSearchParams()\n const returnTo = React.useMemo(\n () => resolveReturnTo(searchParams?.get('returnTo') ?? null),\n [searchParams],\n )\n\n return (\n <Page>\n <PageBody>\n <CreateDealForm returnTo={returnTo} />\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": ";AA+BQ;AA7BR,YAAY,WAAW;AACvB,SAAS,uBAAuB;AAChC,SAAS,MAAM,gBAAgB;AAC/B,SAAS,sBAAsB;AAE/B,MAAM,oBAAoB;AAQ1B,SAAS,gBAAgB,OAA0C;AACjE,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,CAAC,MAAM,WAAW,0BAA0B,EAAG,QAAO;AAC1D,SAAO;AACT;AAEe,SAAR,iBAAkC;AACvC,QAAM,eAAe,gBAAgB;AACrC,QAAM,WAAW,MAAM;AAAA,IACrB,MAAM,gBAAgB,cAAc,IAAI,UAAU,KAAK,IAAI;AAAA,IAC3D,CAAC,YAAY;AAAA,EACf;AAEA,SACE,oBAAC,QACC,8BAAC,YACC,8BAAC,kBAAe,UAAoB,GACtC,GACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -76,6 +76,7 @@ const schema = z.object({
76
76
  personIds: z.array(z.string().trim().min(1)).optional(),
77
77
  companyIds: z.array(z.string().trim().min(1)).optional()
78
78
  }).passthrough();
79
+ const dealFormSchema = schema;
79
80
  import { toDateInputValue as toDateInputValueOrNull } from "@open-mercato/shared/lib/date/format";
80
81
  function toDateInputValue(value) {
81
82
  return toDateInputValueOrNull(value) ?? "";
@@ -894,6 +895,7 @@ export {
894
895
  DealForm,
895
896
  DealPeopleSelector,
896
897
  buildDealValidationError,
898
+ dealFormSchema,
897
899
  DealForm_default as default,
898
900
  useDealAssociationLookups
899
901
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/components/detail/DealForm.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { DictionarySelectField } from '../formConfig'\nimport { createDictionarySelectLabels } from './utils'\nimport { E } from '#generated/entities.ids.generated'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { useCurrencyDictionary } from './hooks/useCurrencyDictionary'\nimport { DictionaryEntrySelect } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport { normalizeCustomFieldSubmitValue } from './customFieldUtils'\n\nexport type DealFormBaseValues = {\n title: string\n status?: string | null\n pipelineStage?: string | null\n pipelineId?: string | null\n pipelineStageId?: string | null\n valueAmount?: number | null\n valueCurrency?: string | null\n probability?: number | null\n expectedCloseAt?: string | null\n description?: string | null\n personIds?: string[]\n companyIds?: string[]\n}\n\nexport type DealFormSubmitPayload = {\n base: DealFormBaseValues\n custom: Record<string, unknown>\n}\n\nexport type DealFormProps = {\n mode: 'create' | 'edit'\n initialValues?: Partial<DealFormBaseValues & Record<string, unknown>>\n onSubmit: (payload: DealFormSubmitPayload) => Promise<void>\n onCancel: () => void\n onDelete?: () => Promise<void> | void\n submitLabel?: string\n cancelLabel?: string\n isSubmitting?: boolean\n embedded?: boolean\n trackDirtyWhenEmbedded?: boolean\n title?: string\n backHref?: string\n hideFooterActions?: boolean\n onDirtyChange?: (dirty: boolean) => void\n collapsibleGroups?: boolean | { pageType: string; chevronPosition?: 'left' | 'right' }\n sortableGroups?: boolean | { pageType: string }\n singleColumnGroups?: boolean\n showAssociationsGroup?: boolean\n showVersionHistory?: boolean\n showCancelAction?: boolean\n}\n\ntype EntityOption = {\n id: string\n label: string\n subtitle?: string | null\n}\n\nexport type DealLookupOption = EntityOption\n\ntype EntityMultiSelectProps = {\n value: string[]\n onChange: (next: string[]) => void\n initialOptions?: EntityOption[]\n placeholder: string\n emptyLabel: string\n loadingLabel: string\n noResultsLabel: string\n removeLabel: string\n errorLabel: string\n search: (query: string) => Promise<EntityOption[]>\n fetchByIds: (ids: string[]) => Promise<EntityOption[]>\n disabled?: boolean\n autoFocus?: boolean\n}\n\nconst DEAL_ENTITY_IDS = [E.customers.customer_deal]\nconst CURRENCY_PRIORITY = ['EUR', 'USD', 'GBP', 'PLN'] as const\n\nconst schema = z.object({\n title: z\n .string()\n .trim()\n .min(1, 'customers.people.detail.deals.titleRequired')\n .max(200, 'customers.people.detail.deals.titleTooLong'),\n status: z\n .string()\n .trim()\n .max(50, 'customers.people.detail.deals.statusTooLong')\n .optional(),\n pipelineStage: z\n .string()\n .trim()\n .max(100, 'customers.people.detail.deals.pipelineTooLong')\n .optional(),\n pipelineId: z.preprocess(\n (v) => (typeof v === 'string' && !v.trim() ? undefined : v),\n z.string().uuid('customers.people.detail.deals.pipelineIdInvalid').optional(),\n ),\n pipelineStageId: z.preprocess(\n (v) => (typeof v === 'string' && !v.trim() ? undefined : v),\n z.string().uuid('customers.people.detail.deals.pipelineStageIdInvalid').optional(),\n ),\n valueAmount: z\n .preprocess((value) => {\n if (value === '' || value === null || value === undefined) return undefined\n if (typeof value === 'number') return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return undefined\n const parsed = Number(trimmed)\n if (Number.isNaN(parsed)) return value\n return parsed\n }\n return value\n }, z\n .number()\n .min(0, 'customers.people.detail.deals.valueInvalid')\n .optional())\n .optional(),\n valueCurrency: z\n .string()\n .transform((value) => value.trim().toUpperCase())\n .refine(\n (value) => !value || /^[A-Z]{3}$/.test(value),\n 'customers.people.detail.deals.currencyInvalid',\n )\n .optional(),\n probability: z\n .preprocess((value) => {\n if (value === '' || value === null || value === undefined) return undefined\n if (typeof value === 'number') return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return undefined\n const parsed = Number(trimmed)\n if (Number.isNaN(parsed)) return value\n return parsed\n }\n return value\n }, z\n .number()\n .min(0, 'customers.people.detail.deals.probabilityInvalid')\n .max(100, 'customers.people.detail.deals.probabilityInvalid')\n .optional())\n .optional(),\n expectedCloseAt: z\n .string()\n .transform((value) => value.trim())\n .refine(\n (value) => {\n if (!value) return true\n const parsed = new Date(value)\n return !Number.isNaN(parsed.getTime())\n },\n 'customers.people.detail.deals.expectedCloseInvalid',\n )\n .optional(),\n description: z.string().max(4000, 'customers.people.detail.deals.descriptionTooLong').optional(),\n personIds: z.array(z.string().trim().min(1)).optional(),\n companyIds: z.array(z.string().trim().min(1)).optional(),\n}).passthrough()\n\nimport { toDateInputValue as toDateInputValueOrNull } from '@open-mercato/shared/lib/date/format'\n\nfunction toDateInputValue(value: string | null | undefined): string {\n return toDateInputValueOrNull(value) ?? ''\n}\n\nfunction normalizeCurrency(value: string | null | undefined): string {\n if (!value) return ''\n return value.trim().slice(0, 3).toUpperCase()\n}\n\nfunction sanitizeIdList(input: unknown): string[] {\n if (!Array.isArray(input)) return []\n const set = new Set<string>()\n input.forEach((candidate) => {\n if (typeof candidate !== 'string') return\n const trimmed = candidate.trim()\n if (!trimmed.length) return\n set.add(trimmed)\n })\n return Array.from(set)\n}\n\nfunction extractPersonOption(record: Record<string, unknown>): EntityOption | null {\n const id = typeof record.id === 'string' ? record.id : null\n if (!id) return null\n const displayName =\n typeof record.displayName === 'string' && record.displayName.trim().length\n ? record.displayName.trim()\n : typeof record.display_name === 'string' && record.display_name.trim().length\n ? (record.display_name as string).trim()\n : null\n const email =\n typeof record.primaryEmail === 'string' && record.primaryEmail.trim().length\n ? record.primaryEmail.trim()\n : typeof record.primary_email === 'string' && record.primary_email.trim().length\n ? (record.primary_email as string).trim()\n : null\n const label = displayName ?? email ?? id\n const subtitle = email && email !== label ? email : null\n return { id, label, subtitle }\n}\n\nfunction extractCompanyOption(record: Record<string, unknown>): EntityOption | null {\n const id = typeof record.id === 'string' ? record.id : null\n if (!id) return null\n const displayName =\n typeof record.displayName === 'string' && record.displayName.trim().length\n ? record.displayName.trim()\n : typeof record.display_name === 'string' && record.display_name.trim().length\n ? (record.display_name as string).trim()\n : null\n const domain =\n typeof record.domain === 'string' && record.domain.trim().length\n ? record.domain.trim()\n : typeof record.websiteUrl === 'string' && record.websiteUrl.trim().length\n ? record.websiteUrl.trim()\n : typeof record.website_url === 'string' && record.website_url.trim().length\n ? (record.website_url as string).trim()\n : null\n const label = displayName ?? domain ?? id\n const subtitle = domain && domain !== label ? domain : null\n return { id, label, subtitle }\n}\n\nfunction EntityMultiSelect({\n value,\n onChange,\n initialOptions = [],\n placeholder,\n emptyLabel,\n loadingLabel,\n noResultsLabel,\n removeLabel,\n errorLabel,\n search,\n fetchByIds,\n disabled = false,\n autoFocus = false,\n}: EntityMultiSelectProps) {\n const [input, setInput] = React.useState('')\n const [suggestions, setSuggestions] = React.useState<EntityOption[]>([])\n const [cache, setCache] = React.useState<Map<string, EntityOption>>(() => new Map())\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n\n const normalizedValue = React.useMemo(() => sanitizeIdList(value), [value])\n\n React.useEffect(() => {\n if (!initialOptions.length) return\n setCache((prev) => {\n const next = new Map(prev)\n initialOptions.forEach((option) => {\n if (option?.id) next.set(option.id, option)\n })\n return next\n })\n }, [initialOptions])\n\n React.useEffect(() => {\n if (!normalizedValue.length) return\n const missing = normalizedValue.filter((id) => !cache.has(id))\n if (!missing.length) return\n let cancelled = false\n ;(async () => {\n try {\n const entries = await fetchByIds(missing)\n if (cancelled) return\n setCache((prev) => {\n const next = new Map(prev)\n entries.forEach((entry) => {\n if (entry?.id) next.set(entry.id, entry)\n })\n return next\n })\n } catch {\n if (!cancelled) setError(errorLabel)\n }\n })().catch(() => {})\n return () => { cancelled = true }\n }, [cache, errorLabel, fetchByIds, normalizedValue])\n\n React.useEffect(() => {\n if (disabled) {\n setLoading(false)\n return\n }\n let cancelled = false\n const handler = window.setTimeout(async () => {\n setLoading(true)\n try {\n const results = await search(input.trim())\n if (cancelled) return\n setSuggestions(results)\n setCache((prev) => {\n const next = new Map(prev)\n results.forEach((entry) => {\n if (entry?.id) next.set(entry.id, entry)\n })\n return next\n })\n setError(null)\n } catch {\n if (!cancelled) {\n setError(errorLabel)\n setSuggestions([])\n }\n } finally {\n if (!cancelled) setLoading(false)\n }\n }, 200)\n return () => {\n cancelled = true\n window.clearTimeout(handler)\n }\n }, [disabled, errorLabel, input, search])\n\n const filteredSuggestions = React.useMemo(\n () => suggestions.filter((option) => !normalizedValue.includes(option.id)),\n [normalizedValue, suggestions],\n )\n\n const selectedOptions = React.useMemo(\n () => normalizedValue.map((id) => cache.get(id) ?? { id, label: id }),\n [cache, normalizedValue],\n )\n\n const addOption = React.useCallback(\n (option: EntityOption) => {\n if (!option?.id) return\n if (normalizedValue.includes(option.id)) return\n const next = [...normalizedValue, option.id]\n onChange(next)\n setCache((prev) => {\n const nextCache = new Map(prev)\n nextCache.set(option.id, option)\n return nextCache\n })\n setInput('')\n setSuggestions([])\n },\n [normalizedValue, onChange],\n )\n\n const removeOption = React.useCallback(\n (id: string) => {\n const next = normalizedValue.filter((candidate) => candidate !== id)\n onChange(next)\n },\n [normalizedValue, onChange],\n )\n\n return (\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2 rounded border px-2 py-1\">\n {selectedOptions.map((option) => (\n <span key={option.id} className=\"inline-flex items-center gap-1 rounded bg-muted px-2 py-0.5 text-xs\">\n {option.label}\n <IconButton\n variant=\"ghost\"\n size=\"xs\"\n className=\"opacity-60 hover:opacity-100\"\n onClick={() => removeOption(option.id)}\n aria-label={`${removeLabel} ${option.label}`}\n disabled={disabled}\n >\n \u00D7\n </IconButton>\n </span>\n ))}\n <input\n type=\"text\"\n className=\"flex-1 min-w-[160px] border-0 bg-transparent py-1 text-sm outline-none\"\n value={input}\n placeholder={placeholder}\n onChange={(event) => setInput(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault()\n const nextOption = filteredSuggestions[0]\n if (nextOption) addOption(nextOption)\n } else if (event.key === 'Backspace' && !input.length && normalizedValue.length) {\n removeOption(normalizedValue[normalizedValue.length - 1])\n }\n }}\n disabled={disabled}\n autoFocus={autoFocus}\n data-crud-focus-target=\"\"\n />\n </div>\n {loading ? <div className=\"text-xs text-muted-foreground\">{loadingLabel}</div> : null}\n {!loading && filteredSuggestions.length ? (\n <div className=\"flex flex-wrap gap-2\">\n {filteredSuggestions.slice(0, 10).map((option) => (\n <Button\n key={option.id}\n variant=\"outline\"\n size=\"sm\"\n className=\"h-auto px-2 py-1 text-xs font-normal\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => addOption(option)}\n disabled={disabled}\n aria-label={option.label}\n >\n <span className=\"flex flex-col items-start\">\n <span>{option.label}</span>\n {option.subtitle ? (\n <span className=\"text-overline text-muted-foreground\">{option.subtitle}</span>\n ) : null}\n </span>\n </Button>\n ))}\n </div>\n ) : null}\n {!loading && !filteredSuggestions.length && input.trim().length ? (\n <div className=\"text-xs text-muted-foreground\">{noResultsLabel}</div>\n ) : null}\n {error ? <div className=\"text-xs text-status-error-text\">{error}</div> : null}\n {!normalizedValue.length && !input.trim().length ? (\n <div className=\"text-xs text-muted-foreground\">{emptyLabel}</div>\n ) : null}\n </div>\n )\n}\n\nexport function useDealAssociationLookups(options?: { excludeLinkedDealId?: string | null }) {\n const searchPeoplePage = React.useCallback(async (query: string, page = 1): Promise<{ items: EntityOption[]; totalPages: number }> => {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: '20',\n sortField: 'name',\n sortDir: 'asc',\n })\n if (query.trim().length) params.set('search', query.trim())\n if (options?.excludeLinkedDealId) params.set('excludeLinkedDealId', options.excludeLinkedDealId)\n const call = await apiCall<Record<string, unknown>>(`/api/customers/people?${params.toString()}`)\n if (!call.ok) {\n throw new Error(typeof call.result?.error === 'string' ? String(call.result?.error) : 'Failed to search people')\n }\n const payload = call.result ?? {}\n const items = Array.isArray(payload.items) ? payload.items : []\n return {\n items: items\n .map((item: unknown) => (item && typeof item === 'object' ? extractPersonOption(item as Record<string, unknown>) : null))\n .filter((entry: EntityOption | null): entry is EntityOption => entry !== null),\n totalPages: typeof payload.totalPages === 'number' ? payload.totalPages : 1,\n }\n }, [options?.excludeLinkedDealId])\n\n const searchPeople = React.useCallback(async (query: string): Promise<EntityOption[]> => {\n const result = await searchPeoplePage(query, 1)\n return result.items\n }, [searchPeoplePage])\n\n const fetchPeopleByIds = React.useCallback(async (ids: string[]): Promise<EntityOption[]> => {\n const unique = sanitizeIdList(ids)\n if (!unique.length) return []\n try {\n const params = new URLSearchParams({\n ids: unique.join(','),\n pageSize: String(Math.max(unique.length, 1)),\n })\n const call = await apiCall<Record<string, unknown>>(`/api/customers/people?${params.toString()}`)\n if (!call.ok) throw new Error()\n const payload = call.result ?? {}\n const items = Array.isArray(payload.items) ? payload.items : []\n const optionMap = new Map<string, EntityOption>()\n items.forEach((item: unknown) => {\n if (!item || typeof item !== 'object') return\n const option = extractPersonOption(item as Record<string, unknown>)\n if (option?.id) optionMap.set(option.id, option)\n })\n return unique.map((id) => optionMap.get(id) ?? { id, label: id })\n } catch {\n return unique.map((id) => ({ id, label: id }))\n }\n }, [])\n\n const searchCompaniesPage = React.useCallback(async (query: string, page = 1): Promise<{ items: EntityOption[]; totalPages: number }> => {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: '20',\n sortField: 'name',\n sortDir: 'asc',\n })\n if (query.trim().length) params.set('search', query.trim())\n if (options?.excludeLinkedDealId) params.set('excludeLinkedDealId', options.excludeLinkedDealId)\n const call = await apiCall<Record<string, unknown>>(`/api/customers/companies?${params.toString()}`)\n if (!call.ok) {\n throw new Error(typeof call.result?.error === 'string' ? String(call.result?.error) : 'Failed to search companies')\n }\n const payload = call.result ?? {}\n const items = Array.isArray(payload.items) ? payload.items : []\n return {\n items: items\n .map((item: unknown) => (item && typeof item === 'object' ? extractCompanyOption(item as Record<string, unknown>) : null))\n .filter((entry: EntityOption | null): entry is EntityOption => entry !== null),\n totalPages: typeof payload.totalPages === 'number' ? payload.totalPages : 1,\n }\n }, [options?.excludeLinkedDealId])\n\n const searchCompanies = React.useCallback(async (query: string): Promise<EntityOption[]> => {\n const result = await searchCompaniesPage(query, 1)\n return result.items\n }, [searchCompaniesPage])\n\n const fetchCompaniesByIds = React.useCallback(async (ids: string[]): Promise<EntityOption[]> => {\n const unique = sanitizeIdList(ids)\n if (!unique.length) return []\n try {\n const params = new URLSearchParams({\n ids: unique.join(','),\n pageSize: String(Math.max(unique.length, 1)),\n })\n const call = await apiCall<Record<string, unknown>>(`/api/customers/companies?${params.toString()}`)\n if (!call.ok) throw new Error()\n const payload = call.result ?? {}\n const items = Array.isArray(payload.items) ? payload.items : []\n const optionMap = new Map<string, EntityOption>()\n items.forEach((item: unknown) => {\n if (!item || typeof item !== 'object') return\n const option = extractCompanyOption(item as Record<string, unknown>)\n if (option?.id) optionMap.set(option.id, option)\n })\n return unique.map((id) => optionMap.get(id) ?? { id, label: id })\n } catch {\n return unique.map((id) => ({ id, label: id }))\n }\n }, [])\n\n return {\n searchPeople,\n searchPeoplePage,\n fetchPeopleByIds,\n searchCompanies,\n searchCompaniesPage,\n fetchCompaniesByIds,\n }\n}\n\nexport function DealPeopleSelector({\n value,\n onChange,\n options = [],\n disabled = false,\n autoFocus = false,\n}: {\n value: string[]\n onChange: (next: string[]) => void\n options?: EntityOption[]\n disabled?: boolean\n autoFocus?: boolean\n}) {\n const t = useT()\n const { searchPeople, fetchPeopleByIds } = useDealAssociationLookups()\n\n return (\n <EntityMultiSelect\n value={value}\n onChange={onChange}\n initialOptions={options}\n placeholder={t('customers.deals.form.people.searchPlaceholder', 'Search people\u2026')}\n emptyLabel={t('customers.deals.form.people.empty', 'No people linked yet.')}\n loadingLabel={t('customers.deals.form.people.loading', 'Searching people\u2026')}\n noResultsLabel={t('customers.deals.form.people.noResults', 'No people match your search.')}\n removeLabel={t('customers.deals.form.assignees.remove', 'Remove')}\n errorLabel={t('customers.deals.form.people.error', 'Failed to load people.')}\n search={searchPeople}\n fetchByIds={fetchPeopleByIds}\n disabled={disabled}\n autoFocus={autoFocus}\n />\n )\n}\n\nexport function DealCompaniesSelector({\n value,\n onChange,\n options = [],\n disabled = false,\n}: {\n value: string[]\n onChange: (next: string[]) => void\n options?: EntityOption[]\n disabled?: boolean\n}) {\n const t = useT()\n const { searchCompanies, fetchCompaniesByIds } = useDealAssociationLookups()\n\n return (\n <EntityMultiSelect\n value={value}\n onChange={onChange}\n initialOptions={options}\n placeholder={t('customers.deals.form.companies.searchPlaceholder', 'Search companies\u2026')}\n emptyLabel={t('customers.deals.form.companies.empty', 'No companies linked yet.')}\n loadingLabel={t('customers.deals.form.companies.loading', 'Searching companies\u2026')}\n noResultsLabel={t('customers.deals.form.companies.noResults', 'No companies match your search.')}\n removeLabel={t('customers.deals.form.assignees.remove', 'Remove')}\n errorLabel={t('customers.deals.form.companies.error', 'Failed to load companies.')}\n search={searchCompanies}\n fetchByIds={fetchCompaniesByIds}\n disabled={disabled}\n />\n )\n}\n\nexport function DealForm({\n mode,\n initialValues,\n onSubmit,\n onCancel,\n onDelete,\n submitLabel,\n cancelLabel,\n isSubmitting = false,\n embedded = true,\n trackDirtyWhenEmbedded = false,\n title,\n backHref,\n hideFooterActions = false,\n onDirtyChange,\n collapsibleGroups,\n sortableGroups,\n singleColumnGroups = false,\n showAssociationsGroup = true,\n showVersionHistory = true,\n showCancelAction = true,\n}: DealFormProps) {\n const t = useT()\n const [pending, setPending] = React.useState(false)\n const {\n data: currencyDictionaryData,\n error: currencyDictionaryErrorRaw,\n isLoading: currencyDictionaryLoading,\n refetch: refetchCurrencyDictionary,\n } = useCurrencyDictionary()\n const currencyDictionaryError = currencyDictionaryErrorRaw\n ? currencyDictionaryErrorRaw instanceof Error\n ? currencyDictionaryErrorRaw.message\n : String(currencyDictionaryErrorRaw)\n : null\n\n const translate = React.useCallback(\n (key: string, fallback: string) => {\n const value = t(key)\n return value === key ? fallback : value\n },\n [t],\n )\n\n const dictionaryLabels = React.useMemo(() => ({\n status: createDictionarySelectLabels('deal-statuses', translate),\n }), [translate])\n\n const resolvedCurrencyError = React.useMemo(() => {\n if (currencyDictionaryError) return currencyDictionaryError\n if (!currencyDictionaryLoading && !currencyDictionaryData) {\n return t('customers.deals.form.currency.missing', 'Currency dictionary is not configured yet.')\n }\n return null\n }, [currencyDictionaryData, currencyDictionaryError, currencyDictionaryLoading, t])\n\n const fetchCurrencyOptions = React.useCallback(async () => {\n let payload = currencyDictionaryData ?? null\n if (!payload) {\n try {\n payload = await refetchCurrencyDictionary()\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err ?? '')\n throw new Error(message || t('customers.deals.form.currency.error', 'Failed to load currency dictionary.'))\n }\n }\n if (!payload) {\n throw new Error(t('customers.deals.form.currency.missing', 'Currency dictionary is not configured yet.'))\n }\n const priorityOrder = new Map<string, number>()\n CURRENCY_PRIORITY.forEach((code, index) => priorityOrder.set(code, index))\n const prioritized: { value: string; label: string; color: string | null; icon: string | null }[] = []\n const remainder: { value: string; label: string; color: string | null; icon: string | null }[] = []\n payload.entries.forEach((entry) => {\n const value = entry.value.toUpperCase()\n const label = entry.label && entry.label.length ? `${value} \u2013 ${entry.label}` : value\n const option = { value, label, color: null, icon: null }\n if (priorityOrder.has(value)) prioritized.push(option)\n else remainder.push(option)\n })\n prioritized.sort((a, b) => (priorityOrder.get(a.value)! - priorityOrder.get(b.value)!))\n remainder.sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: 'base' }))\n return [...prioritized, ...remainder]\n }, [currencyDictionaryData, refetchCurrencyDictionary, t])\n\n const currencyDictionaryLabels = React.useMemo(() => ({\n placeholder: t('customers.deals.form.currency.placeholder', 'Select currency\u2026'),\n addLabel: t('customers.deals.form.currency.add', 'Add currency'),\n dialogTitle: t('customers.deals.form.currency.dialogTitle', 'Add currency'),\n valueLabel: t('customers.deals.form.currency.valueLabel', 'Currency code'),\n valuePlaceholder: t('customers.deals.form.currency.valuePlaceholder', 'e.g. USD'),\n labelLabel: t('customers.deals.form.currency.labelLabel', 'Label'),\n labelPlaceholder: t('customers.deals.form.currency.labelPlaceholder', 'Display name shown in UI'),\n emptyError: t('customers.deals.form.currency.error.required', 'Currency code is required.'),\n cancelLabel: t('customers.deals.form.currency.cancel', 'Cancel'),\n saveLabel: t('customers.deals.form.currency.save', 'Save'),\n errorLoad: t('customers.deals.form.currency.error', 'Failed to load currency dictionary.'),\n errorSave: t('customers.deals.form.currency.error', 'Failed to load currency dictionary.'),\n loadingLabel: t('customers.deals.form.currency.loading', 'Loading currencies\u2026'),\n manageTitle: t('customers.deals.form.currency.manage', 'Manage currency dictionary'),\n }), [t])\n\n const { searchPeople, fetchPeopleByIds, searchCompanies, fetchCompaniesByIds } = useDealAssociationLookups()\n\n const disabled = pending || isSubmitting\n const canDelete = mode === 'edit' && typeof onDelete === 'function'\n\n type PipelineOption = { id: string; name: string; isDefault: boolean }\n type PipelineStageOption = { id: string; label: string; order: number }\n\n const [pipelines, setPipelines] = React.useState<PipelineOption[]>([])\n const [pipelineStages, setPipelineStages] = React.useState<PipelineStageOption[]>([])\n\n const loadStagesForPipeline = React.useCallback(async (pipelineId: string) => {\n if (!pipelineId) {\n setPipelineStages([])\n return\n }\n try {\n const call = await apiCall<{ items: PipelineStageOption[] }>(`/api/customers/pipeline-stages?pipelineId=${encodeURIComponent(pipelineId)}`)\n if (call.ok && call.result?.items) {\n const sorted = [...call.result.items].sort((a, b) => a.order - b.order)\n setPipelineStages(sorted)\n }\n } catch {\n setPipelineStages([])\n }\n }, [])\n\n React.useEffect(() => {\n let cancelled = false\n ;(async () => {\n try {\n const call = await apiCall<{ items: PipelineOption[] }>('/api/customers/pipelines')\n if (cancelled) return\n if (call.ok && call.result?.items) {\n setPipelines(call.result.items)\n }\n } catch {\n // ignore\n }\n })().catch(() => {})\n return () => { cancelled = true }\n }, [])\n\n React.useEffect(() => {\n const pid = initialValues?.pipelineId\n if (typeof pid === 'string' && pid.length) {\n loadStagesForPipeline(pid).catch(() => {})\n }\n }, [initialValues?.pipelineId, loadStagesForPipeline])\n\n const baseFields = React.useMemo<CrudField[]>(() => [\n {\n id: 'title',\n label: t('customers.people.detail.deals.fields.title', 'Title'),\n type: 'text',\n required: true,\n },\n {\n id: 'status',\n label: t('customers.people.detail.deals.fields.status', 'Status'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => (\n <DictionarySelectField\n kind=\"deal-statuses\"\n value={typeof value === 'string' ? value : undefined}\n onChange={(next) => setValue(next ?? '')}\n labels={dictionaryLabels.status}\n selectClassName=\"w-full\"\n />\n ),\n } as CrudField,\n {\n id: 'pipelineId',\n label: t('customers.people.detail.deals.fields.pipeline', 'Pipeline'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => (\n <Select\n value={typeof value === 'string' && value ? value : undefined}\n onValueChange={(next) => {\n setValue(next ?? '')\n loadStagesForPipeline(next ?? '').catch(() => {})\n }}\n disabled={disabled}\n >\n <SelectTrigger>\n <SelectValue placeholder={t('customers.deals.form.pipeline.placeholder', 'Select pipeline\u2026')} />\n </SelectTrigger>\n <SelectContent>\n {pipelines.map((p) => (\n <SelectItem key={p.id} value={p.id}>{p.name}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n ),\n } as CrudField,\n {\n id: 'pipelineStageId',\n label: t('customers.people.detail.deals.fields.pipelineStage', 'Pipeline stage'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => (\n <Select\n value={typeof value === 'string' && value ? value : undefined}\n onValueChange={(next) => setValue(next ?? '')}\n disabled={disabled || !pipelineStages.length}\n >\n <SelectTrigger>\n <SelectValue placeholder={t('customers.deals.form.pipelineStage.placeholder', 'Select stage\u2026')} />\n </SelectTrigger>\n <SelectContent>\n {pipelineStages.map((s) => (\n <SelectItem key={s.id} value={s.id}>{s.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n ),\n } as CrudField,\n {\n id: 'valueAmount',\n label: t('customers.people.detail.deals.fields.valueAmount', 'Amount'),\n type: 'number',\n layout: 'half',\n },\n {\n id: 'valueCurrency',\n label: t('customers.people.detail.deals.fields.valueCurrency', 'Currency'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => (\n <div className=\"space-y-1\">\n <DictionaryEntrySelect\n value={typeof value === 'string' ? value : undefined}\n onChange={(next) => setValue(next ?? '')}\n fetchOptions={fetchCurrencyOptions}\n labels={currencyDictionaryLabels}\n manageHref=\"/backend/config/dictionaries?key=currency\"\n allowInlineCreate={false}\n allowAppearance={false}\n selectClassName=\"w-full\"\n disabled={disabled}\n showLabelInput={false}\n />\n {resolvedCurrencyError ? (\n <div className=\"text-xs text-muted-foreground\">{resolvedCurrencyError}</div>\n ) : null}\n </div>\n ),\n } as CrudField,\n {\n id: 'probability',\n label: t('customers.people.detail.deals.fields.probability', 'Probability (%)'),\n type: 'number',\n layout: 'half',\n },\n {\n id: 'expectedCloseAt',\n label: t('customers.people.detail.deals.fields.expectedCloseAt', 'Expected close'),\n type: 'date',\n layout: 'half',\n },\n {\n id: 'description',\n label: t('customers.people.detail.deals.fields.description', 'Description'),\n type: 'textarea',\n },\n {\n id: 'personIds',\n label: t('customers.people.detail.deals.fields.people', 'People'),\n type: 'custom',\n component: ({ value, setValue, autoFocus }) => (\n <EntityMultiSelect\n value={Array.isArray(value) ? value : []}\n onChange={(next) => setValue(next)}\n placeholder={t('customers.deals.form.people.searchPlaceholder', 'Search people\u2026')}\n emptyLabel={t('customers.deals.form.people.empty', 'No people linked yet.')}\n loadingLabel={t('customers.deals.form.people.loading', 'Searching people\u2026')}\n noResultsLabel={t('customers.deals.form.people.noResults', 'No people match your search.')}\n removeLabel={t('customers.deals.form.assignees.remove', 'Remove')}\n errorLabel={t('customers.deals.form.people.error', 'Failed to load people.')}\n search={searchPeople}\n fetchByIds={fetchPeopleByIds}\n disabled={disabled}\n autoFocus={autoFocus}\n />\n ),\n } as CrudField,\n {\n id: 'companyIds',\n label: t('customers.people.detail.deals.fields.companies', 'Companies'),\n type: 'custom',\n component: ({ value, setValue }) => (\n <EntityMultiSelect\n value={Array.isArray(value) ? value : []}\n onChange={(next) => setValue(next)}\n placeholder={t('customers.deals.form.companies.searchPlaceholder', 'Search companies\u2026')}\n emptyLabel={t('customers.deals.form.companies.empty', 'No companies linked yet.')}\n loadingLabel={t('customers.deals.form.companies.loading', 'Searching companies\u2026')}\n noResultsLabel={t('customers.deals.form.companies.noResults', 'No companies match your search.')}\n removeLabel={t('customers.deals.form.assignees.remove', 'Remove')}\n errorLabel={t('customers.deals.form.companies.error', 'Failed to load companies.')}\n search={searchCompanies}\n fetchByIds={fetchCompaniesByIds}\n disabled={disabled}\n />\n ),\n } as CrudField,\n ], [currencyDictionaryLabels, fetchCurrencyOptions, resolvedCurrencyError, pipelines, pipelineStages, loadStagesForPipeline, dictionaryLabels.status, disabled, fetchCompaniesByIds, fetchPeopleByIds, searchCompanies, searchPeople, t])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => {\n const nextGroups: CrudFormGroup[] = [\n {\n id: 'details',\n title: t('customers.people.detail.deals.form.details', 'Deal details'),\n column: 1,\n fields: ['title', 'status', 'pipelineId', 'pipelineStageId', 'valueAmount', 'valueCurrency', 'probability', 'expectedCloseAt', 'description'],\n },\n ...(showAssociationsGroup\n ? [{\n id: 'associations',\n title: t('customers.people.detail.deals.form.associations', 'Associations'),\n column: 1,\n fields: ['personIds', 'companyIds'],\n } satisfies CrudFormGroup]\n : []),\n {\n id: 'custom',\n title: t('customers.people.detail.deals.form.customFields', 'Custom fields'),\n column: 2,\n kind: 'customFields',\n },\n ]\n return nextGroups.map((group) => (singleColumnGroups ? { ...group, column: 1 } : group))\n }, [showAssociationsGroup, singleColumnGroups, t])\n\n const embeddedInitialValues = React.useMemo(() => {\n const normalizeNumber = (value: unknown): number | null => {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const parsed = Number(value)\n return Number.isNaN(parsed) ? null : parsed\n }\n return null\n }\n\n const resolveIdsFromSource = (source: unknown): string[] => {\n if (Array.isArray(source)) {\n return sanitizeIdList(\n source.map((entry) => {\n if (typeof entry === 'string') return entry\n if (entry && typeof entry === 'object' && 'id' in entry) {\n const candidate = (entry as { id?: unknown }).id\n if (typeof candidate === 'string') return candidate\n }\n return null\n }),\n )\n }\n return []\n }\n\n return {\n id: typeof initialValues?.id === 'string' ? initialValues.id : undefined,\n title: initialValues?.title ?? '',\n status: initialValues?.status ?? '',\n pipelineStage: initialValues?.pipelineStage ?? '',\n pipelineId: initialValues?.pipelineId ?? (typeof (initialValues as Record<string, unknown>)?.pipeline_id === 'string' ? (initialValues as Record<string, unknown>).pipeline_id as string : ''),\n pipelineStageId: initialValues?.pipelineStageId ?? (typeof (initialValues as Record<string, unknown>)?.pipeline_stage_id === 'string' ? (initialValues as Record<string, unknown>).pipeline_stage_id as string : ''),\n valueAmount: normalizeNumber(initialValues?.valueAmount ?? null),\n valueCurrency: normalizeCurrency(initialValues?.valueCurrency ?? null),\n probability: normalizeNumber(initialValues?.probability ?? null),\n expectedCloseAt: toDateInputValue(initialValues?.expectedCloseAt ?? null),\n description: initialValues?.description ?? '',\n personIds: sanitizeIdList(initialValues?.personIds ?? resolveIdsFromSource(initialValues?.people)),\n companyIds: sanitizeIdList(initialValues?.companyIds ?? resolveIdsFromSource(initialValues?.companies)),\n ...Object.fromEntries(\n Object.entries(initialValues ?? {})\n .filter(([key]) => key.startsWith('cf_'))\n .map(([key, value]) => [key, value]),\n ),\n }\n }, [initialValues])\n\n const handleSubmit = React.useCallback(\n async (values: Record<string, unknown>) => {\n if (pending || isSubmitting) return\n setPending(true)\n try {\n const parsed = schema.safeParse(values)\n if (!parsed.success) {\n throw buildDealValidationError(parsed.error.issues, t)\n }\n const expectedCloseAt =\n parsed.data.expectedCloseAt && parsed.data.expectedCloseAt.length\n ? new Date(parsed.data.expectedCloseAt).toISOString()\n : undefined\n const personIds = sanitizeIdList(parsed.data.personIds)\n const companyIds = sanitizeIdList(parsed.data.companyIds)\n const base: DealFormBaseValues = {\n title: parsed.data.title,\n status: parsed.data.status || undefined,\n pipelineStage: parsed.data.pipelineStage || undefined,\n pipelineId: parsed.data.pipelineId || undefined,\n pipelineStageId: parsed.data.pipelineStageId || undefined,\n valueAmount:\n typeof parsed.data.valueAmount === 'number' ? parsed.data.valueAmount : undefined,\n valueCurrency: parsed.data.valueCurrency || undefined,\n probability:\n typeof parsed.data.probability === 'number' ? parsed.data.probability : undefined,\n expectedCloseAt,\n description: parsed.data.description && parsed.data.description.length\n ? parsed.data.description\n : undefined,\n personIds,\n companyIds,\n }\n const customEntries = collectCustomFieldValues(values, {\n transform: (value) => normalizeCustomFieldSubmitValue(value),\n })\n await onSubmit({ base, custom: customEntries })\n } finally {\n setPending(false)\n }\n },\n [isSubmitting, onSubmit, pending, t],\n )\n\n return (\n <CrudForm<Record<string, unknown>>\n embedded={embedded}\n trackDirtyWhenEmbedded={trackDirtyWhenEmbedded}\n title={title}\n backHref={backHref}\n hideFooterActions={hideFooterActions}\n onDirtyChange={onDirtyChange}\n collapsibleGroups={collapsibleGroups}\n sortableGroups={sortableGroups}\n versionHistory={showVersionHistory && mode === 'edit' && initialValues?.id\n ? { resourceKind: 'customers.deal', resourceId: String(initialValues.id) }\n : undefined}\n schema={schema}\n fields={baseFields}\n groups={groups}\n entityIds={DEAL_ENTITY_IDS}\n initialValues={embeddedInitialValues}\n onSubmit={handleSubmit}\n onDelete={canDelete ? onDelete : undefined}\n deleteVisible={canDelete}\n submitLabel={\n submitLabel ??\n (mode === 'edit'\n ? t('customers.people.detail.deals.update', 'Update deal (\u2318/Ctrl + Enter)')\n : t('customers.people.detail.deals.save', 'Save deal (\u2318/Ctrl + Enter)'))\n }\n extraActions={showCancelAction ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onCancel}\n disabled={pending || isSubmitting}\n >\n {cancelLabel ?? t('customers.people.detail.deals.cancel', 'Cancel')}\n </Button>\n ) : undefined}\n />\n )\n}\n\nexport function buildDealValidationError(issues: z.ZodIssue[], t: (key: string, fallback?: string) => string) {\n const issue = issues[0]\n const message =\n typeof issue?.message === 'string'\n ? issue.message\n : t('customers.people.detail.deals.error', 'Failed to save deal.')\n const firstPath = Array.isArray(issue?.path) ? issue?.path?.[0] : undefined\n const field = typeof firstPath === 'string' ? firstPath : undefined\n throw createCrudFormError(message, field ? { [field]: message } : undefined)\n}\n\nexport default DealForm\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { DictionarySelectField } from '../formConfig'\nimport { createDictionarySelectLabels } from './utils'\nimport { E } from '#generated/entities.ids.generated'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { useCurrencyDictionary } from './hooks/useCurrencyDictionary'\nimport { DictionaryEntrySelect } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport { normalizeCustomFieldSubmitValue } from './customFieldUtils'\n\nexport type DealFormBaseValues = {\n title: string\n status?: string | null\n pipelineStage?: string | null\n pipelineId?: string | null\n pipelineStageId?: string | null\n valueAmount?: number | null\n valueCurrency?: string | null\n probability?: number | null\n expectedCloseAt?: string | null\n description?: string | null\n personIds?: string[]\n companyIds?: string[]\n}\n\nexport type DealFormSubmitPayload = {\n base: DealFormBaseValues\n custom: Record<string, unknown>\n}\n\nexport type DealFormProps = {\n mode: 'create' | 'edit'\n initialValues?: Partial<DealFormBaseValues & Record<string, unknown>>\n onSubmit: (payload: DealFormSubmitPayload) => Promise<void>\n onCancel: () => void\n onDelete?: () => Promise<void> | void\n submitLabel?: string\n cancelLabel?: string\n isSubmitting?: boolean\n embedded?: boolean\n trackDirtyWhenEmbedded?: boolean\n title?: string\n backHref?: string\n hideFooterActions?: boolean\n onDirtyChange?: (dirty: boolean) => void\n collapsibleGroups?: boolean | { pageType: string; chevronPosition?: 'left' | 'right' }\n sortableGroups?: boolean | { pageType: string }\n singleColumnGroups?: boolean\n showAssociationsGroup?: boolean\n showVersionHistory?: boolean\n showCancelAction?: boolean\n}\n\ntype EntityOption = {\n id: string\n label: string\n subtitle?: string | null\n}\n\nexport type DealLookupOption = EntityOption\n\ntype EntityMultiSelectProps = {\n value: string[]\n onChange: (next: string[]) => void\n initialOptions?: EntityOption[]\n placeholder: string\n emptyLabel: string\n loadingLabel: string\n noResultsLabel: string\n removeLabel: string\n errorLabel: string\n search: (query: string) => Promise<EntityOption[]>\n fetchByIds: (ids: string[]) => Promise<EntityOption[]>\n disabled?: boolean\n autoFocus?: boolean\n}\n\nconst DEAL_ENTITY_IDS = [E.customers.customer_deal]\nconst CURRENCY_PRIORITY = ['EUR', 'USD', 'GBP', 'PLN'] as const\n\nconst schema = z.object({\n title: z\n .string()\n .trim()\n .min(1, 'customers.people.detail.deals.titleRequired')\n .max(200, 'customers.people.detail.deals.titleTooLong'),\n status: z\n .string()\n .trim()\n .max(50, 'customers.people.detail.deals.statusTooLong')\n .optional(),\n pipelineStage: z\n .string()\n .trim()\n .max(100, 'customers.people.detail.deals.pipelineTooLong')\n .optional(),\n pipelineId: z.preprocess(\n (v) => (typeof v === 'string' && !v.trim() ? undefined : v),\n z.string().uuid('customers.people.detail.deals.pipelineIdInvalid').optional(),\n ),\n pipelineStageId: z.preprocess(\n (v) => (typeof v === 'string' && !v.trim() ? undefined : v),\n z.string().uuid('customers.people.detail.deals.pipelineStageIdInvalid').optional(),\n ),\n valueAmount: z\n .preprocess((value) => {\n if (value === '' || value === null || value === undefined) return undefined\n if (typeof value === 'number') return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return undefined\n const parsed = Number(trimmed)\n if (Number.isNaN(parsed)) return value\n return parsed\n }\n return value\n }, z\n .number()\n .min(0, 'customers.people.detail.deals.valueInvalid')\n .optional())\n .optional(),\n valueCurrency: z\n .string()\n .transform((value) => value.trim().toUpperCase())\n .refine(\n (value) => !value || /^[A-Z]{3}$/.test(value),\n 'customers.people.detail.deals.currencyInvalid',\n )\n .optional(),\n probability: z\n .preprocess((value) => {\n if (value === '' || value === null || value === undefined) return undefined\n if (typeof value === 'number') return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return undefined\n const parsed = Number(trimmed)\n if (Number.isNaN(parsed)) return value\n return parsed\n }\n return value\n }, z\n .number()\n .min(0, 'customers.people.detail.deals.probabilityInvalid')\n .max(100, 'customers.people.detail.deals.probabilityInvalid')\n .optional())\n .optional(),\n expectedCloseAt: z\n .string()\n .transform((value) => value.trim())\n .refine(\n (value) => {\n if (!value) return true\n const parsed = new Date(value)\n return !Number.isNaN(parsed.getTime())\n },\n 'customers.people.detail.deals.expectedCloseInvalid',\n )\n .optional(),\n description: z.string().max(4000, 'customers.people.detail.deals.descriptionTooLong').optional(),\n personIds: z.array(z.string().trim().min(1)).optional(),\n companyIds: z.array(z.string().trim().min(1)).optional(),\n}).passthrough()\n\nexport const dealFormSchema = schema\n\nimport { toDateInputValue as toDateInputValueOrNull } from '@open-mercato/shared/lib/date/format'\n\nfunction toDateInputValue(value: string | null | undefined): string {\n return toDateInputValueOrNull(value) ?? ''\n}\n\nfunction normalizeCurrency(value: string | null | undefined): string {\n if (!value) return ''\n return value.trim().slice(0, 3).toUpperCase()\n}\n\nfunction sanitizeIdList(input: unknown): string[] {\n if (!Array.isArray(input)) return []\n const set = new Set<string>()\n input.forEach((candidate) => {\n if (typeof candidate !== 'string') return\n const trimmed = candidate.trim()\n if (!trimmed.length) return\n set.add(trimmed)\n })\n return Array.from(set)\n}\n\nfunction extractPersonOption(record: Record<string, unknown>): EntityOption | null {\n const id = typeof record.id === 'string' ? record.id : null\n if (!id) return null\n const displayName =\n typeof record.displayName === 'string' && record.displayName.trim().length\n ? record.displayName.trim()\n : typeof record.display_name === 'string' && record.display_name.trim().length\n ? (record.display_name as string).trim()\n : null\n const email =\n typeof record.primaryEmail === 'string' && record.primaryEmail.trim().length\n ? record.primaryEmail.trim()\n : typeof record.primary_email === 'string' && record.primary_email.trim().length\n ? (record.primary_email as string).trim()\n : null\n const label = displayName ?? email ?? id\n const subtitle = email && email !== label ? email : null\n return { id, label, subtitle }\n}\n\nfunction extractCompanyOption(record: Record<string, unknown>): EntityOption | null {\n const id = typeof record.id === 'string' ? record.id : null\n if (!id) return null\n const displayName =\n typeof record.displayName === 'string' && record.displayName.trim().length\n ? record.displayName.trim()\n : typeof record.display_name === 'string' && record.display_name.trim().length\n ? (record.display_name as string).trim()\n : null\n const domain =\n typeof record.domain === 'string' && record.domain.trim().length\n ? record.domain.trim()\n : typeof record.websiteUrl === 'string' && record.websiteUrl.trim().length\n ? record.websiteUrl.trim()\n : typeof record.website_url === 'string' && record.website_url.trim().length\n ? (record.website_url as string).trim()\n : null\n const label = displayName ?? domain ?? id\n const subtitle = domain && domain !== label ? domain : null\n return { id, label, subtitle }\n}\n\nfunction EntityMultiSelect({\n value,\n onChange,\n initialOptions = [],\n placeholder,\n emptyLabel,\n loadingLabel,\n noResultsLabel,\n removeLabel,\n errorLabel,\n search,\n fetchByIds,\n disabled = false,\n autoFocus = false,\n}: EntityMultiSelectProps) {\n const [input, setInput] = React.useState('')\n const [suggestions, setSuggestions] = React.useState<EntityOption[]>([])\n const [cache, setCache] = React.useState<Map<string, EntityOption>>(() => new Map())\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n\n const normalizedValue = React.useMemo(() => sanitizeIdList(value), [value])\n\n React.useEffect(() => {\n if (!initialOptions.length) return\n setCache((prev) => {\n const next = new Map(prev)\n initialOptions.forEach((option) => {\n if (option?.id) next.set(option.id, option)\n })\n return next\n })\n }, [initialOptions])\n\n React.useEffect(() => {\n if (!normalizedValue.length) return\n const missing = normalizedValue.filter((id) => !cache.has(id))\n if (!missing.length) return\n let cancelled = false\n ;(async () => {\n try {\n const entries = await fetchByIds(missing)\n if (cancelled) return\n setCache((prev) => {\n const next = new Map(prev)\n entries.forEach((entry) => {\n if (entry?.id) next.set(entry.id, entry)\n })\n return next\n })\n } catch {\n if (!cancelled) setError(errorLabel)\n }\n })().catch(() => {})\n return () => { cancelled = true }\n }, [cache, errorLabel, fetchByIds, normalizedValue])\n\n React.useEffect(() => {\n if (disabled) {\n setLoading(false)\n return\n }\n let cancelled = false\n const handler = window.setTimeout(async () => {\n setLoading(true)\n try {\n const results = await search(input.trim())\n if (cancelled) return\n setSuggestions(results)\n setCache((prev) => {\n const next = new Map(prev)\n results.forEach((entry) => {\n if (entry?.id) next.set(entry.id, entry)\n })\n return next\n })\n setError(null)\n } catch {\n if (!cancelled) {\n setError(errorLabel)\n setSuggestions([])\n }\n } finally {\n if (!cancelled) setLoading(false)\n }\n }, 200)\n return () => {\n cancelled = true\n window.clearTimeout(handler)\n }\n }, [disabled, errorLabel, input, search])\n\n const filteredSuggestions = React.useMemo(\n () => suggestions.filter((option) => !normalizedValue.includes(option.id)),\n [normalizedValue, suggestions],\n )\n\n const selectedOptions = React.useMemo(\n () => normalizedValue.map((id) => cache.get(id) ?? { id, label: id }),\n [cache, normalizedValue],\n )\n\n const addOption = React.useCallback(\n (option: EntityOption) => {\n if (!option?.id) return\n if (normalizedValue.includes(option.id)) return\n const next = [...normalizedValue, option.id]\n onChange(next)\n setCache((prev) => {\n const nextCache = new Map(prev)\n nextCache.set(option.id, option)\n return nextCache\n })\n setInput('')\n setSuggestions([])\n },\n [normalizedValue, onChange],\n )\n\n const removeOption = React.useCallback(\n (id: string) => {\n const next = normalizedValue.filter((candidate) => candidate !== id)\n onChange(next)\n },\n [normalizedValue, onChange],\n )\n\n return (\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2 rounded border px-2 py-1\">\n {selectedOptions.map((option) => (\n <span key={option.id} className=\"inline-flex items-center gap-1 rounded bg-muted px-2 py-0.5 text-xs\">\n {option.label}\n <IconButton\n variant=\"ghost\"\n size=\"xs\"\n className=\"opacity-60 hover:opacity-100\"\n onClick={() => removeOption(option.id)}\n aria-label={`${removeLabel} ${option.label}`}\n disabled={disabled}\n >\n \u00D7\n </IconButton>\n </span>\n ))}\n <input\n type=\"text\"\n className=\"flex-1 min-w-[160px] border-0 bg-transparent py-1 text-sm outline-none\"\n value={input}\n placeholder={placeholder}\n onChange={(event) => setInput(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault()\n const nextOption = filteredSuggestions[0]\n if (nextOption) addOption(nextOption)\n } else if (event.key === 'Backspace' && !input.length && normalizedValue.length) {\n removeOption(normalizedValue[normalizedValue.length - 1])\n }\n }}\n disabled={disabled}\n autoFocus={autoFocus}\n data-crud-focus-target=\"\"\n />\n </div>\n {loading ? <div className=\"text-xs text-muted-foreground\">{loadingLabel}</div> : null}\n {!loading && filteredSuggestions.length ? (\n <div className=\"flex flex-wrap gap-2\">\n {filteredSuggestions.slice(0, 10).map((option) => (\n <Button\n key={option.id}\n variant=\"outline\"\n size=\"sm\"\n className=\"h-auto px-2 py-1 text-xs font-normal\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => addOption(option)}\n disabled={disabled}\n aria-label={option.label}\n >\n <span className=\"flex flex-col items-start\">\n <span>{option.label}</span>\n {option.subtitle ? (\n <span className=\"text-overline text-muted-foreground\">{option.subtitle}</span>\n ) : null}\n </span>\n </Button>\n ))}\n </div>\n ) : null}\n {!loading && !filteredSuggestions.length && input.trim().length ? (\n <div className=\"text-xs text-muted-foreground\">{noResultsLabel}</div>\n ) : null}\n {error ? <div className=\"text-xs text-status-error-text\">{error}</div> : null}\n {!normalizedValue.length && !input.trim().length ? (\n <div className=\"text-xs text-muted-foreground\">{emptyLabel}</div>\n ) : null}\n </div>\n )\n}\n\nexport function useDealAssociationLookups(options?: { excludeLinkedDealId?: string | null }) {\n const searchPeoplePage = React.useCallback(async (query: string, page = 1): Promise<{ items: EntityOption[]; totalPages: number }> => {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: '20',\n sortField: 'name',\n sortDir: 'asc',\n })\n if (query.trim().length) params.set('search', query.trim())\n if (options?.excludeLinkedDealId) params.set('excludeLinkedDealId', options.excludeLinkedDealId)\n const call = await apiCall<Record<string, unknown>>(`/api/customers/people?${params.toString()}`)\n if (!call.ok) {\n throw new Error(typeof call.result?.error === 'string' ? String(call.result?.error) : 'Failed to search people')\n }\n const payload = call.result ?? {}\n const items = Array.isArray(payload.items) ? payload.items : []\n return {\n items: items\n .map((item: unknown) => (item && typeof item === 'object' ? extractPersonOption(item as Record<string, unknown>) : null))\n .filter((entry: EntityOption | null): entry is EntityOption => entry !== null),\n totalPages: typeof payload.totalPages === 'number' ? payload.totalPages : 1,\n }\n }, [options?.excludeLinkedDealId])\n\n const searchPeople = React.useCallback(async (query: string): Promise<EntityOption[]> => {\n const result = await searchPeoplePage(query, 1)\n return result.items\n }, [searchPeoplePage])\n\n const fetchPeopleByIds = React.useCallback(async (ids: string[]): Promise<EntityOption[]> => {\n const unique = sanitizeIdList(ids)\n if (!unique.length) return []\n try {\n const params = new URLSearchParams({\n ids: unique.join(','),\n pageSize: String(Math.max(unique.length, 1)),\n })\n const call = await apiCall<Record<string, unknown>>(`/api/customers/people?${params.toString()}`)\n if (!call.ok) throw new Error()\n const payload = call.result ?? {}\n const items = Array.isArray(payload.items) ? payload.items : []\n const optionMap = new Map<string, EntityOption>()\n items.forEach((item: unknown) => {\n if (!item || typeof item !== 'object') return\n const option = extractPersonOption(item as Record<string, unknown>)\n if (option?.id) optionMap.set(option.id, option)\n })\n return unique.map((id) => optionMap.get(id) ?? { id, label: id })\n } catch {\n return unique.map((id) => ({ id, label: id }))\n }\n }, [])\n\n const searchCompaniesPage = React.useCallback(async (query: string, page = 1): Promise<{ items: EntityOption[]; totalPages: number }> => {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: '20',\n sortField: 'name',\n sortDir: 'asc',\n })\n if (query.trim().length) params.set('search', query.trim())\n if (options?.excludeLinkedDealId) params.set('excludeLinkedDealId', options.excludeLinkedDealId)\n const call = await apiCall<Record<string, unknown>>(`/api/customers/companies?${params.toString()}`)\n if (!call.ok) {\n throw new Error(typeof call.result?.error === 'string' ? String(call.result?.error) : 'Failed to search companies')\n }\n const payload = call.result ?? {}\n const items = Array.isArray(payload.items) ? payload.items : []\n return {\n items: items\n .map((item: unknown) => (item && typeof item === 'object' ? extractCompanyOption(item as Record<string, unknown>) : null))\n .filter((entry: EntityOption | null): entry is EntityOption => entry !== null),\n totalPages: typeof payload.totalPages === 'number' ? payload.totalPages : 1,\n }\n }, [options?.excludeLinkedDealId])\n\n const searchCompanies = React.useCallback(async (query: string): Promise<EntityOption[]> => {\n const result = await searchCompaniesPage(query, 1)\n return result.items\n }, [searchCompaniesPage])\n\n const fetchCompaniesByIds = React.useCallback(async (ids: string[]): Promise<EntityOption[]> => {\n const unique = sanitizeIdList(ids)\n if (!unique.length) return []\n try {\n const params = new URLSearchParams({\n ids: unique.join(','),\n pageSize: String(Math.max(unique.length, 1)),\n })\n const call = await apiCall<Record<string, unknown>>(`/api/customers/companies?${params.toString()}`)\n if (!call.ok) throw new Error()\n const payload = call.result ?? {}\n const items = Array.isArray(payload.items) ? payload.items : []\n const optionMap = new Map<string, EntityOption>()\n items.forEach((item: unknown) => {\n if (!item || typeof item !== 'object') return\n const option = extractCompanyOption(item as Record<string, unknown>)\n if (option?.id) optionMap.set(option.id, option)\n })\n return unique.map((id) => optionMap.get(id) ?? { id, label: id })\n } catch {\n return unique.map((id) => ({ id, label: id }))\n }\n }, [])\n\n return {\n searchPeople,\n searchPeoplePage,\n fetchPeopleByIds,\n searchCompanies,\n searchCompaniesPage,\n fetchCompaniesByIds,\n }\n}\n\nexport function DealPeopleSelector({\n value,\n onChange,\n options = [],\n disabled = false,\n autoFocus = false,\n}: {\n value: string[]\n onChange: (next: string[]) => void\n options?: EntityOption[]\n disabled?: boolean\n autoFocus?: boolean\n}) {\n const t = useT()\n const { searchPeople, fetchPeopleByIds } = useDealAssociationLookups()\n\n return (\n <EntityMultiSelect\n value={value}\n onChange={onChange}\n initialOptions={options}\n placeholder={t('customers.deals.form.people.searchPlaceholder', 'Search people\u2026')}\n emptyLabel={t('customers.deals.form.people.empty', 'No people linked yet.')}\n loadingLabel={t('customers.deals.form.people.loading', 'Searching people\u2026')}\n noResultsLabel={t('customers.deals.form.people.noResults', 'No people match your search.')}\n removeLabel={t('customers.deals.form.assignees.remove', 'Remove')}\n errorLabel={t('customers.deals.form.people.error', 'Failed to load people.')}\n search={searchPeople}\n fetchByIds={fetchPeopleByIds}\n disabled={disabled}\n autoFocus={autoFocus}\n />\n )\n}\n\nexport function DealCompaniesSelector({\n value,\n onChange,\n options = [],\n disabled = false,\n}: {\n value: string[]\n onChange: (next: string[]) => void\n options?: EntityOption[]\n disabled?: boolean\n}) {\n const t = useT()\n const { searchCompanies, fetchCompaniesByIds } = useDealAssociationLookups()\n\n return (\n <EntityMultiSelect\n value={value}\n onChange={onChange}\n initialOptions={options}\n placeholder={t('customers.deals.form.companies.searchPlaceholder', 'Search companies\u2026')}\n emptyLabel={t('customers.deals.form.companies.empty', 'No companies linked yet.')}\n loadingLabel={t('customers.deals.form.companies.loading', 'Searching companies\u2026')}\n noResultsLabel={t('customers.deals.form.companies.noResults', 'No companies match your search.')}\n removeLabel={t('customers.deals.form.assignees.remove', 'Remove')}\n errorLabel={t('customers.deals.form.companies.error', 'Failed to load companies.')}\n search={searchCompanies}\n fetchByIds={fetchCompaniesByIds}\n disabled={disabled}\n />\n )\n}\n\nexport function DealForm({\n mode,\n initialValues,\n onSubmit,\n onCancel,\n onDelete,\n submitLabel,\n cancelLabel,\n isSubmitting = false,\n embedded = true,\n trackDirtyWhenEmbedded = false,\n title,\n backHref,\n hideFooterActions = false,\n onDirtyChange,\n collapsibleGroups,\n sortableGroups,\n singleColumnGroups = false,\n showAssociationsGroup = true,\n showVersionHistory = true,\n showCancelAction = true,\n}: DealFormProps) {\n const t = useT()\n const [pending, setPending] = React.useState(false)\n const {\n data: currencyDictionaryData,\n error: currencyDictionaryErrorRaw,\n isLoading: currencyDictionaryLoading,\n refetch: refetchCurrencyDictionary,\n } = useCurrencyDictionary()\n const currencyDictionaryError = currencyDictionaryErrorRaw\n ? currencyDictionaryErrorRaw instanceof Error\n ? currencyDictionaryErrorRaw.message\n : String(currencyDictionaryErrorRaw)\n : null\n\n const translate = React.useCallback(\n (key: string, fallback: string) => {\n const value = t(key)\n return value === key ? fallback : value\n },\n [t],\n )\n\n const dictionaryLabels = React.useMemo(() => ({\n status: createDictionarySelectLabels('deal-statuses', translate),\n }), [translate])\n\n const resolvedCurrencyError = React.useMemo(() => {\n if (currencyDictionaryError) return currencyDictionaryError\n if (!currencyDictionaryLoading && !currencyDictionaryData) {\n return t('customers.deals.form.currency.missing', 'Currency dictionary is not configured yet.')\n }\n return null\n }, [currencyDictionaryData, currencyDictionaryError, currencyDictionaryLoading, t])\n\n const fetchCurrencyOptions = React.useCallback(async () => {\n let payload = currencyDictionaryData ?? null\n if (!payload) {\n try {\n payload = await refetchCurrencyDictionary()\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err ?? '')\n throw new Error(message || t('customers.deals.form.currency.error', 'Failed to load currency dictionary.'))\n }\n }\n if (!payload) {\n throw new Error(t('customers.deals.form.currency.missing', 'Currency dictionary is not configured yet.'))\n }\n const priorityOrder = new Map<string, number>()\n CURRENCY_PRIORITY.forEach((code, index) => priorityOrder.set(code, index))\n const prioritized: { value: string; label: string; color: string | null; icon: string | null }[] = []\n const remainder: { value: string; label: string; color: string | null; icon: string | null }[] = []\n payload.entries.forEach((entry) => {\n const value = entry.value.toUpperCase()\n const label = entry.label && entry.label.length ? `${value} \u2013 ${entry.label}` : value\n const option = { value, label, color: null, icon: null }\n if (priorityOrder.has(value)) prioritized.push(option)\n else remainder.push(option)\n })\n prioritized.sort((a, b) => (priorityOrder.get(a.value)! - priorityOrder.get(b.value)!))\n remainder.sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: 'base' }))\n return [...prioritized, ...remainder]\n }, [currencyDictionaryData, refetchCurrencyDictionary, t])\n\n const currencyDictionaryLabels = React.useMemo(() => ({\n placeholder: t('customers.deals.form.currency.placeholder', 'Select currency\u2026'),\n addLabel: t('customers.deals.form.currency.add', 'Add currency'),\n dialogTitle: t('customers.deals.form.currency.dialogTitle', 'Add currency'),\n valueLabel: t('customers.deals.form.currency.valueLabel', 'Currency code'),\n valuePlaceholder: t('customers.deals.form.currency.valuePlaceholder', 'e.g. USD'),\n labelLabel: t('customers.deals.form.currency.labelLabel', 'Label'),\n labelPlaceholder: t('customers.deals.form.currency.labelPlaceholder', 'Display name shown in UI'),\n emptyError: t('customers.deals.form.currency.error.required', 'Currency code is required.'),\n cancelLabel: t('customers.deals.form.currency.cancel', 'Cancel'),\n saveLabel: t('customers.deals.form.currency.save', 'Save'),\n errorLoad: t('customers.deals.form.currency.error', 'Failed to load currency dictionary.'),\n errorSave: t('customers.deals.form.currency.error', 'Failed to load currency dictionary.'),\n loadingLabel: t('customers.deals.form.currency.loading', 'Loading currencies\u2026'),\n manageTitle: t('customers.deals.form.currency.manage', 'Manage currency dictionary'),\n }), [t])\n\n const { searchPeople, fetchPeopleByIds, searchCompanies, fetchCompaniesByIds } = useDealAssociationLookups()\n\n const disabled = pending || isSubmitting\n const canDelete = mode === 'edit' && typeof onDelete === 'function'\n\n type PipelineOption = { id: string; name: string; isDefault: boolean }\n type PipelineStageOption = { id: string; label: string; order: number }\n\n const [pipelines, setPipelines] = React.useState<PipelineOption[]>([])\n const [pipelineStages, setPipelineStages] = React.useState<PipelineStageOption[]>([])\n\n const loadStagesForPipeline = React.useCallback(async (pipelineId: string) => {\n if (!pipelineId) {\n setPipelineStages([])\n return\n }\n try {\n const call = await apiCall<{ items: PipelineStageOption[] }>(`/api/customers/pipeline-stages?pipelineId=${encodeURIComponent(pipelineId)}`)\n if (call.ok && call.result?.items) {\n const sorted = [...call.result.items].sort((a, b) => a.order - b.order)\n setPipelineStages(sorted)\n }\n } catch {\n setPipelineStages([])\n }\n }, [])\n\n React.useEffect(() => {\n let cancelled = false\n ;(async () => {\n try {\n const call = await apiCall<{ items: PipelineOption[] }>('/api/customers/pipelines')\n if (cancelled) return\n if (call.ok && call.result?.items) {\n setPipelines(call.result.items)\n }\n } catch {\n // ignore\n }\n })().catch(() => {})\n return () => { cancelled = true }\n }, [])\n\n React.useEffect(() => {\n const pid = initialValues?.pipelineId\n if (typeof pid === 'string' && pid.length) {\n loadStagesForPipeline(pid).catch(() => {})\n }\n }, [initialValues?.pipelineId, loadStagesForPipeline])\n\n const baseFields = React.useMemo<CrudField[]>(() => [\n {\n id: 'title',\n label: t('customers.people.detail.deals.fields.title', 'Title'),\n type: 'text',\n required: true,\n },\n {\n id: 'status',\n label: t('customers.people.detail.deals.fields.status', 'Status'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => (\n <DictionarySelectField\n kind=\"deal-statuses\"\n value={typeof value === 'string' ? value : undefined}\n onChange={(next) => setValue(next ?? '')}\n labels={dictionaryLabels.status}\n selectClassName=\"w-full\"\n />\n ),\n } as CrudField,\n {\n id: 'pipelineId',\n label: t('customers.people.detail.deals.fields.pipeline', 'Pipeline'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => (\n <Select\n value={typeof value === 'string' && value ? value : undefined}\n onValueChange={(next) => {\n setValue(next ?? '')\n loadStagesForPipeline(next ?? '').catch(() => {})\n }}\n disabled={disabled}\n >\n <SelectTrigger>\n <SelectValue placeholder={t('customers.deals.form.pipeline.placeholder', 'Select pipeline\u2026')} />\n </SelectTrigger>\n <SelectContent>\n {pipelines.map((p) => (\n <SelectItem key={p.id} value={p.id}>{p.name}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n ),\n } as CrudField,\n {\n id: 'pipelineStageId',\n label: t('customers.people.detail.deals.fields.pipelineStage', 'Pipeline stage'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => (\n <Select\n value={typeof value === 'string' && value ? value : undefined}\n onValueChange={(next) => setValue(next ?? '')}\n disabled={disabled || !pipelineStages.length}\n >\n <SelectTrigger>\n <SelectValue placeholder={t('customers.deals.form.pipelineStage.placeholder', 'Select stage\u2026')} />\n </SelectTrigger>\n <SelectContent>\n {pipelineStages.map((s) => (\n <SelectItem key={s.id} value={s.id}>{s.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n ),\n } as CrudField,\n {\n id: 'valueAmount',\n label: t('customers.people.detail.deals.fields.valueAmount', 'Amount'),\n type: 'number',\n layout: 'half',\n },\n {\n id: 'valueCurrency',\n label: t('customers.people.detail.deals.fields.valueCurrency', 'Currency'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => (\n <div className=\"space-y-1\">\n <DictionaryEntrySelect\n value={typeof value === 'string' ? value : undefined}\n onChange={(next) => setValue(next ?? '')}\n fetchOptions={fetchCurrencyOptions}\n labels={currencyDictionaryLabels}\n manageHref=\"/backend/config/dictionaries?key=currency\"\n allowInlineCreate={false}\n allowAppearance={false}\n selectClassName=\"w-full\"\n disabled={disabled}\n showLabelInput={false}\n />\n {resolvedCurrencyError ? (\n <div className=\"text-xs text-muted-foreground\">{resolvedCurrencyError}</div>\n ) : null}\n </div>\n ),\n } as CrudField,\n {\n id: 'probability',\n label: t('customers.people.detail.deals.fields.probability', 'Probability (%)'),\n type: 'number',\n layout: 'half',\n },\n {\n id: 'expectedCloseAt',\n label: t('customers.people.detail.deals.fields.expectedCloseAt', 'Expected close'),\n type: 'date',\n layout: 'half',\n },\n {\n id: 'description',\n label: t('customers.people.detail.deals.fields.description', 'Description'),\n type: 'textarea',\n },\n {\n id: 'personIds',\n label: t('customers.people.detail.deals.fields.people', 'People'),\n type: 'custom',\n component: ({ value, setValue, autoFocus }) => (\n <EntityMultiSelect\n value={Array.isArray(value) ? value : []}\n onChange={(next) => setValue(next)}\n placeholder={t('customers.deals.form.people.searchPlaceholder', 'Search people\u2026')}\n emptyLabel={t('customers.deals.form.people.empty', 'No people linked yet.')}\n loadingLabel={t('customers.deals.form.people.loading', 'Searching people\u2026')}\n noResultsLabel={t('customers.deals.form.people.noResults', 'No people match your search.')}\n removeLabel={t('customers.deals.form.assignees.remove', 'Remove')}\n errorLabel={t('customers.deals.form.people.error', 'Failed to load people.')}\n search={searchPeople}\n fetchByIds={fetchPeopleByIds}\n disabled={disabled}\n autoFocus={autoFocus}\n />\n ),\n } as CrudField,\n {\n id: 'companyIds',\n label: t('customers.people.detail.deals.fields.companies', 'Companies'),\n type: 'custom',\n component: ({ value, setValue }) => (\n <EntityMultiSelect\n value={Array.isArray(value) ? value : []}\n onChange={(next) => setValue(next)}\n placeholder={t('customers.deals.form.companies.searchPlaceholder', 'Search companies\u2026')}\n emptyLabel={t('customers.deals.form.companies.empty', 'No companies linked yet.')}\n loadingLabel={t('customers.deals.form.companies.loading', 'Searching companies\u2026')}\n noResultsLabel={t('customers.deals.form.companies.noResults', 'No companies match your search.')}\n removeLabel={t('customers.deals.form.assignees.remove', 'Remove')}\n errorLabel={t('customers.deals.form.companies.error', 'Failed to load companies.')}\n search={searchCompanies}\n fetchByIds={fetchCompaniesByIds}\n disabled={disabled}\n />\n ),\n } as CrudField,\n ], [currencyDictionaryLabels, fetchCurrencyOptions, resolvedCurrencyError, pipelines, pipelineStages, loadStagesForPipeline, dictionaryLabels.status, disabled, fetchCompaniesByIds, fetchPeopleByIds, searchCompanies, searchPeople, t])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => {\n const nextGroups: CrudFormGroup[] = [\n {\n id: 'details',\n title: t('customers.people.detail.deals.form.details', 'Deal details'),\n column: 1,\n fields: ['title', 'status', 'pipelineId', 'pipelineStageId', 'valueAmount', 'valueCurrency', 'probability', 'expectedCloseAt', 'description'],\n },\n ...(showAssociationsGroup\n ? [{\n id: 'associations',\n title: t('customers.people.detail.deals.form.associations', 'Associations'),\n column: 1,\n fields: ['personIds', 'companyIds'],\n } satisfies CrudFormGroup]\n : []),\n {\n id: 'custom',\n title: t('customers.people.detail.deals.form.customFields', 'Custom fields'),\n column: 2,\n kind: 'customFields',\n },\n ]\n return nextGroups.map((group) => (singleColumnGroups ? { ...group, column: 1 } : group))\n }, [showAssociationsGroup, singleColumnGroups, t])\n\n const embeddedInitialValues = React.useMemo(() => {\n const normalizeNumber = (value: unknown): number | null => {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const parsed = Number(value)\n return Number.isNaN(parsed) ? null : parsed\n }\n return null\n }\n\n const resolveIdsFromSource = (source: unknown): string[] => {\n if (Array.isArray(source)) {\n return sanitizeIdList(\n source.map((entry) => {\n if (typeof entry === 'string') return entry\n if (entry && typeof entry === 'object' && 'id' in entry) {\n const candidate = (entry as { id?: unknown }).id\n if (typeof candidate === 'string') return candidate\n }\n return null\n }),\n )\n }\n return []\n }\n\n return {\n id: typeof initialValues?.id === 'string' ? initialValues.id : undefined,\n title: initialValues?.title ?? '',\n status: initialValues?.status ?? '',\n pipelineStage: initialValues?.pipelineStage ?? '',\n pipelineId: initialValues?.pipelineId ?? (typeof (initialValues as Record<string, unknown>)?.pipeline_id === 'string' ? (initialValues as Record<string, unknown>).pipeline_id as string : ''),\n pipelineStageId: initialValues?.pipelineStageId ?? (typeof (initialValues as Record<string, unknown>)?.pipeline_stage_id === 'string' ? (initialValues as Record<string, unknown>).pipeline_stage_id as string : ''),\n valueAmount: normalizeNumber(initialValues?.valueAmount ?? null),\n valueCurrency: normalizeCurrency(initialValues?.valueCurrency ?? null),\n probability: normalizeNumber(initialValues?.probability ?? null),\n expectedCloseAt: toDateInputValue(initialValues?.expectedCloseAt ?? null),\n description: initialValues?.description ?? '',\n personIds: sanitizeIdList(initialValues?.personIds ?? resolveIdsFromSource(initialValues?.people)),\n companyIds: sanitizeIdList(initialValues?.companyIds ?? resolveIdsFromSource(initialValues?.companies)),\n ...Object.fromEntries(\n Object.entries(initialValues ?? {})\n .filter(([key]) => key.startsWith('cf_'))\n .map(([key, value]) => [key, value]),\n ),\n }\n }, [initialValues])\n\n const handleSubmit = React.useCallback(\n async (values: Record<string, unknown>) => {\n if (pending || isSubmitting) return\n setPending(true)\n try {\n const parsed = schema.safeParse(values)\n if (!parsed.success) {\n throw buildDealValidationError(parsed.error.issues, t)\n }\n const expectedCloseAt =\n parsed.data.expectedCloseAt && parsed.data.expectedCloseAt.length\n ? new Date(parsed.data.expectedCloseAt).toISOString()\n : undefined\n const personIds = sanitizeIdList(parsed.data.personIds)\n const companyIds = sanitizeIdList(parsed.data.companyIds)\n const base: DealFormBaseValues = {\n title: parsed.data.title,\n status: parsed.data.status || undefined,\n pipelineStage: parsed.data.pipelineStage || undefined,\n pipelineId: parsed.data.pipelineId || undefined,\n pipelineStageId: parsed.data.pipelineStageId || undefined,\n valueAmount:\n typeof parsed.data.valueAmount === 'number' ? parsed.data.valueAmount : undefined,\n valueCurrency: parsed.data.valueCurrency || undefined,\n probability:\n typeof parsed.data.probability === 'number' ? parsed.data.probability : undefined,\n expectedCloseAt,\n description: parsed.data.description && parsed.data.description.length\n ? parsed.data.description\n : undefined,\n personIds,\n companyIds,\n }\n const customEntries = collectCustomFieldValues(values, {\n transform: (value) => normalizeCustomFieldSubmitValue(value),\n })\n await onSubmit({ base, custom: customEntries })\n } finally {\n setPending(false)\n }\n },\n [isSubmitting, onSubmit, pending, t],\n )\n\n return (\n <CrudForm<Record<string, unknown>>\n embedded={embedded}\n trackDirtyWhenEmbedded={trackDirtyWhenEmbedded}\n title={title}\n backHref={backHref}\n hideFooterActions={hideFooterActions}\n onDirtyChange={onDirtyChange}\n collapsibleGroups={collapsibleGroups}\n sortableGroups={sortableGroups}\n versionHistory={showVersionHistory && mode === 'edit' && initialValues?.id\n ? { resourceKind: 'customers.deal', resourceId: String(initialValues.id) }\n : undefined}\n schema={schema}\n fields={baseFields}\n groups={groups}\n entityIds={DEAL_ENTITY_IDS}\n initialValues={embeddedInitialValues}\n onSubmit={handleSubmit}\n onDelete={canDelete ? onDelete : undefined}\n deleteVisible={canDelete}\n submitLabel={\n submitLabel ??\n (mode === 'edit'\n ? t('customers.people.detail.deals.update', 'Update deal (\u2318/Ctrl + Enter)')\n : t('customers.people.detail.deals.save', 'Save deal (\u2318/Ctrl + Enter)'))\n }\n extraActions={showCancelAction ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onCancel}\n disabled={pending || isSubmitting}\n >\n {cancelLabel ?? t('customers.people.detail.deals.cancel', 'Cancel')}\n </Button>\n ) : undefined}\n />\n )\n}\n\nexport function buildDealValidationError(issues: z.ZodIssue[], t: (key: string, fallback?: string) => string) {\n const issue = issues[0]\n const message =\n typeof issue?.message === 'string'\n ? issue.message\n : t('customers.people.detail.deals.error', 'Failed to save deal.')\n const firstPath = Array.isArray(issue?.path) ? issue?.path?.[0] : undefined\n const field = typeof firstPath === 'string' ? firstPath : undefined\n throw createCrudFormError(message, field ? { [field]: message } : undefined)\n}\n\nexport default DealForm\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }