@open-mercato/core 0.6.6-develop.6386.1.391a1afb9e → 0.6.6-develop.6387.1.f4896ad565

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 (57) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/customers/api/deals/map/route.js +433 -0
  3. package/dist/modules/customers/api/deals/map/route.js.map +7 -0
  4. package/dist/modules/customers/backend/customers/companies/create/page.js +2 -0
  5. package/dist/modules/customers/backend/customers/companies/create/page.js.map +2 -2
  6. package/dist/modules/customers/backend/customers/deals/map/components/DealsLocationPanel.js +159 -0
  7. package/dist/modules/customers/backend/customers/deals/map/components/DealsLocationPanel.js.map +7 -0
  8. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvas.js +26 -0
  9. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvas.js.map +7 -0
  10. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.js +321 -0
  11. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.js.map +7 -0
  12. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapView.js +533 -0
  13. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapView.js.map +7 -0
  14. package/dist/modules/customers/backend/customers/deals/map/page.js +55 -0
  15. package/dist/modules/customers/backend/customers/deals/map/page.js.map +7 -0
  16. package/dist/modules/customers/backend/customers/deals/map/page.meta.js +38 -0
  17. package/dist/modules/customers/backend/customers/deals/map/page.meta.js.map +7 -0
  18. package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.js +3 -3
  19. package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.js.map +2 -2
  20. package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js +22 -1
  21. package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js.map +2 -2
  22. package/dist/modules/customers/backend/customers/people/create/page.js +2 -0
  23. package/dist/modules/customers/backend/customers/people/create/page.js.map +2 -2
  24. package/dist/modules/customers/components/AddressEditor.js +34 -2
  25. package/dist/modules/customers/components/AddressEditor.js.map +2 -2
  26. package/dist/modules/customers/components/AddressTiles.js +43 -3
  27. package/dist/modules/customers/components/AddressTiles.js.map +2 -2
  28. package/dist/modules/customers/components/detail/AddressesSection.js +4 -1
  29. package/dist/modules/customers/components/detail/AddressesSection.js.map +2 -2
  30. package/dist/modules/customers/components/formConfig.js +10 -0
  31. package/dist/modules/customers/components/formConfig.js.map +2 -2
  32. package/dist/modules/customers/data/validators.js +3 -2
  33. package/dist/modules/customers/data/validators.js.map +2 -2
  34. package/dist/modules/customers/lib/dealsMapLocation.js +75 -0
  35. package/dist/modules/customers/lib/dealsMapLocation.js.map +7 -0
  36. package/package.json +11 -7
  37. package/src/modules/customers/api/deals/map/route.ts +549 -0
  38. package/src/modules/customers/backend/customers/companies/create/page.tsx +2 -0
  39. package/src/modules/customers/backend/customers/deals/map/components/DealsLocationPanel.tsx +213 -0
  40. package/src/modules/customers/backend/customers/deals/map/components/DealsMapCanvas.tsx +79 -0
  41. package/src/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.tsx +407 -0
  42. package/src/modules/customers/backend/customers/deals/map/components/DealsMapView.tsx +667 -0
  43. package/src/modules/customers/backend/customers/deals/map/page.meta.ts +36 -0
  44. package/src/modules/customers/backend/customers/deals/map/page.tsx +77 -0
  45. package/src/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.tsx +3 -3
  46. package/src/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.tsx +22 -1
  47. package/src/modules/customers/backend/customers/people/create/page.tsx +2 -0
  48. package/src/modules/customers/components/AddressEditor.tsx +35 -0
  49. package/src/modules/customers/components/AddressTiles.tsx +51 -1
  50. package/src/modules/customers/components/detail/AddressesSection.tsx +3 -0
  51. package/src/modules/customers/components/formConfig.tsx +10 -0
  52. package/src/modules/customers/data/validators.ts +13 -2
  53. package/src/modules/customers/i18n/de.json +24 -0
  54. package/src/modules/customers/i18n/en.json +24 -0
  55. package/src/modules/customers/i18n/es.json +24 -0
  56. package/src/modules/customers/i18n/pl.json +24 -0
  57. package/src/modules/customers/lib/dealsMapLocation.ts +125 -0
@@ -0,0 +1,55 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import Link from "next/link";
5
+ import { Page, PageBody } from "@open-mercato/ui/backend/Page";
6
+ import {
7
+ Breadcrumb,
8
+ BreadcrumbItem,
9
+ BreadcrumbLink,
10
+ BreadcrumbList,
11
+ BreadcrumbPage,
12
+ BreadcrumbSeparator
13
+ } from "@open-mercato/ui/primitives/breadcrumb";
14
+ import { SearchInput } from "@open-mercato/ui/primitives/search-input";
15
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
16
+ import { translateWithFallback } from "@open-mercato/shared/lib/i18n/translate";
17
+ import { ViewTabsRow } from "../pipeline/components/ViewTabsRow.js";
18
+ import { DealsMapView } from "./components/DealsMapView.js";
19
+ function DealsMapPage() {
20
+ const t = useT();
21
+ const [search, setSearch] = React.useState("");
22
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsxs(PageBody, { children: [
23
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
24
+ /* @__PURE__ */ jsx(Breadcrumb, { children: /* @__PURE__ */ jsxs(BreadcrumbList, { children: [
25
+ /* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(BreadcrumbLink, { asChild: true, children: /* @__PURE__ */ jsx(Link, { href: "/backend", children: translateWithFallback(t, "customers.deals.kanban.breadcrumb.dashboard", "Dashboard") }) }) }),
26
+ /* @__PURE__ */ jsx(BreadcrumbSeparator, {}),
27
+ /* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(BreadcrumbLink, { asChild: true, children: /* @__PURE__ */ jsx(Link, { href: "/backend/customers/deals", children: translateWithFallback(t, "customers.deals.kanban.breadcrumb.deals", "Deals") }) }) }),
28
+ /* @__PURE__ */ jsx(BreadcrumbSeparator, {}),
29
+ /* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(BreadcrumbPage, { children: translateWithFallback(t, "customers.nav.deals.map", "Deals Map") }) })
30
+ ] }) }),
31
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
32
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold leading-tight text-foreground sm:text-2xl", children: translateWithFallback(t, "customers.nav.deals.map", "Deals Map") }),
33
+ /* @__PURE__ */ jsx(
34
+ SearchInput,
35
+ {
36
+ value: search,
37
+ onChange: setSearch,
38
+ placeholder: translateWithFallback(
39
+ t,
40
+ "customers.deals.kanban.search.placeholder",
41
+ "Search deals\u2026"
42
+ ),
43
+ className: "w-64"
44
+ }
45
+ )
46
+ ] })
47
+ ] }),
48
+ /* @__PURE__ */ jsx(ViewTabsRow, { active: "map", className: "mt-4" }),
49
+ /* @__PURE__ */ jsx(DealsMapView, { search })
50
+ ] }) });
51
+ }
52
+ export {
53
+ DealsMapPage as default
54
+ };
55
+ //# sourceMappingURL=page.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/modules/customers/backend/customers/deals/map/page.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from '@open-mercato/ui/primitives/breadcrumb'\nimport { SearchInput } from '@open-mercato/ui/primitives/search-input'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { ViewTabsRow } from '../pipeline/components/ViewTabsRow'\nimport { DealsMapView } from './components/DealsMapView'\n\nexport default function DealsMapPage(): React.ReactElement {\n const t = useT()\n const [search, setSearch] = React.useState('')\n\n return (\n <Page>\n <PageBody>\n <div className=\"flex flex-col gap-2\">\n <Breadcrumb>\n <BreadcrumbList>\n <BreadcrumbItem>\n <BreadcrumbLink asChild>\n <Link href=\"/backend\">\n {translateWithFallback(t, 'customers.deals.kanban.breadcrumb.dashboard', 'Dashboard')}\n </Link>\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbLink asChild>\n <Link href=\"/backend/customers/deals\">\n {translateWithFallback(t, 'customers.deals.kanban.breadcrumb.deals', 'Deals')}\n </Link>\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage>\n {translateWithFallback(t, 'customers.nav.deals.map', 'Deals Map')}\n </BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <h1 className=\"text-xl font-semibold leading-tight text-foreground sm:text-2xl\">\n {translateWithFallback(t, 'customers.nav.deals.map', 'Deals Map')}\n </h1>\n <SearchInput\n value={search}\n onChange={setSearch}\n placeholder={translateWithFallback(\n t,\n 'customers.deals.kanban.search.placeholder',\n 'Search deals\u2026',\n )}\n className=\"w-64\"\n />\n </div>\n </div>\n\n <ViewTabsRow active=\"map\" className=\"mt-4\" />\n\n <DealsMapView search={search} />\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": ";AA4BY,SAGM,KAHN;AA1BZ,YAAY,WAAW;AACvB,OAAO,UAAU;AACjB,SAAS,MAAM,gBAAgB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAAmB;AAC5B,SAAS,YAAY;AACrB,SAAS,6BAA6B;AACtC,SAAS,mBAAmB;AAC5B,SAAS,oBAAoB;AAEd,SAAR,eAAoD;AACzD,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE;AAE7C,SACE,oBAAC,QACC,+BAAC,YACC;AAAA,yBAAC,SAAI,WAAU,uBACb;AAAA,0BAAC,cACC,+BAAC,kBACC;AAAA,4BAAC,kBACC,8BAAC,kBAAe,SAAO,MACrB,8BAAC,QAAK,MAAK,YACR,gCAAsB,GAAG,+CAA+C,WAAW,GACtF,GACF,GACF;AAAA,QACA,oBAAC,uBAAoB;AAAA,QACrB,oBAAC,kBACC,8BAAC,kBAAe,SAAO,MACrB,8BAAC,QAAK,MAAK,4BACR,gCAAsB,GAAG,2CAA2C,OAAO,GAC9E,GACF,GACF;AAAA,QACA,oBAAC,uBAAoB;AAAA,QACrB,oBAAC,kBACC,8BAAC,kBACE,gCAAsB,GAAG,2BAA2B,WAAW,GAClE,GACF;AAAA,SACF,GACF;AAAA,MAEA,qBAAC,SAAI,WAAU,sEACb;AAAA,4BAAC,QAAG,WAAU,mEACX,gCAAsB,GAAG,2BAA2B,WAAW,GAClE;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,YACP,UAAU;AAAA,YACV,aAAa;AAAA,cACX;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,YACA,WAAU;AAAA;AAAA,QACZ;AAAA,SACF;AAAA,OACF;AAAA,IAEA,oBAAC,eAAY,QAAO,OAAM,WAAU,QAAO;AAAA,IAE3C,oBAAC,gBAAa,QAAgB;AAAA,KAChC,GACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,38 @@
1
+ import React from "react";
2
+ const mapIcon = React.createElement(
3
+ "svg",
4
+ {
5
+ width: 16,
6
+ height: 16,
7
+ viewBox: "0 0 24 24",
8
+ fill: "none",
9
+ stroke: "currentColor",
10
+ strokeWidth: 2,
11
+ strokeLinecap: "round",
12
+ strokeLinejoin: "round"
13
+ },
14
+ React.createElement("path", {
15
+ d: "M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0z"
16
+ }),
17
+ React.createElement("path", { d: "M15 5.764v15" }),
18
+ React.createElement("path", { d: "M9 3.236v15" })
19
+ );
20
+ const metadata = {
21
+ requireAuth: true,
22
+ requireFeatures: ["customers.deals.view", "customers.activities.view"],
23
+ pageTitle: "Deals Map",
24
+ pageTitleKey: "customers.nav.deals.map",
25
+ pageGroup: "Customers",
26
+ pageGroupKey: "customers.nav.group",
27
+ pagePriority: 10,
28
+ pageOrder: 122,
29
+ icon: mapIcon,
30
+ breadcrumb: [
31
+ { label: "Deals", labelKey: "customers.nav.deals", href: "/backend/customers/deals" },
32
+ { label: "Deals Map", labelKey: "customers.nav.deals.map" }
33
+ ]
34
+ };
35
+ export {
36
+ metadata
37
+ };
38
+ //# sourceMappingURL=page.meta.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/modules/customers/backend/customers/deals/map/page.meta.ts"],
4
+ "sourcesContent": ["import React from 'react'\n\nconst mapIcon = React.createElement(\n 'svg',\n {\n width: 16,\n height: 16,\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n },\n React.createElement('path', {\n d: 'M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0z',\n }),\n React.createElement('path', { d: 'M15 5.764v15' }),\n React.createElement('path', { d: 'M9 3.236v15' })\n)\n\nexport const metadata = {\n requireAuth: true,\n requireFeatures: ['customers.deals.view', 'customers.activities.view'],\n pageTitle: 'Deals Map',\n pageTitleKey: 'customers.nav.deals.map',\n pageGroup: 'Customers',\n pageGroupKey: 'customers.nav.group',\n pagePriority: 10,\n pageOrder: 122,\n icon: mapIcon,\n breadcrumb: [\n { label: 'Deals', labelKey: 'customers.nav.deals', href: '/backend/customers/deals' },\n { label: 'Deals Map', labelKey: 'customers.nav.deals.map' },\n ],\n}\n"],
5
+ "mappings": "AAAA,OAAO,WAAW;AAElB,MAAM,UAAU,MAAM;AAAA,EACpB;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,eAAe;AAAA,IACf,gBAAgB;AAAA,EAClB;AAAA,EACA,MAAM,cAAc,QAAQ;AAAA,IAC1B,GAAG;AAAA,EACL,CAAC;AAAA,EACD,MAAM,cAAc,QAAQ,EAAE,GAAG,eAAe,CAAC;AAAA,EACjD,MAAM,cAAc,QAAQ,EAAE,GAAG,cAAc,CAAC;AAClD;AAEO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,wBAAwB,2BAA2B;AAAA,EACrE,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,cAAc;AAAA,EACd,WAAW;AAAA,EACX,MAAM;AAAA,EACN,YAAY;AAAA,IACV,EAAE,OAAO,SAAS,UAAU,uBAAuB,MAAM,2BAA2B;AAAA,IACpF,EAAE,OAAO,aAAa,UAAU,0BAA0B;AAAA,EAC5D;AACF;",
6
+ "names": []
7
+ }
@@ -10,9 +10,9 @@ function FilterBarRow({
10
10
  onChipClick
11
11
  }) {
12
12
  const t = useT();
13
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-y-2 rounded-lg bg-muted/40 px-3.5 py-3", children: [
13
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 rounded-lg bg-muted/40 px-3.5 py-3 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between sm:gap-y-2", children: [
14
14
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
15
- /* @__PURE__ */ jsxs("span", { className: "text-overline font-bold uppercase leading-normal text-muted-foreground", children: [
15
+ /* @__PURE__ */ jsxs("span", { className: "text-overline w-full font-bold uppercase leading-normal text-muted-foreground sm:w-auto", children: [
16
16
  translateWithFallback(t, "customers.deals.kanban.filter.label", "Filter"),
17
17
  ":"
18
18
  ] }),
@@ -33,7 +33,7 @@ function FilterBarRow({
33
33
  chip.id
34
34
  ))
35
35
  ] }),
36
- /* @__PURE__ */ jsx("div", { className: "ml-auto", children: sortNode })
36
+ /* @__PURE__ */ jsx("div", { className: "sm:ml-auto", children: sortNode })
37
37
  ] });
38
38
  }
39
39
  var FilterBarRow_default = FilterBarRow;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../../src/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { ChipButton } from './ChipButton'\n\nexport type KanbanFilterChip = {\n id: 'owner' | 'people' | 'companies' | 'close'\n label: string\n value: string\n}\n\ntype FilterBarRowProps = {\n /** Popover-backed chips (Status, Pipeline) rendered first, in order */\n leadingChips: React.ReactNode\n /** Static (Phase-5-stubbed) chips */\n chips: KanbanFilterChip[]\n /** Right-aligned sort chip (popover-backed) */\n sortNode: React.ReactNode\n onChipClick: (chipId: KanbanFilterChip['id']) => void\n}\n\nexport function FilterBarRow({\n leadingChips,\n chips,\n sortNode,\n onChipClick,\n}: FilterBarRowProps): React.ReactElement {\n const t = useT()\n // Note: the Figma mock includes a \"+ Add filter\" chip (1045:11987) that opens a picker for\n // Tags / Source / Currency / Created date / Updated date / Last activity / custom fields.\n // That picker is not wired up in this slice (it would need AdvancedFilterPanel integration),\n // so the affordance is intentionally omitted instead of shipping a \"coming next\" toast.\n return (\n <div className=\"flex flex-wrap items-center justify-between gap-y-2 rounded-lg bg-muted/40 px-3.5 py-3\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-overline font-bold uppercase leading-normal text-muted-foreground\">\n {translateWithFallback(t, 'customers.deals.kanban.filter.label', 'Filter')}:\n </span>\n {leadingChips}\n {chips.map((chip) => (\n <ChipButton\n key={chip.id}\n label={chip.label}\n value={chip.value}\n onClick={() => onChipClick(chip.id)}\n ariaLabel={translateWithFallback(\n t,\n 'customers.deals.kanban.filter.aria.chip',\n 'Filter by {label}',\n { label: chip.label },\n )}\n />\n ))}\n </div>\n <div className=\"ml-auto\">{sortNode}</div>\n </div>\n )\n}\n\nexport default FilterBarRow\n"],
5
- "mappings": ";AAqCQ,SAKE,KALF;AAlCR,SAAS,YAAY;AACrB,SAAS,6BAA6B;AACtC,SAAS,kBAAkB;AAkBpB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0C;AACxC,QAAM,IAAI,KAAK;AAKf,SACE,qBAAC,SAAI,WAAU,0FACb;AAAA,yBAAC,SAAI,WAAU,qCACb;AAAA,2BAAC,UAAK,WAAU,0EACb;AAAA,8BAAsB,GAAG,uCAAuC,QAAQ;AAAA,QAAE;AAAA,SAC7E;AAAA,MACC;AAAA,MACA,MAAM,IAAI,CAAC,SACV;AAAA,QAAC;AAAA;AAAA,UAEC,OAAO,KAAK;AAAA,UACZ,OAAO,KAAK;AAAA,UACZ,SAAS,MAAM,YAAY,KAAK,EAAE;AAAA,UAClC,WAAW;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA,YACA,EAAE,OAAO,KAAK,MAAM;AAAA,UACtB;AAAA;AAAA,QATK,KAAK;AAAA,MAUZ,CACD;AAAA,OACH;AAAA,IACA,oBAAC,SAAI,WAAU,WAAW,oBAAS;AAAA,KACrC;AAEJ;AAEA,IAAO,uBAAQ;",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { ChipButton } from './ChipButton'\n\nexport type KanbanFilterChip = {\n id: 'owner' | 'people' | 'companies' | 'close'\n label: string\n value: string\n}\n\ntype FilterBarRowProps = {\n /** Popover-backed chips (Status, Pipeline) rendered first, in order */\n leadingChips: React.ReactNode\n /** Static (Phase-5-stubbed) chips */\n chips: KanbanFilterChip[]\n /** Right-aligned sort chip (popover-backed) */\n sortNode: React.ReactNode\n onChipClick: (chipId: KanbanFilterChip['id']) => void\n}\n\nexport function FilterBarRow({\n leadingChips,\n chips,\n sortNode,\n onChipClick,\n}: FilterBarRowProps): React.ReactElement {\n const t = useT()\n // Note: the Figma mock includes a \"+ Add filter\" chip (1045:11987) that opens a picker for\n // Tags / Source / Currency / Created date / Updated date / Last activity / custom fields.\n // That picker is not wired up in this slice (it would need AdvancedFilterPanel integration),\n // so the affordance is intentionally omitted instead of shipping a \"coming next\" toast.\n return (\n <div className=\"flex flex-col gap-2 rounded-lg bg-muted/40 px-3.5 py-3 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between sm:gap-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-overline w-full font-bold uppercase leading-normal text-muted-foreground sm:w-auto\">\n {translateWithFallback(t, 'customers.deals.kanban.filter.label', 'Filter')}:\n </span>\n {leadingChips}\n {chips.map((chip) => (\n <ChipButton\n key={chip.id}\n label={chip.label}\n value={chip.value}\n onClick={() => onChipClick(chip.id)}\n ariaLabel={translateWithFallback(\n t,\n 'customers.deals.kanban.filter.aria.chip',\n 'Filter by {label}',\n { label: chip.label },\n )}\n />\n ))}\n </div>\n <div className=\"sm:ml-auto\">{sortNode}</div>\n </div>\n )\n}\n\nexport default FilterBarRow\n"],
5
+ "mappings": ";AAqCQ,SAKE,KALF;AAlCR,SAAS,YAAY;AACrB,SAAS,6BAA6B;AACtC,SAAS,kBAAkB;AAkBpB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0C;AACxC,QAAM,IAAI,KAAK;AAKf,SACE,qBAAC,SAAI,WAAU,iIACb;AAAA,yBAAC,SAAI,WAAU,qCACb;AAAA,2BAAC,UAAK,WAAU,2FACb;AAAA,8BAAsB,GAAG,uCAAuC,QAAQ;AAAA,QAAE;AAAA,SAC7E;AAAA,MACC;AAAA,MACA,MAAM,IAAI,CAAC,SACV;AAAA,QAAC;AAAA;AAAA,UAEC,OAAO,KAAK;AAAA,UACZ,OAAO,KAAK;AAAA,UACZ,SAAS,MAAM,YAAY,KAAK,EAAE;AAAA,UAClC,WAAW;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA,YACA,EAAE,OAAO,KAAK,MAAM;AAAA,UACtB;AAAA;AAAA,QATK,KAAK;AAAA,MAUZ,CACD;AAAA,OACH;AAAA,IACA,oBAAC,SAAI,WAAU,cAAc,oBAAS;AAAA,KACxC;AAEJ;AAEA,IAAO,uBAAQ;",
6
6
  "names": []
7
7
  }
@@ -5,17 +5,20 @@ import { useT } from "@open-mercato/shared/lib/i18n/context";
5
5
  import { translateWithFallback } from "@open-mercato/shared/lib/i18n/translate";
6
6
  const VIEW_KANBAN_HREF = "/backend/customers/deals/pipeline";
7
7
  const VIEW_LIST_HREF = "/backend/customers/deals";
8
+ const VIEW_MAP_HREF = "/backend/customers/deals/map";
8
9
  function ViewTabsRow({ active, className }) {
9
10
  const t = useT();
10
11
  const labels = {
11
12
  kanban: translateWithFallback(t, "customers.deals.kanban.view.kanban", "Kanban"),
12
- list: translateWithFallback(t, "customers.deals.kanban.view.list", "List")
13
+ list: translateWithFallback(t, "customers.deals.kanban.view.list", "List"),
14
+ map: translateWithFallback(t, "customers.deals.kanban.view.map", "Map")
13
15
  };
14
16
  const baseTab = "inline-flex items-center px-3.5 py-2.5 text-sm leading-normal transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2";
15
17
  const activeTab = "border-b-2 border-foreground font-semibold text-foreground";
16
18
  const inactiveTab = "border-b-2 border-transparent font-normal text-muted-foreground hover:text-foreground";
17
19
  const isKanbanActive = active === "kanban";
18
20
  const isListActive = active === "list";
21
+ const isMapActive = active === "map";
19
22
  return /* @__PURE__ */ jsxs(
20
23
  "div",
21
24
  {
@@ -58,6 +61,24 @@ function ViewTabsRow({ active, className }) {
58
61
  className: `${baseTab} ${inactiveTab}`,
59
62
  children: labels.list
60
63
  }
64
+ ),
65
+ isMapActive ? /* @__PURE__ */ jsx(
66
+ "span",
67
+ {
68
+ role: "tab",
69
+ "aria-selected": true,
70
+ className: `${baseTab} ${activeTab}`,
71
+ children: labels.map
72
+ }
73
+ ) : /* @__PURE__ */ jsx(
74
+ Link,
75
+ {
76
+ href: VIEW_MAP_HREF,
77
+ role: "tab",
78
+ "aria-selected": false,
79
+ className: `${baseTab} ${inactiveTab}`,
80
+ children: labels.map
81
+ }
61
82
  )
62
83
  ]
63
84
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../../src/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nexport type KanbanView = 'kanban' | 'list'\n\ntype ViewTabsRowProps = {\n active: KanbanView\n className?: string\n}\n\nconst VIEW_KANBAN_HREF = '/backend/customers/deals/pipeline'\nconst VIEW_LIST_HREF = '/backend/customers/deals'\n\nexport function ViewTabsRow({ active, className }: ViewTabsRowProps): React.ReactElement {\n const t = useT()\n const labels = {\n kanban: translateWithFallback(t, 'customers.deals.kanban.view.kanban', 'Kanban'),\n list: translateWithFallback(t, 'customers.deals.kanban.view.list', 'List'),\n }\n\n const baseTab =\n 'inline-flex items-center px-3.5 py-2.5 text-sm leading-normal transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2'\n const activeTab = 'border-b-2 border-foreground font-semibold text-foreground'\n const inactiveTab = 'border-b-2 border-transparent font-normal text-muted-foreground hover:text-foreground'\n\n // Renders the active tab as a non-navigating `<span>` and the inactive tab as a `<Link>`,\n // so the user can always round-trip between kanban and list from either page. Previously\n // the kanban tab was a hardcoded `<span>` because the row was only rendered on the kanban\n // page \u2014 adding it to the list page (item 7 of the SPEC-048 UX review) requires it to\n // navigate back to /pipeline.\n const isKanbanActive = active === 'kanban'\n const isListActive = active === 'list'\n\n return (\n <div\n role=\"tablist\"\n aria-label={translateWithFallback(t, 'customers.deals.kanban.view.tablistLabel', 'Deals views')}\n className={`flex items-end gap-1 border-b border-border ${className ?? ''}`.trim()}\n >\n {isKanbanActive ? (\n <span\n role=\"tab\"\n aria-selected={true}\n className={`${baseTab} ${activeTab}`}\n >\n {labels.kanban}\n </span>\n ) : (\n <Link\n href={VIEW_KANBAN_HREF}\n role=\"tab\"\n aria-selected={false}\n className={`${baseTab} ${inactiveTab}`}\n >\n {labels.kanban}\n </Link>\n )}\n {isListActive ? (\n <span\n role=\"tab\"\n aria-selected={true}\n className={`${baseTab} ${activeTab}`}\n >\n {labels.list}\n </span>\n ) : (\n <Link\n href={VIEW_LIST_HREF}\n role=\"tab\"\n aria-selected={false}\n className={`${baseTab} ${inactiveTab}`}\n >\n {labels.list}\n </Link>\n )}\n </div>\n )\n}\n\nexport default ViewTabsRow\n"],
5
- "mappings": ";AAsCI,SAMI,KANJ;AAnCJ,OAAO,UAAU;AACjB,SAAS,YAAY;AACrB,SAAS,6BAA6B;AAStC,MAAM,mBAAmB;AACzB,MAAM,iBAAiB;AAEhB,SAAS,YAAY,EAAE,QAAQ,UAAU,GAAyC;AACvF,QAAM,IAAI,KAAK;AACf,QAAM,SAAS;AAAA,IACb,QAAQ,sBAAsB,GAAG,sCAAsC,QAAQ;AAAA,IAC/E,MAAM,sBAAsB,GAAG,oCAAoC,MAAM;AAAA,EAC3E;AAEA,QAAM,UACJ;AACF,QAAM,YAAY;AAClB,QAAM,cAAc;AAOpB,QAAM,iBAAiB,WAAW;AAClC,QAAM,eAAe,WAAW;AAEhC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY,sBAAsB,GAAG,4CAA4C,aAAa;AAAA,MAC9F,WAAW,+CAA+C,aAAa,EAAE,GAAG,KAAK;AAAA,MAEhF;AAAA,yBACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,WAAW,GAAG,OAAO,IAAI,SAAS;AAAA,YAEjC,iBAAO;AAAA;AAAA,QACV,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,WAAW,GAAG,OAAO,IAAI,WAAW;AAAA,YAEnC,iBAAO;AAAA;AAAA,QACV;AAAA,QAED,eACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,WAAW,GAAG,OAAO,IAAI,SAAS;AAAA,YAEjC,iBAAO;AAAA;AAAA,QACV,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,WAAW,GAAG,OAAO,IAAI,WAAW;AAAA,YAEnC,iBAAO;AAAA;AAAA,QACV;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,IAAO,sBAAQ;",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nexport type KanbanView = 'kanban' | 'list' | 'map'\n\ntype ViewTabsRowProps = {\n active: KanbanView\n className?: string\n}\n\nconst VIEW_KANBAN_HREF = '/backend/customers/deals/pipeline'\nconst VIEW_LIST_HREF = '/backend/customers/deals'\nconst VIEW_MAP_HREF = '/backend/customers/deals/map'\n\nexport function ViewTabsRow({ active, className }: ViewTabsRowProps): React.ReactElement {\n const t = useT()\n const labels = {\n kanban: translateWithFallback(t, 'customers.deals.kanban.view.kanban', 'Kanban'),\n list: translateWithFallback(t, 'customers.deals.kanban.view.list', 'List'),\n map: translateWithFallback(t, 'customers.deals.kanban.view.map', 'Map'),\n }\n\n const baseTab =\n 'inline-flex items-center px-3.5 py-2.5 text-sm leading-normal transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2'\n const activeTab = 'border-b-2 border-foreground font-semibold text-foreground'\n const inactiveTab = 'border-b-2 border-transparent font-normal text-muted-foreground hover:text-foreground'\n\n // Renders the active tab as a non-navigating `<span>` and the inactive tab as a `<Link>`,\n // so the user can always round-trip between kanban and list from either page. Previously\n // the kanban tab was a hardcoded `<span>` because the row was only rendered on the kanban\n // page \u2014 adding it to the list page (item 7 of the SPEC-048 UX review) requires it to\n // navigate back to /pipeline.\n const isKanbanActive = active === 'kanban'\n const isListActive = active === 'list'\n const isMapActive = active === 'map'\n\n return (\n <div\n role=\"tablist\"\n aria-label={translateWithFallback(t, 'customers.deals.kanban.view.tablistLabel', 'Deals views')}\n className={`flex items-end gap-1 border-b border-border ${className ?? ''}`.trim()}\n >\n {isKanbanActive ? (\n <span\n role=\"tab\"\n aria-selected={true}\n className={`${baseTab} ${activeTab}`}\n >\n {labels.kanban}\n </span>\n ) : (\n <Link\n href={VIEW_KANBAN_HREF}\n role=\"tab\"\n aria-selected={false}\n className={`${baseTab} ${inactiveTab}`}\n >\n {labels.kanban}\n </Link>\n )}\n {isListActive ? (\n <span\n role=\"tab\"\n aria-selected={true}\n className={`${baseTab} ${activeTab}`}\n >\n {labels.list}\n </span>\n ) : (\n <Link\n href={VIEW_LIST_HREF}\n role=\"tab\"\n aria-selected={false}\n className={`${baseTab} ${inactiveTab}`}\n >\n {labels.list}\n </Link>\n )}\n {isMapActive ? (\n <span\n role=\"tab\"\n aria-selected={true}\n className={`${baseTab} ${activeTab}`}\n >\n {labels.map}\n </span>\n ) : (\n <Link\n href={VIEW_MAP_HREF}\n role=\"tab\"\n aria-selected={false}\n className={`${baseTab} ${inactiveTab}`}\n >\n {labels.map}\n </Link>\n )}\n </div>\n )\n}\n\nexport default ViewTabsRow\n"],
5
+ "mappings": ";AAyCI,SAMI,KANJ;AAtCJ,OAAO,UAAU;AACjB,SAAS,YAAY;AACrB,SAAS,6BAA6B;AAStC,MAAM,mBAAmB;AACzB,MAAM,iBAAiB;AACvB,MAAM,gBAAgB;AAEf,SAAS,YAAY,EAAE,QAAQ,UAAU,GAAyC;AACvF,QAAM,IAAI,KAAK;AACf,QAAM,SAAS;AAAA,IACb,QAAQ,sBAAsB,GAAG,sCAAsC,QAAQ;AAAA,IAC/E,MAAM,sBAAsB,GAAG,oCAAoC,MAAM;AAAA,IACzE,KAAK,sBAAsB,GAAG,mCAAmC,KAAK;AAAA,EACxE;AAEA,QAAM,UACJ;AACF,QAAM,YAAY;AAClB,QAAM,cAAc;AAOpB,QAAM,iBAAiB,WAAW;AAClC,QAAM,eAAe,WAAW;AAChC,QAAM,cAAc,WAAW;AAE/B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY,sBAAsB,GAAG,4CAA4C,aAAa;AAAA,MAC9F,WAAW,+CAA+C,aAAa,EAAE,GAAG,KAAK;AAAA,MAEhF;AAAA,yBACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,WAAW,GAAG,OAAO,IAAI,SAAS;AAAA,YAEjC,iBAAO;AAAA;AAAA,QACV,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,WAAW,GAAG,OAAO,IAAI,WAAW;AAAA,YAEnC,iBAAO;AAAA;AAAA,QACV;AAAA,QAED,eACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,WAAW,GAAG,OAAO,IAAI,SAAS;AAAA,YAEjC,iBAAO;AAAA;AAAA,QACV,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,WAAW,GAAG,OAAO,IAAI,WAAW;AAAA,YAEnC,iBAAO;AAAA;AAAA,QACV;AAAA,QAED,cACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,WAAW,GAAG,OAAO,IAAI,SAAS;AAAA,YAEjC,iBAAO;AAAA;AAAA,QACV,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,WAAW,GAAG,OAAO,IAAI,WAAW;AAAA,YAEnC,iBAAO;AAAA;AAAA,QACV;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,IAAO,sBAAQ;",
6
6
  "names": []
7
7
  }
@@ -100,6 +100,8 @@ function CreatePersonPage() {
100
100
  if (postalCode !== void 0) body.postalCode = postalCode;
101
101
  const country = normalize(entry.country);
102
102
  if (country !== void 0) body.country = country.toUpperCase();
103
+ if (typeof entry.latitude === "number") body.latitude = entry.latitude;
104
+ if (typeof entry.longitude === "number") body.longitude = entry.longitude;
103
105
  try {
104
106
  await createCrud("customers/addresses", body);
105
107
  } catch (addressErr) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/customers/backend/customers/people/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 { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { createCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport {\n buildPersonPayload,\n createPersonFormFields,\n createPersonFormGroups,\n createPersonFormSchema,\n type PersonFormValues,\n} from '../../../../components/formConfig'\n\nexport default function CreatePersonPage() {\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { organizationId } = useOrganizationScopeDetail()\n\n const formSchema = React.useMemo(() => createPersonFormSchema(), [])\n const fields = React.useMemo(() => createPersonFormFields(t), [t])\n const groups = React.useMemo(() => createPersonFormGroups(t), [t])\n const returnTo = searchParams.get('returnTo')\n const companyParam = searchParams.get('companyId')\n const companyEntityId = React.useMemo(() => {\n if (!companyParam) return undefined\n const trimmed = companyParam.trim()\n return trimmed.length ? trimmed : undefined\n }, [companyParam])\n const initialValues = React.useMemo<Partial<PersonFormValues>>(\n () => ({\n addresses: [] as PersonFormValues['addresses'],\n ...(companyEntityId ? { companyEntityId } : {}),\n }),\n [companyEntityId],\n )\n\n return (\n <Page>\n <PageBody>\n <CrudForm<PersonFormValues>\n title={t('customers.people.create.title')}\n backHref={returnTo ?? '/backend/customers/people'}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n submitLabel={t('customers.people.form.submit')}\n cancelHref={returnTo ?? '/backend/customers/people'}\n schema={formSchema}\n onSubmit={async (values) => {\n const addresses = Array.isArray(values.addresses) ? values.addresses : []\n let payload: Record<string, unknown>\n try {\n payload = buildPersonPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error && err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.people.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n throw err\n }\n\n const { result: created } = await createCrud<{ id?: string; entityId?: string }>(\n 'customers/people',\n payload,\n )\n const newId =\n created && typeof created.id === 'string'\n ? created.id\n : (typeof created?.entityId === 'string' ? created.entityId : null)\n\n if (newId && addresses.length) {\n const normalize = (value?: string | null) => {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n return trimmed.length ? trimmed : undefined\n }\n for (const entry of addresses) {\n const normalizedLine1 = normalize(entry.addressLine1)\n if (!normalizedLine1) continue\n const body: Record<string, unknown> = {\n entityId: newId,\n ...(organizationId ? { organizationId } : {}),\n addressLine1: normalizedLine1,\n isPrimary: entry.isPrimary ?? false,\n }\n const name = normalize(entry.name)\n if (name !== undefined) body.name = name\n const purpose = normalize(entry.purpose)\n if (purpose !== undefined) body.purpose = purpose\n const line2 = normalize(entry.addressLine2)\n if (line2 !== undefined) body.addressLine2 = line2\n const buildingNumber = normalize(entry.buildingNumber)\n if (buildingNumber !== undefined) body.buildingNumber = buildingNumber\n const flatNumber = normalize(entry.flatNumber)\n if (flatNumber !== undefined) body.flatNumber = flatNumber\n const city = normalize(entry.city)\n if (city !== undefined) body.city = city\n const region = normalize(entry.region)\n if (region !== undefined) body.region = region\n const postalCode = normalize(entry.postalCode)\n if (postalCode !== undefined) body.postalCode = postalCode\n const country = normalize(entry.country)\n if (country !== undefined) body.country = country.toUpperCase()\n try {\n await createCrud('customers/addresses', body)\n } catch (addressErr) {\n const message =\n (addressErr instanceof Error && addressErr.message\n ? addressErr.message\n : null) ||\n t('customers.people.detail.addresses.error')\n flash(message, 'error')\n }\n }\n }\n\n flash(t('customers.people.form.success'), 'success')\n if (returnTo) router.push(returnTo)\n else if (newId) router.push(`/backend/customers/people-v2/${newId}`)\n else router.push('/backend/customers/people')\n }}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
- "mappings": "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",
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 { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { createCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport {\n buildPersonPayload,\n createPersonFormFields,\n createPersonFormGroups,\n createPersonFormSchema,\n type PersonFormValues,\n} from '../../../../components/formConfig'\n\nexport default function CreatePersonPage() {\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { organizationId } = useOrganizationScopeDetail()\n\n const formSchema = React.useMemo(() => createPersonFormSchema(), [])\n const fields = React.useMemo(() => createPersonFormFields(t), [t])\n const groups = React.useMemo(() => createPersonFormGroups(t), [t])\n const returnTo = searchParams.get('returnTo')\n const companyParam = searchParams.get('companyId')\n const companyEntityId = React.useMemo(() => {\n if (!companyParam) return undefined\n const trimmed = companyParam.trim()\n return trimmed.length ? trimmed : undefined\n }, [companyParam])\n const initialValues = React.useMemo<Partial<PersonFormValues>>(\n () => ({\n addresses: [] as PersonFormValues['addresses'],\n ...(companyEntityId ? { companyEntityId } : {}),\n }),\n [companyEntityId],\n )\n\n return (\n <Page>\n <PageBody>\n <CrudForm<PersonFormValues>\n title={t('customers.people.create.title')}\n backHref={returnTo ?? '/backend/customers/people'}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n submitLabel={t('customers.people.form.submit')}\n cancelHref={returnTo ?? '/backend/customers/people'}\n schema={formSchema}\n onSubmit={async (values) => {\n const addresses = Array.isArray(values.addresses) ? values.addresses : []\n let payload: Record<string, unknown>\n try {\n payload = buildPersonPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error && err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.people.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n throw err\n }\n\n const { result: created } = await createCrud<{ id?: string; entityId?: string }>(\n 'customers/people',\n payload,\n )\n const newId =\n created && typeof created.id === 'string'\n ? created.id\n : (typeof created?.entityId === 'string' ? created.entityId : null)\n\n if (newId && addresses.length) {\n const normalize = (value?: string | null) => {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n return trimmed.length ? trimmed : undefined\n }\n for (const entry of addresses) {\n const normalizedLine1 = normalize(entry.addressLine1)\n if (!normalizedLine1) continue\n const body: Record<string, unknown> = {\n entityId: newId,\n ...(organizationId ? { organizationId } : {}),\n addressLine1: normalizedLine1,\n isPrimary: entry.isPrimary ?? false,\n }\n const name = normalize(entry.name)\n if (name !== undefined) body.name = name\n const purpose = normalize(entry.purpose)\n if (purpose !== undefined) body.purpose = purpose\n const line2 = normalize(entry.addressLine2)\n if (line2 !== undefined) body.addressLine2 = line2\n const buildingNumber = normalize(entry.buildingNumber)\n if (buildingNumber !== undefined) body.buildingNumber = buildingNumber\n const flatNumber = normalize(entry.flatNumber)\n if (flatNumber !== undefined) body.flatNumber = flatNumber\n const city = normalize(entry.city)\n if (city !== undefined) body.city = city\n const region = normalize(entry.region)\n if (region !== undefined) body.region = region\n const postalCode = normalize(entry.postalCode)\n if (postalCode !== undefined) body.postalCode = postalCode\n const country = normalize(entry.country)\n if (country !== undefined) body.country = country.toUpperCase()\n if (typeof entry.latitude === 'number') body.latitude = entry.latitude\n if (typeof entry.longitude === 'number') body.longitude = entry.longitude\n try {\n await createCrud('customers/addresses', body)\n } catch (addressErr) {\n const message =\n (addressErr instanceof Error && addressErr.message\n ? addressErr.message\n : null) ||\n t('customers.people.detail.addresses.error')\n flash(message, 'error')\n }\n }\n }\n\n flash(t('customers.people.form.success'), 'success')\n if (returnTo) router.push(returnTo)\n else if (newId) router.push(`/backend/customers/people-v2/${newId}`)\n else router.push('/backend/customers/people')\n }}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -33,7 +33,8 @@ function AddressEditor({
33
33
  disabled = false,
34
34
  errors = {},
35
35
  hidePrimaryToggle = false,
36
- showFormatHint = true
36
+ showFormatHint = true,
37
+ showCoordinateFields = false
37
38
  }) {
38
39
  const pathname = usePathname();
39
40
  const searchParams = useSearchParams();
@@ -61,6 +62,7 @@ function AddressEditor({
61
62
  region: value.region ?? "",
62
63
  postalCode: value.postalCode ?? "",
63
64
  country: value.country ?? "",
65
+ ...showCoordinateFields ? { latitude: value.latitude ?? "", longitude: value.longitude ?? "" } : {},
64
66
  isPrimary: value.isPrimary ?? false
65
67
  };
66
68
  const update = React.useCallback(
@@ -388,7 +390,37 @@ function AddressEditor({
388
390
  ]
389
391
  }
390
392
  ),
391
- errors.country ? /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: errors.country }) : null
393
+ errors.country ? /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: errors.country }) : null,
394
+ showCoordinateFields ? /* @__PURE__ */ jsxs(Fragment, { children: [
395
+ /* @__PURE__ */ jsx(
396
+ Input,
397
+ {
398
+ className: inputClass("latitude"),
399
+ placeholder: t("customers.people.detail.addresses.fields.latitude", "Latitude"),
400
+ "aria-label": t("customers.people.detail.addresses.fields.latitude", "Latitude"),
401
+ inputMode: "decimal",
402
+ value: current.latitude ?? "",
403
+ onChange: (evt) => update("latitude", evt.target.value),
404
+ disabled,
405
+ "aria-invalid": errors.latitude ? "true" : void 0
406
+ }
407
+ ),
408
+ errors.latitude ? /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: errors.latitude }) : null,
409
+ /* @__PURE__ */ jsx(
410
+ Input,
411
+ {
412
+ className: inputClass("longitude"),
413
+ placeholder: t("customers.people.detail.addresses.fields.longitude", "Longitude"),
414
+ "aria-label": t("customers.people.detail.addresses.fields.longitude", "Longitude"),
415
+ inputMode: "decimal",
416
+ value: current.longitude ?? "",
417
+ onChange: (evt) => update("longitude", evt.target.value),
418
+ disabled,
419
+ "aria-invalid": errors.longitude ? "true" : void 0
420
+ }
421
+ ),
422
+ errors.longitude ? /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: errors.longitude }) : null
423
+ ] }) : null
392
424
  ] }),
393
425
  !hidePrimaryToggle ? /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2 text-sm", children: [
394
426
  /* @__PURE__ */ jsx(
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/customers/components/AddressEditor.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { usePathname, useSearchParams } from 'next/navigation'\nimport { Plus, Settings } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from '@open-mercato/ui/primitives/dialog'\nimport { buildCountryOptions } from '@open-mercato/shared/lib/location/countries'\nimport { buildHrefWithReturnTo } from '@open-mercato/shared/lib/navigation/returnTo'\nimport type { AddressFormatStrategy } from '../utils/addressFormat'\nimport { useAddressTypes } from './detail/hooks/useAddressTypes'\n\ntype Translator = (key: string, fallback?: string, params?: Record<string, string | number>) => string\n\nexport type AddressEditorDraft = {\n name: string\n purpose: string\n companyName: string\n addressLine1: string\n addressLine2: string\n buildingNumber: string\n flatNumber: string\n city: string\n region: string\n postalCode: string\n country: string\n isPrimary: boolean\n}\n\nexport type AddressEditorField =\n | 'name'\n | 'purpose'\n | 'companyName'\n | 'addressLine1'\n | 'addressLine2'\n | 'buildingNumber'\n | 'flatNumber'\n | 'city'\n | 'region'\n | 'postalCode'\n | 'country'\n | 'isPrimary'\n\ntype AddressEditorProps = {\n value: AddressEditorDraft\n onChange: (next: AddressEditorDraft) => void\n format: AddressFormatStrategy\n t: Translator\n disabled?: boolean\n errors?: Partial<Record<AddressEditorField, string>>\n hidePrimaryToggle?: boolean\n showFormatHint?: boolean\n}\n\nexport function AddressEditor({\n value,\n onChange,\n format,\n t,\n disabled = false,\n errors = {},\n hidePrimaryToggle = false,\n showFormatHint = true,\n}: AddressEditorProps) {\n const pathname = usePathname()\n const searchParams = useSearchParams()\n const { options: addressTypes, loading: addressTypesLoading, error: addressTypeError, createType } = useAddressTypes(t)\n const [typeDialogOpen, setTypeDialogOpen] = React.useState(false)\n const [typeValue, setTypeValue] = React.useState('')\n const [typeFormError, setTypeFormError] = React.useState<string | null>(null)\n const [countryDialogOpen, setCountryDialogOpen] = React.useState(false)\n const [countryQuery, setCountryQuery] = React.useState('')\n\n const countryOptions = React.useMemo(\n () =>\n buildCountryOptions({\n transformLabel: (code, fallback) => t(`customers.countries.${code.toLowerCase()}`, fallback ?? code),\n }),\n [t],\n )\n\n const current: AddressEditorDraft = {\n name: value.name ?? '',\n purpose: value.purpose ?? '',\n companyName: value.companyName ?? '',\n addressLine1: value.addressLine1 ?? '',\n addressLine2: value.addressLine2 ?? '',\n buildingNumber: value.buildingNumber ?? '',\n flatNumber: value.flatNumber ?? '',\n city: value.city ?? '',\n region: value.region ?? '',\n postalCode: value.postalCode ?? '',\n country: value.country ?? '',\n isPrimary: value.isPrimary ?? false,\n }\n\n const update = React.useCallback(\n (key: keyof AddressEditorDraft, nextValue: string | boolean) => {\n onChange({ ...current, [key]: nextValue })\n },\n [current, onChange],\n )\n\n const filteredCountryOptions = React.useMemo(() => {\n const query = countryQuery.trim().toLowerCase()\n if (!query.length) return countryOptions\n return countryOptions.filter(\n (option) => option.label.toLowerCase().includes(query) || option.code.toLowerCase().includes(query),\n )\n }, [countryOptions, countryQuery])\n\n const selectedCountry = React.useMemo(() => {\n const code = (current.country ?? '').toUpperCase()\n if (!code.length) return null\n return countryOptions.find((option) => option.code === code) ?? null\n }, [countryOptions, current.country])\n const returnTo = React.useMemo(() => {\n const query = searchParams?.toString() ?? ''\n if (!pathname) return null\n return query.length ? `${pathname}?${query}` : pathname\n }, [pathname, searchParams])\n const manageAddressTypesHref = React.useMemo(\n () => buildHrefWithReturnTo('/backend/config/customers', returnTo),\n [returnTo],\n )\n\n const handleTypeSubmit = React.useCallback(\n async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault()\n const trimmed = typeValue.trim()\n if (!trimmed.length) {\n setTypeFormError(t('customers.people.detail.addresses.types.emptyError', 'Please provide a value'))\n return\n }\n setTypeFormError(null)\n await createType(trimmed)\n setTypeDialogOpen(false)\n setTypeValue('')\n },\n [createType, t, typeValue],\n )\n\n const inputClass = (field: AddressEditorField) =>\n [\n 'w-full rounded-md border px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring',\n errors[field] ? 'border-status-error-border focus:ring-status-error-border' : 'border-input bg-background',\n ].join(' ')\n\n return (\n <div className=\"space-y-3\">\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <Input\n className={inputClass('name')}\n placeholder={t('customers.people.detail.addresses.fields.label', 'Label')}\n value={current.name}\n onChange={(evt) => update('name', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.name ? 'true' : undefined}\n />\n <div className=\"flex gap-2\">\n <Select\n value={current.purpose || undefined}\n onValueChange={(next) => update('purpose', next ?? '')}\n disabled={disabled}\n >\n <SelectTrigger\n className={errors.purpose ? 'border-destructive' : undefined}\n aria-invalid={errors.purpose ? 'true' : undefined}\n >\n <SelectValue\n placeholder={\n addressTypesLoading\n ? t('customers.people.detail.addresses.types.loading', 'Loading\u2026')\n : t('customers.people.detail.addresses.types.placeholder', 'Address type')\n }\n />\n </SelectTrigger>\n <SelectContent>\n {addressTypes.map((entry) => (\n <SelectItem key={entry.value} value={entry.value}>\n {entry.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Dialog open={typeDialogOpen} onOpenChange={setTypeDialogOpen}>\n <DialogTrigger asChild>\n <Button type=\"button\" variant=\"outline\" size=\"icon\" className=\"shrink-0\" disabled={disabled}>\n <Plus className=\"h-4 w-4\" />\n </Button>\n </DialogTrigger>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>{t('customers.people.detail.addresses.types.add', 'Add address type')}</DialogTitle>\n <DialogDescription>\n {t('customers.people.detail.addresses.types.addHint', 'Create a new address type for reuse.')}\n </DialogDescription>\n </DialogHeader>\n <form className=\"space-y-3\" onSubmit={handleTypeSubmit}>\n <Input\n autoFocus\n value={typeValue}\n onChange={(evt) => {\n setTypeValue(evt.target.value)\n if (typeFormError) setTypeFormError(null)\n }}\n placeholder={t('customers.people.detail.addresses.types.placeholder', 'Address type')}\n disabled={disabled}\n aria-invalid={typeFormError ? 'true' : undefined}\n />\n {typeFormError ? <p className=\"text-sm text-destructive\">{typeFormError}</p> : null}\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setTypeDialogOpen(false)} disabled={disabled}>\n {t('customers.people.detail.addresses.types.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={disabled || !typeValue.trim()}>\n {t('customers.people.detail.addresses.types.save', 'Save')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n <Button\n asChild\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"shrink-0\"\n disabled={disabled}\n title={t('customers.people.detail.addresses.types.manage', 'Manage address types')}\n >\n <Link\n href={manageAddressTypesHref}\n aria-label={t('customers.people.detail.addresses.types.manage', 'Manage address types')}\n >\n <Settings className=\"h-4 w-4\" />\n </Link>\n </Button>\n </div>\n </div>\n {errors.purpose ? <p className=\"text-xs text-destructive\">{errors.purpose}</p> : null}\n {addressTypeError ? <p className=\"text-xs text-destructive\">{addressTypeError}</p> : null}\n <Input\n className={inputClass('companyName')}\n placeholder={t('customers.people.detail.addresses.fields.companyName', 'Company name')}\n value={current.companyName}\n onChange={(evt) => update('companyName', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.companyName ? 'true' : undefined}\n />\n {showFormatHint ? (\n <p className=\"text-xs text-muted-foreground\">\n {format === 'street_first'\n ? t('customers.people.detail.addresses.streetFormatHint', 'Street-first layout is active.')\n : t('customers.people.detail.addresses.lineFormatHint', 'Address-line layout is active.')}\n </p>\n ) : null}\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2\">\n <Input\n className={inputClass('addressLine1')}\n placeholder={\n format === 'street_first'\n ? t('customers.people.detail.addresses.fields.street', 'Street')\n : t('customers.people.detail.addresses.fields.line1', 'Address line 1')\n }\n value={current.addressLine1}\n onChange={(evt) => update('addressLine1', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.addressLine1 ? 'true' : undefined}\n />\n {errors.addressLine1 ? <p className=\"text-xs text-destructive sm:col-span-2\">{errors.addressLine1}</p> : null}\n {format === 'street_first' ? (\n <>\n <Input\n className={inputClass('buildingNumber')}\n placeholder={t('customers.people.detail.addresses.fields.buildingNumber', 'Building number')}\n value={current.buildingNumber}\n onChange={(evt) => update('buildingNumber', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.buildingNumber ? 'true' : undefined}\n />\n <Input\n className={inputClass('flatNumber')}\n placeholder={t('customers.people.detail.addresses.fields.flatNumber', 'Flat number')}\n value={current.flatNumber}\n onChange={(evt) => update('flatNumber', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.flatNumber ? 'true' : undefined}\n />\n <Input\n className={inputClass('addressLine2')}\n placeholder={t('customers.people.detail.addresses.fields.streetExtra', 'Address line 2')}\n value={current.addressLine2}\n onChange={(evt) => update('addressLine2', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.addressLine2 ? 'true' : undefined}\n />\n {errors.addressLine2 ? <p className=\"text-xs text-destructive sm:col-span-2\">{errors.addressLine2}</p> : null}\n </>\n ) : (\n <>\n <Input\n className={inputClass('addressLine2')}\n placeholder={t('customers.people.detail.addresses.fields.line2', 'Address line 2')}\n value={current.addressLine2}\n onChange={(evt) => update('addressLine2', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.addressLine2 ? 'true' : undefined}\n />\n {errors.addressLine2 ? <p className=\"text-xs text-destructive sm:col-span-2\">{errors.addressLine2}</p> : null}\n </>\n )}\n <Input\n className={inputClass('city')}\n placeholder={t('customers.people.detail.addresses.fields.city', 'City')}\n value={current.city}\n onChange={(evt) => update('city', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.city ? 'true' : undefined}\n />\n {errors.city ? <p className=\"text-xs text-destructive\">{errors.city}</p> : null}\n <Input\n className={inputClass('region')}\n placeholder={t('customers.people.detail.addresses.fields.region', 'Region/state')}\n value={current.region}\n onChange={(evt) => update('region', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.region ? 'true' : undefined}\n />\n {errors.region ? <p className=\"text-xs text-destructive\">{errors.region}</p> : null}\n <Input\n className={inputClass('postalCode')}\n placeholder={t('customers.people.detail.addresses.fields.postalCode', 'Postal code')}\n value={current.postalCode}\n onChange={(evt) => update('postalCode', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.postalCode ? 'true' : undefined}\n />\n {errors.postalCode ? <p className=\"text-xs text-destructive\">{errors.postalCode}</p> : null}\n <Dialog\n open={countryDialogOpen}\n onOpenChange={(open) => {\n setCountryDialogOpen(open)\n if (!open) setCountryQuery('')\n }}\n >\n <DialogTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n className={`${inputClass('country')} h-10 w-full justify-between`}\n disabled={disabled}\n aria-invalid={errors.country ? 'true' : undefined}\n >\n <span className=\"truncate text-left\">\n {selectedCountry\n ? `${selectedCountry.label}`\n : t('customers.people.detail.addresses.countryPlaceholder', 'Select country')}\n </span>\n <span className=\"ml-2 text-xs text-muted-foreground\">\n {selectedCountry ? selectedCountry.code : null}\n </span>\n </Button>\n </DialogTrigger>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>{t('customers.people.detail.addresses.countryDialogTitle', 'Select country')}</DialogTitle>\n <DialogDescription>\n {t('customers.people.detail.addresses.countryDialogDescription', 'Search and choose an ISO country code.')}\n </DialogDescription>\n </DialogHeader>\n <div className=\"space-y-3\">\n <Input\n placeholder={t('customers.people.detail.addresses.countrySearch', 'Search country')}\n value={countryQuery}\n onChange={(evt) => setCountryQuery(evt.target.value)}\n />\n <div className=\"max-h-64 overflow-y-auto rounded border divide-y\">\n {filteredCountryOptions.length === 0 ? (\n <p className=\"px-3 py-2 text-sm text-muted-foreground\">\n {t('customers.people.detail.addresses.countryEmpty', 'No matches found')}\n </p>\n ) : (\n filteredCountryOptions.map((option) => (\n <Button\n key={option.code}\n variant=\"ghost\"\n size=\"sm\"\n className=\"w-full justify-between rounded-none font-normal\"\n onClick={() => {\n update('country', option.code)\n setCountryDialogOpen(false)\n setCountryQuery('')\n }}\n >\n <span className=\"truncate\">{option.label}</span>\n <span className=\"text-xs text-muted-foreground\">{option.code}</span>\n </Button>\n ))\n )}\n </div>\n <div className=\"flex items-center justify-between gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n update('country', '')\n setCountryDialogOpen(false)\n setCountryQuery('')\n }}\n disabled={disabled}\n >\n {t('customers.people.detail.addresses.countryClear', 'Clear')}\n </Button>\n <Button type=\"button\" onClick={() => setCountryDialogOpen(false)}>\n {t('customers.people.detail.addresses.countryClose', 'Done')}\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n {errors.country ? <p className=\"text-xs text-destructive\">{errors.country}</p> : null}\n </div>\n {!hidePrimaryToggle ? (\n <label className=\"inline-flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={current.isPrimary}\n onChange={(evt) => update('isPrimary', evt.target.checked)}\n disabled={disabled}\n aria-invalid={errors.isPrimary ? 'true' : undefined}\n />\n <span>{t('customers.people.detail.addresses.fields.primary', 'Set as primary')}</span>\n </label>\n ) : null}\n {errors.isPrimary ? <p className=\"text-xs text-destructive\">{errors.isPrimary}</p> : null}\n </div>\n )\n}\n\nexport default AddressEditor\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { usePathname, useSearchParams } from 'next/navigation'\nimport { Plus, Settings } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from '@open-mercato/ui/primitives/dialog'\nimport { buildCountryOptions } from '@open-mercato/shared/lib/location/countries'\nimport { buildHrefWithReturnTo } from '@open-mercato/shared/lib/navigation/returnTo'\nimport type { AddressFormatStrategy } from '../utils/addressFormat'\nimport { useAddressTypes } from './detail/hooks/useAddressTypes'\n\ntype Translator = (key: string, fallback?: string, params?: Record<string, string | number>) => string\n\nexport type AddressEditorDraft = {\n name: string\n purpose: string\n companyName: string\n addressLine1: string\n addressLine2: string\n buildingNumber: string\n flatNumber: string\n city: string\n region: string\n postalCode: string\n country: string\n latitude?: string\n longitude?: string\n isPrimary: boolean\n}\n\nexport type AddressEditorField =\n | 'name'\n | 'purpose'\n | 'companyName'\n | 'addressLine1'\n | 'addressLine2'\n | 'buildingNumber'\n | 'flatNumber'\n | 'city'\n | 'region'\n | 'postalCode'\n | 'country'\n | 'latitude'\n | 'longitude'\n | 'isPrimary'\n\ntype AddressEditorProps = {\n value: AddressEditorDraft\n onChange: (next: AddressEditorDraft) => void\n format: AddressFormatStrategy\n t: Translator\n disabled?: boolean\n errors?: Partial<Record<AddressEditorField, string>>\n hidePrimaryToggle?: boolean\n showFormatHint?: boolean\n showCoordinateFields?: boolean\n}\n\nexport function AddressEditor({\n value,\n onChange,\n format,\n t,\n disabled = false,\n errors = {},\n hidePrimaryToggle = false,\n showFormatHint = true,\n showCoordinateFields = false,\n}: AddressEditorProps) {\n const pathname = usePathname()\n const searchParams = useSearchParams()\n const { options: addressTypes, loading: addressTypesLoading, error: addressTypeError, createType } = useAddressTypes(t)\n const [typeDialogOpen, setTypeDialogOpen] = React.useState(false)\n const [typeValue, setTypeValue] = React.useState('')\n const [typeFormError, setTypeFormError] = React.useState<string | null>(null)\n const [countryDialogOpen, setCountryDialogOpen] = React.useState(false)\n const [countryQuery, setCountryQuery] = React.useState('')\n\n const countryOptions = React.useMemo(\n () =>\n buildCountryOptions({\n transformLabel: (code, fallback) => t(`customers.countries.${code.toLowerCase()}`, fallback ?? code),\n }),\n [t],\n )\n\n const current: AddressEditorDraft = {\n name: value.name ?? '',\n purpose: value.purpose ?? '',\n companyName: value.companyName ?? '',\n addressLine1: value.addressLine1 ?? '',\n addressLine2: value.addressLine2 ?? '',\n buildingNumber: value.buildingNumber ?? '',\n flatNumber: value.flatNumber ?? '',\n city: value.city ?? '',\n region: value.region ?? '',\n postalCode: value.postalCode ?? '',\n country: value.country ?? '',\n ...(showCoordinateFields\n ? { latitude: value.latitude ?? '', longitude: value.longitude ?? '' }\n : {}),\n isPrimary: value.isPrimary ?? false,\n }\n\n const update = React.useCallback(\n (key: keyof AddressEditorDraft, nextValue: string | boolean) => {\n onChange({ ...current, [key]: nextValue })\n },\n [current, onChange],\n )\n\n const filteredCountryOptions = React.useMemo(() => {\n const query = countryQuery.trim().toLowerCase()\n if (!query.length) return countryOptions\n return countryOptions.filter(\n (option) => option.label.toLowerCase().includes(query) || option.code.toLowerCase().includes(query),\n )\n }, [countryOptions, countryQuery])\n\n const selectedCountry = React.useMemo(() => {\n const code = (current.country ?? '').toUpperCase()\n if (!code.length) return null\n return countryOptions.find((option) => option.code === code) ?? null\n }, [countryOptions, current.country])\n const returnTo = React.useMemo(() => {\n const query = searchParams?.toString() ?? ''\n if (!pathname) return null\n return query.length ? `${pathname}?${query}` : pathname\n }, [pathname, searchParams])\n const manageAddressTypesHref = React.useMemo(\n () => buildHrefWithReturnTo('/backend/config/customers', returnTo),\n [returnTo],\n )\n\n const handleTypeSubmit = React.useCallback(\n async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault()\n const trimmed = typeValue.trim()\n if (!trimmed.length) {\n setTypeFormError(t('customers.people.detail.addresses.types.emptyError', 'Please provide a value'))\n return\n }\n setTypeFormError(null)\n await createType(trimmed)\n setTypeDialogOpen(false)\n setTypeValue('')\n },\n [createType, t, typeValue],\n )\n\n const inputClass = (field: AddressEditorField) =>\n [\n 'w-full rounded-md border px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring',\n errors[field] ? 'border-status-error-border focus:ring-status-error-border' : 'border-input bg-background',\n ].join(' ')\n\n return (\n <div className=\"space-y-3\">\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <Input\n className={inputClass('name')}\n placeholder={t('customers.people.detail.addresses.fields.label', 'Label')}\n value={current.name}\n onChange={(evt) => update('name', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.name ? 'true' : undefined}\n />\n <div className=\"flex gap-2\">\n <Select\n value={current.purpose || undefined}\n onValueChange={(next) => update('purpose', next ?? '')}\n disabled={disabled}\n >\n <SelectTrigger\n className={errors.purpose ? 'border-destructive' : undefined}\n aria-invalid={errors.purpose ? 'true' : undefined}\n >\n <SelectValue\n placeholder={\n addressTypesLoading\n ? t('customers.people.detail.addresses.types.loading', 'Loading\u2026')\n : t('customers.people.detail.addresses.types.placeholder', 'Address type')\n }\n />\n </SelectTrigger>\n <SelectContent>\n {addressTypes.map((entry) => (\n <SelectItem key={entry.value} value={entry.value}>\n {entry.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Dialog open={typeDialogOpen} onOpenChange={setTypeDialogOpen}>\n <DialogTrigger asChild>\n <Button type=\"button\" variant=\"outline\" size=\"icon\" className=\"shrink-0\" disabled={disabled}>\n <Plus className=\"h-4 w-4\" />\n </Button>\n </DialogTrigger>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>{t('customers.people.detail.addresses.types.add', 'Add address type')}</DialogTitle>\n <DialogDescription>\n {t('customers.people.detail.addresses.types.addHint', 'Create a new address type for reuse.')}\n </DialogDescription>\n </DialogHeader>\n <form className=\"space-y-3\" onSubmit={handleTypeSubmit}>\n <Input\n autoFocus\n value={typeValue}\n onChange={(evt) => {\n setTypeValue(evt.target.value)\n if (typeFormError) setTypeFormError(null)\n }}\n placeholder={t('customers.people.detail.addresses.types.placeholder', 'Address type')}\n disabled={disabled}\n aria-invalid={typeFormError ? 'true' : undefined}\n />\n {typeFormError ? <p className=\"text-sm text-destructive\">{typeFormError}</p> : null}\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setTypeDialogOpen(false)} disabled={disabled}>\n {t('customers.people.detail.addresses.types.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={disabled || !typeValue.trim()}>\n {t('customers.people.detail.addresses.types.save', 'Save')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n <Button\n asChild\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"shrink-0\"\n disabled={disabled}\n title={t('customers.people.detail.addresses.types.manage', 'Manage address types')}\n >\n <Link\n href={manageAddressTypesHref}\n aria-label={t('customers.people.detail.addresses.types.manage', 'Manage address types')}\n >\n <Settings className=\"h-4 w-4\" />\n </Link>\n </Button>\n </div>\n </div>\n {errors.purpose ? <p className=\"text-xs text-destructive\">{errors.purpose}</p> : null}\n {addressTypeError ? <p className=\"text-xs text-destructive\">{addressTypeError}</p> : null}\n <Input\n className={inputClass('companyName')}\n placeholder={t('customers.people.detail.addresses.fields.companyName', 'Company name')}\n value={current.companyName}\n onChange={(evt) => update('companyName', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.companyName ? 'true' : undefined}\n />\n {showFormatHint ? (\n <p className=\"text-xs text-muted-foreground\">\n {format === 'street_first'\n ? t('customers.people.detail.addresses.streetFormatHint', 'Street-first layout is active.')\n : t('customers.people.detail.addresses.lineFormatHint', 'Address-line layout is active.')}\n </p>\n ) : null}\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2\">\n <Input\n className={inputClass('addressLine1')}\n placeholder={\n format === 'street_first'\n ? t('customers.people.detail.addresses.fields.street', 'Street')\n : t('customers.people.detail.addresses.fields.line1', 'Address line 1')\n }\n value={current.addressLine1}\n onChange={(evt) => update('addressLine1', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.addressLine1 ? 'true' : undefined}\n />\n {errors.addressLine1 ? <p className=\"text-xs text-destructive sm:col-span-2\">{errors.addressLine1}</p> : null}\n {format === 'street_first' ? (\n <>\n <Input\n className={inputClass('buildingNumber')}\n placeholder={t('customers.people.detail.addresses.fields.buildingNumber', 'Building number')}\n value={current.buildingNumber}\n onChange={(evt) => update('buildingNumber', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.buildingNumber ? 'true' : undefined}\n />\n <Input\n className={inputClass('flatNumber')}\n placeholder={t('customers.people.detail.addresses.fields.flatNumber', 'Flat number')}\n value={current.flatNumber}\n onChange={(evt) => update('flatNumber', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.flatNumber ? 'true' : undefined}\n />\n <Input\n className={inputClass('addressLine2')}\n placeholder={t('customers.people.detail.addresses.fields.streetExtra', 'Address line 2')}\n value={current.addressLine2}\n onChange={(evt) => update('addressLine2', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.addressLine2 ? 'true' : undefined}\n />\n {errors.addressLine2 ? <p className=\"text-xs text-destructive sm:col-span-2\">{errors.addressLine2}</p> : null}\n </>\n ) : (\n <>\n <Input\n className={inputClass('addressLine2')}\n placeholder={t('customers.people.detail.addresses.fields.line2', 'Address line 2')}\n value={current.addressLine2}\n onChange={(evt) => update('addressLine2', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.addressLine2 ? 'true' : undefined}\n />\n {errors.addressLine2 ? <p className=\"text-xs text-destructive sm:col-span-2\">{errors.addressLine2}</p> : null}\n </>\n )}\n <Input\n className={inputClass('city')}\n placeholder={t('customers.people.detail.addresses.fields.city', 'City')}\n value={current.city}\n onChange={(evt) => update('city', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.city ? 'true' : undefined}\n />\n {errors.city ? <p className=\"text-xs text-destructive\">{errors.city}</p> : null}\n <Input\n className={inputClass('region')}\n placeholder={t('customers.people.detail.addresses.fields.region', 'Region/state')}\n value={current.region}\n onChange={(evt) => update('region', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.region ? 'true' : undefined}\n />\n {errors.region ? <p className=\"text-xs text-destructive\">{errors.region}</p> : null}\n <Input\n className={inputClass('postalCode')}\n placeholder={t('customers.people.detail.addresses.fields.postalCode', 'Postal code')}\n value={current.postalCode}\n onChange={(evt) => update('postalCode', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.postalCode ? 'true' : undefined}\n />\n {errors.postalCode ? <p className=\"text-xs text-destructive\">{errors.postalCode}</p> : null}\n <Dialog\n open={countryDialogOpen}\n onOpenChange={(open) => {\n setCountryDialogOpen(open)\n if (!open) setCountryQuery('')\n }}\n >\n <DialogTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n className={`${inputClass('country')} h-10 w-full justify-between`}\n disabled={disabled}\n aria-invalid={errors.country ? 'true' : undefined}\n >\n <span className=\"truncate text-left\">\n {selectedCountry\n ? `${selectedCountry.label}`\n : t('customers.people.detail.addresses.countryPlaceholder', 'Select country')}\n </span>\n <span className=\"ml-2 text-xs text-muted-foreground\">\n {selectedCountry ? selectedCountry.code : null}\n </span>\n </Button>\n </DialogTrigger>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>{t('customers.people.detail.addresses.countryDialogTitle', 'Select country')}</DialogTitle>\n <DialogDescription>\n {t('customers.people.detail.addresses.countryDialogDescription', 'Search and choose an ISO country code.')}\n </DialogDescription>\n </DialogHeader>\n <div className=\"space-y-3\">\n <Input\n placeholder={t('customers.people.detail.addresses.countrySearch', 'Search country')}\n value={countryQuery}\n onChange={(evt) => setCountryQuery(evt.target.value)}\n />\n <div className=\"max-h-64 overflow-y-auto rounded border divide-y\">\n {filteredCountryOptions.length === 0 ? (\n <p className=\"px-3 py-2 text-sm text-muted-foreground\">\n {t('customers.people.detail.addresses.countryEmpty', 'No matches found')}\n </p>\n ) : (\n filteredCountryOptions.map((option) => (\n <Button\n key={option.code}\n variant=\"ghost\"\n size=\"sm\"\n className=\"w-full justify-between rounded-none font-normal\"\n onClick={() => {\n update('country', option.code)\n setCountryDialogOpen(false)\n setCountryQuery('')\n }}\n >\n <span className=\"truncate\">{option.label}</span>\n <span className=\"text-xs text-muted-foreground\">{option.code}</span>\n </Button>\n ))\n )}\n </div>\n <div className=\"flex items-center justify-between gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n update('country', '')\n setCountryDialogOpen(false)\n setCountryQuery('')\n }}\n disabled={disabled}\n >\n {t('customers.people.detail.addresses.countryClear', 'Clear')}\n </Button>\n <Button type=\"button\" onClick={() => setCountryDialogOpen(false)}>\n {t('customers.people.detail.addresses.countryClose', 'Done')}\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n {errors.country ? <p className=\"text-xs text-destructive\">{errors.country}</p> : null}\n {showCoordinateFields ? (\n <>\n <Input\n className={inputClass('latitude')}\n placeholder={t('customers.people.detail.addresses.fields.latitude', 'Latitude')}\n aria-label={t('customers.people.detail.addresses.fields.latitude', 'Latitude')}\n inputMode=\"decimal\"\n value={current.latitude ?? ''}\n onChange={(evt) => update('latitude', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.latitude ? 'true' : undefined}\n />\n {errors.latitude ? <p className=\"text-xs text-destructive\">{errors.latitude}</p> : null}\n <Input\n className={inputClass('longitude')}\n placeholder={t('customers.people.detail.addresses.fields.longitude', 'Longitude')}\n aria-label={t('customers.people.detail.addresses.fields.longitude', 'Longitude')}\n inputMode=\"decimal\"\n value={current.longitude ?? ''}\n onChange={(evt) => update('longitude', evt.target.value)}\n disabled={disabled}\n aria-invalid={errors.longitude ? 'true' : undefined}\n />\n {errors.longitude ? <p className=\"text-xs text-destructive\">{errors.longitude}</p> : null}\n </>\n ) : null}\n </div>\n {!hidePrimaryToggle ? (\n <label className=\"inline-flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={current.isPrimary}\n onChange={(evt) => update('isPrimary', evt.target.checked)}\n disabled={disabled}\n aria-invalid={errors.isPrimary ? 'true' : undefined}\n />\n <span>{t('customers.people.detail.addresses.fields.primary', 'Set as primary')}</span>\n </label>\n ) : null}\n {errors.isPrimary ? <p className=\"text-xs text-destructive\">{errors.isPrimary}</p> : null}\n </div>\n )\n}\n\nexport default AddressEditor\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }