@open-mercato/core 0.6.6-develop.6385.1.9a81faa5f0 → 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 (69) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/attachments/lib/scope.js +26 -0
  3. package/dist/modules/attachments/lib/scope.js.map +7 -0
  4. package/dist/modules/catalog/commands/variants.js +4 -2
  5. package/dist/modules/catalog/commands/variants.js.map +2 -2
  6. package/dist/modules/customers/api/deals/map/route.js +433 -0
  7. package/dist/modules/customers/api/deals/map/route.js.map +7 -0
  8. package/dist/modules/customers/backend/customers/companies/create/page.js +2 -0
  9. package/dist/modules/customers/backend/customers/companies/create/page.js.map +2 -2
  10. package/dist/modules/customers/backend/customers/deals/map/components/DealsLocationPanel.js +159 -0
  11. package/dist/modules/customers/backend/customers/deals/map/components/DealsLocationPanel.js.map +7 -0
  12. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvas.js +26 -0
  13. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvas.js.map +7 -0
  14. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.js +321 -0
  15. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.js.map +7 -0
  16. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapView.js +533 -0
  17. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapView.js.map +7 -0
  18. package/dist/modules/customers/backend/customers/deals/map/page.js +55 -0
  19. package/dist/modules/customers/backend/customers/deals/map/page.js.map +7 -0
  20. package/dist/modules/customers/backend/customers/deals/map/page.meta.js +38 -0
  21. package/dist/modules/customers/backend/customers/deals/map/page.meta.js.map +7 -0
  22. package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.js +3 -3
  23. package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.js.map +2 -2
  24. package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js +22 -1
  25. package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js.map +2 -2
  26. package/dist/modules/customers/backend/customers/people/create/page.js +2 -0
  27. package/dist/modules/customers/backend/customers/people/create/page.js.map +2 -2
  28. package/dist/modules/customers/components/AddressEditor.js +34 -2
  29. package/dist/modules/customers/components/AddressEditor.js.map +2 -2
  30. package/dist/modules/customers/components/AddressTiles.js +43 -3
  31. package/dist/modules/customers/components/AddressTiles.js.map +2 -2
  32. package/dist/modules/customers/components/detail/AddressesSection.js +4 -1
  33. package/dist/modules/customers/components/detail/AddressesSection.js.map +2 -2
  34. package/dist/modules/customers/components/formConfig.js +10 -0
  35. package/dist/modules/customers/components/formConfig.js.map +2 -2
  36. package/dist/modules/customers/data/validators.js +3 -2
  37. package/dist/modules/customers/data/validators.js.map +2 -2
  38. package/dist/modules/customers/lib/dealsMapLocation.js +75 -0
  39. package/dist/modules/customers/lib/dealsMapLocation.js.map +7 -0
  40. package/dist/modules/messages/commands/messages.js +0 -1
  41. package/dist/modules/messages/commands/messages.js.map +2 -2
  42. package/dist/modules/messages/lib/attachments.js +13 -7
  43. package/dist/modules/messages/lib/attachments.js.map +2 -2
  44. package/package.json +11 -7
  45. package/src/modules/attachments/lib/scope.ts +42 -0
  46. package/src/modules/catalog/commands/variants.ts +7 -2
  47. package/src/modules/customers/api/deals/map/route.ts +549 -0
  48. package/src/modules/customers/backend/customers/companies/create/page.tsx +2 -0
  49. package/src/modules/customers/backend/customers/deals/map/components/DealsLocationPanel.tsx +213 -0
  50. package/src/modules/customers/backend/customers/deals/map/components/DealsMapCanvas.tsx +79 -0
  51. package/src/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.tsx +407 -0
  52. package/src/modules/customers/backend/customers/deals/map/components/DealsMapView.tsx +667 -0
  53. package/src/modules/customers/backend/customers/deals/map/page.meta.ts +36 -0
  54. package/src/modules/customers/backend/customers/deals/map/page.tsx +77 -0
  55. package/src/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.tsx +3 -3
  56. package/src/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.tsx +22 -1
  57. package/src/modules/customers/backend/customers/people/create/page.tsx +2 -0
  58. package/src/modules/customers/components/AddressEditor.tsx +35 -0
  59. package/src/modules/customers/components/AddressTiles.tsx +51 -1
  60. package/src/modules/customers/components/detail/AddressesSection.tsx +3 -0
  61. package/src/modules/customers/components/formConfig.tsx +10 -0
  62. package/src/modules/customers/data/validators.ts +13 -2
  63. package/src/modules/customers/i18n/de.json +24 -0
  64. package/src/modules/customers/i18n/en.json +24 -0
  65. package/src/modules/customers/i18n/es.json +24 -0
  66. package/src/modules/customers/i18n/pl.json +24 -0
  67. package/src/modules/customers/lib/dealsMapLocation.ts +125 -0
  68. package/src/modules/messages/commands/messages.ts +0 -1
  69. package/src/modules/messages/lib/attachments.ts +15 -7
@@ -8,6 +8,7 @@ import { TabEmptyState } from "@open-mercato/ui/backend/detail";
8
8
  import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
9
9
  import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
10
10
  import { AddressView, formatAddressJson, formatAddressString } from "../utils/addressFormat.js";
11
+ import { normalizeCoordinateInput, validateCoordinateInput } from "@open-mercato/shared/lib/location/coordinates";
11
12
  import AddressEditor from "./AddressEditor.js";
12
13
  import { useAddressTypes } from "./detail/hooks/useAddressTypes.js";
13
14
  import { useQueryClient } from "@tanstack/react-query";
@@ -23,6 +24,8 @@ const defaultDraft = {
23
24
  region: "",
24
25
  postalCode: "",
25
26
  country: "",
27
+ latitude: "",
28
+ longitude: "",
26
29
  isPrimary: false
27
30
  };
28
31
  const serverFieldMap = {
@@ -37,6 +40,8 @@ const serverFieldMap = {
37
40
  region: "region",
38
41
  postalCode: "postalCode",
39
42
  country: "country",
43
+ latitude: "latitude",
44
+ longitude: "longitude",
40
45
  isPrimary: "isPrimary"
41
46
  };
42
47
  function normalizeOptional(value) {
@@ -86,7 +91,8 @@ function CustomerAddressTiles({
86
91
  hideAddButton = false,
87
92
  onAddActionChange,
88
93
  emptyStateTitle,
89
- emptyStateActionLabel
94
+ emptyStateActionLabel,
95
+ showCoordinateFields = false
90
96
  }) {
91
97
  const scopeVersion = useOrganizationScopeVersion();
92
98
  const queryClient = useQueryClient();
@@ -114,6 +120,8 @@ function CustomerAddressTiles({
114
120
  region: t("customers.people.detail.addresses.fields.region"),
115
121
  postalCode: t("customers.people.detail.addresses.fields.postalCode"),
116
122
  country: t("customers.people.detail.addresses.fields.country"),
123
+ latitude: t("customers.people.detail.addresses.fields.latitude", "Latitude"),
124
+ longitude: t("customers.people.detail.addresses.fields.longitude", "Longitude"),
117
125
  isPrimary: t("customers.people.detail.addresses.fields.primary")
118
126
  }),
119
127
  [t]
@@ -182,6 +190,8 @@ function CustomerAddressTiles({
182
190
  region: address.region ?? "",
183
191
  postalCode: address.postalCode ?? "",
184
192
  country: address.country ? address.country.toUpperCase() : "",
193
+ latitude: address.latitude != null ? String(address.latitude) : "",
194
+ longitude: address.longitude != null ? String(address.longitude) : "",
185
195
  isPrimary: address.isPrimary ?? false
186
196
  });
187
197
  setFieldErrors({});
@@ -207,6 +217,28 @@ function CustomerAddressTiles({
207
217
  setGeneralError(message);
208
218
  return;
209
219
  }
220
+ const coordinateErrors = {};
221
+ for (const key of ["latitude", "longitude"]) {
222
+ const result = validateCoordinateInput(key, draft[key]);
223
+ if (result.status === "invalid") {
224
+ coordinateErrors[key] = t(
225
+ "customers.people.detail.addresses.validation.invalid",
226
+ void 0,
227
+ { field: fieldLabels[key] }
228
+ );
229
+ } else if (result.status === "outOfRange") {
230
+ coordinateErrors[key] = t(
231
+ "customers.people.detail.addresses.validation.coordinateRange",
232
+ void 0,
233
+ { field: fieldLabels[key], min: result.min, max: result.max }
234
+ );
235
+ }
236
+ }
237
+ if (Object.keys(coordinateErrors).length) {
238
+ setFieldErrors((prev) => ({ ...prev, ...coordinateErrors }));
239
+ setGeneralError(Object.values(coordinateErrors)[0] ?? null);
240
+ return;
241
+ }
210
242
  const payload = {
211
243
  addressLine1: trimmedLine1,
212
244
  isPrimary: draft.isPrimary
@@ -231,6 +263,12 @@ function CustomerAddressTiles({
231
263
  if (postal !== void 0) payload.postalCode = postal;
232
264
  const country = normalizeOptional(draft.country);
233
265
  if (country !== void 0) payload.country = country.toUpperCase();
266
+ const latitude = normalizeCoordinateInput(draft.latitude);
267
+ if (latitude !== void 0) payload.latitude = latitude;
268
+ else if (editingId) payload.latitude = null;
269
+ const longitude = normalizeCoordinateInput(draft.longitude);
270
+ if (longitude !== void 0) payload.longitude = longitude;
271
+ else if (editingId) payload.longitude = null;
234
272
  setSaving(true);
235
273
  setGeneralError(null);
236
274
  setFieldErrors({});
@@ -327,7 +365,7 @@ function CustomerAddressTiles({
327
365
  {
328
366
  value: draft,
329
367
  onChange: (next) => {
330
- setDraft(next);
368
+ setDraft({ ...next, latitude: next.latitude ?? "", longitude: next.longitude ?? "" });
331
369
  if (Object.keys(fieldErrors).length) {
332
370
  const nextErrors = { ...fieldErrors };
333
371
  Object.keys(nextErrors).forEach((key2) => {
@@ -343,7 +381,8 @@ function CustomerAddressTiles({
343
381
  t,
344
382
  disabled: disableActions,
345
383
  errors: fieldErrors,
346
- showFormatHint: !formatLoading
384
+ showFormatHint: !formatLoading,
385
+ showCoordinateFields
347
386
  }
348
387
  ),
349
388
  generalError ? /* @__PURE__ */ jsx("p", { className: "text-xs text-status-error-text", children: generalError }) : null,
@@ -370,6 +409,7 @@ function CustomerAddressTiles({
370
409
  handleSave,
371
410
  generalError,
372
411
  saving,
412
+ showCoordinateFields,
373
413
  t
374
414
  ]
375
415
  );
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/customers/components/AddressTiles.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Loader2, Pencil, Plus, Trash2, X } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { TabEmptyState } from '@open-mercato/ui/backend/detail'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { AddressView, formatAddressJson, formatAddressString, type AddressFormatStrategy } from '../utils/addressFormat'\nimport AddressEditor from './AddressEditor'\nimport { useAddressTypes } from './detail/hooks/useAddressTypes'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from '@open-mercato/ui/primitives/dialog'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { ensureCustomerDictionary, invalidateCustomerDictionary } from './detail/hooks/useCustomerDictionary'\n\nexport type Translator = (\n key: string,\n fallback?: string,\n params?: Record<string, string | number>,\n) => string\n\nexport type CustomerAddressInput = {\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 CustomerAddressValue = CustomerAddressInput & {\n id: string\n purpose?: string | null\n companyName?: string | null\n}\n\ntype CustomerAddressTilesProps = {\n addresses: CustomerAddressValue[]\n onCreate: (payload: CustomerAddressInput) => Promise<void> | void\n onUpdate?: (id: string, payload: CustomerAddressInput) => Promise<void> | void\n onDelete?: (id: string) => Promise<void> | void\n t: Translator\n emptyLabel: string\n isSubmitting?: boolean\n gridClassName?: string\n hideAddButton?: boolean\n onAddActionChange?: (action: { openCreateForm: () => void; addDisabled: boolean } | null) => void\n emptyStateTitle?: string\n emptyStateActionLabel?: string\n}\n\ntype DraftAddressState = {\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\ntype DraftFieldKey = keyof DraftAddressState\n\ntype AddressValidationDetail = {\n path?: Array<string | number>\n code?: string\n message?: string\n minimum?: number\n maximum?: number\n type?: string\n}\n\nconst defaultDraft: DraftAddressState = {\n name: '',\n purpose: '',\n companyName: '',\n addressLine1: '',\n addressLine2: '',\n buildingNumber: '',\n flatNumber: '',\n city: '',\n region: '',\n postalCode: '',\n country: '',\n isPrimary: false,\n}\n\nconst serverFieldMap: Record<string, DraftFieldKey> = {\n name: 'name',\n purpose: 'purpose',\n companyName: 'companyName',\n addressLine1: 'addressLine1',\n addressLine2: 'addressLine2',\n buildingNumber: 'buildingNumber',\n flatNumber: 'flatNumber',\n city: 'city',\n region: 'region',\n postalCode: 'postalCode',\n country: 'country',\n isPrimary: 'isPrimary',\n}\n\nfunction normalizeOptional(value: string): string | undefined {\n const trimmed = value.trim()\n return trimmed.length ? trimmed : undefined\n}\n\nfunction extractValidationDetails(error: unknown): AddressValidationDetail[] {\n if (!error || typeof error !== 'object') return []\n const candidate = (error as { details?: unknown }).details\n if (!Array.isArray(candidate)) return []\n return candidate\n .map((entry) => (entry && typeof entry === 'object' ? (entry as AddressValidationDetail) : null))\n .filter((entry): entry is AddressValidationDetail => entry !== null)\n}\n\nfunction resolveFieldMessage(detail: AddressValidationDetail, fieldLabel: string, t: Translator): string {\n switch (detail.code) {\n case 'invalid_type':\n return t('customers.people.detail.addresses.validation.invalid', undefined, { field: fieldLabel })\n case 'too_small':\n if (detail.minimum === 1 && detail.type === 'string') {\n return t('customers.people.detail.addresses.validation.required', undefined, { field: fieldLabel })\n }\n return t('customers.people.detail.addresses.validation.generic', undefined, { field: fieldLabel })\n case 'too_big':\n if (typeof detail.maximum === 'number') {\n return t(\n 'customers.people.detail.addresses.validation.tooLong',\n undefined,\n {\n field: fieldLabel,\n max: detail.maximum,\n }\n )\n }\n return t('customers.people.detail.addresses.validation.generic', undefined, { field: fieldLabel })\n default:\n return t('customers.people.detail.addresses.validation.generic', undefined, { field: fieldLabel })\n }\n}\n\nexport function CustomerAddressTiles({\n addresses,\n onCreate,\n onUpdate,\n onDelete,\n t,\n emptyLabel,\n isSubmitting = false,\n gridClassName = 'grid gap-4 min-[480px]:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4',\n hideAddButton = false,\n onAddActionChange,\n emptyStateTitle,\n emptyStateActionLabel,\n}: CustomerAddressTilesProps) {\n const scopeVersion = useOrganizationScopeVersion()\n const queryClient = useQueryClient()\n const [isFormOpen, setIsFormOpen] = React.useState(false)\n const [editingId, setEditingId] = React.useState<string | null>(null)\n const [draft, setDraft] = React.useState<DraftAddressState>(defaultDraft)\n const [saving, setSaving] = React.useState(false)\n const [deletingId, setDeletingId] = React.useState<string | null>(null)\n const [generalError, setGeneralError] = React.useState<string | null>(null)\n const [fieldErrors, setFieldErrors] = React.useState<Partial<Record<DraftFieldKey, string>>>({})\n const [format, setFormat] = React.useState<AddressFormatStrategy>('line_first')\n const [formatLoading, setFormatLoading] = React.useState(false)\n const { map: addressTypeMap } = useAddressTypes(t)\n\n const fieldLabels = React.useMemo(\n () => ({\n name: t('customers.people.detail.addresses.fields.label'),\n purpose: t('customers.people.detail.addresses.fields.type'),\n companyName: t('customers.people.detail.addresses.fields.companyName', 'Company name'),\n addressLine1: t('customers.people.detail.addresses.fields.line1'),\n addressLine2: t('customers.people.detail.addresses.fields.line2'),\n street: t('customers.people.detail.addresses.fields.street', 'Street'),\n buildingNumber: t('customers.people.detail.addresses.fields.buildingNumber', 'Building number'),\n flatNumber: t('customers.people.detail.addresses.fields.flatNumber', 'Flat number'),\n city: t('customers.people.detail.addresses.fields.city'),\n region: t('customers.people.detail.addresses.fields.region'),\n postalCode: t('customers.people.detail.addresses.fields.postalCode'),\n country: t('customers.people.detail.addresses.fields.country'),\n isPrimary: t('customers.people.detail.addresses.fields.primary'),\n }),\n [t]\n )\n const line1FieldLabel = React.useMemo(\n () => (format === 'street_first' ? fieldLabels.street : fieldLabels.addressLine1),\n [fieldLabels.addressLine1, fieldLabels.street, format],\n )\n\n\n\n const resetForm = React.useCallback(() => {\n setDraft(defaultDraft)\n setFieldErrors({})\n setGeneralError(null)\n setEditingId(null)\n }, [])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadFormat() {\n setFormatLoading(true)\n try {\n const call = await apiCall<{ addressFormat?: string; error?: string }>(\n '/api/customers/settings/address-format',\n )\n const payload = (call.result ?? {}) as Record<string, unknown>\n if (!call.ok) {\n if (!cancelled) {\n const message =\n typeof (payload as Record<string, unknown>)?.error === 'string'\n ? (payload as Record<string, unknown>).error as string\n : t('customers.people.detail.addresses.formatLoadError', 'Failed to load address configuration')\n flash(message, 'error')\n }\n return\n }\n const valueRaw = payload?.addressFormat\n const value = typeof valueRaw === 'string' ? valueRaw : null\n if (!cancelled && (value === 'street_first' || value === 'line_first')) {\n setFormat(value)\n }\n } catch (err) {\n if (!cancelled) {\n const message =\n err instanceof Error && err.message\n ? err.message\n : t('customers.people.detail.addresses.formatLoadError', 'Failed to load address configuration')\n flash(message, 'error')\n }\n } finally {\n if (!cancelled) setFormatLoading(false)\n }\n }\n loadFormat().catch(() => {})\n return () => {\n cancelled = true\n }\n }, [scopeVersion, t])\n\n\n const openCreateForm = React.useCallback(() => {\n resetForm()\n setIsFormOpen(true)\n }, [resetForm])\n\n const openEditForm = React.useCallback(\n (address: CustomerAddressValue) => {\n setDraft({\n name: address.name ?? '',\n purpose: address.purpose ?? '',\n companyName: address.companyName ?? '',\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2 ?? '',\n buildingNumber: address.buildingNumber ?? '',\n flatNumber: address.flatNumber ?? '',\n city: address.city ?? '',\n region: address.region ?? '',\n postalCode: address.postalCode ?? '',\n country: address.country ? address.country.toUpperCase() : '',\n isPrimary: address.isPrimary ?? false,\n })\n setFieldErrors({})\n setGeneralError(null)\n setEditingId(address.id)\n setIsFormOpen(true)\n },\n []\n )\n\n const handleCancel = React.useCallback(() => {\n setIsFormOpen(false)\n resetForm()\n }, [resetForm])\n\n const handleSave = React.useCallback(async () => {\n const trimmedLine1 = draft.addressLine1.trim()\n if (!trimmedLine1.length) {\n const message = t(\n 'customers.people.detail.addresses.validation.required',\n undefined,\n { field: line1FieldLabel }\n )\n setFieldErrors((prev) => ({ ...prev, addressLine1: message }))\n setGeneralError(message)\n return\n }\n\n const payload: CustomerAddressInput = {\n addressLine1: trimmedLine1,\n isPrimary: draft.isPrimary,\n }\n\n const purpose = normalizeOptional(draft.purpose)\n if (purpose !== undefined) payload.purpose = purpose\n const name = normalizeOptional(draft.name)\n if (name !== undefined) payload.name = name\n const companyName = normalizeOptional(draft.companyName)\n if (companyName !== undefined) payload.companyName = companyName\n const line2 = normalizeOptional(draft.addressLine2)\n if (line2 !== undefined) payload.addressLine2 = line2\n const buildingNumber = normalizeOptional(draft.buildingNumber)\n if (buildingNumber !== undefined) payload.buildingNumber = buildingNumber\n const flatNumber = normalizeOptional(draft.flatNumber)\n if (flatNumber !== undefined) payload.flatNumber = flatNumber\n const city = normalizeOptional(draft.city)\n if (city !== undefined) payload.city = city\n const region = normalizeOptional(draft.region)\n if (region !== undefined) payload.region = region\n const postal = normalizeOptional(draft.postalCode)\n if (postal !== undefined) payload.postalCode = postal\n const country = normalizeOptional(draft.country)\n if (country !== undefined) payload.country = country.toUpperCase()\n\n setSaving(true)\n setGeneralError(null)\n setFieldErrors({})\n try {\n if (editingId && onUpdate) await onUpdate(editingId, payload)\n else await onCreate(payload)\n resetForm()\n setIsFormOpen(false)\n } catch (err) {\n const details = extractValidationDetails(err)\n if (details.length) {\n const nextErrors: Partial<Record<DraftFieldKey, string>> = {}\n for (const detail of details) {\n const path = Array.isArray(detail.path) ? detail.path : []\n const targetKey = path.length ? serverFieldMap[String(path[0])] : undefined\n if (!targetKey) continue\n const message = resolveFieldMessage(\n detail,\n targetKey === 'addressLine1' ? line1FieldLabel : fieldLabels[targetKey],\n t,\n )\n if (message) nextErrors[targetKey] = message\n }\n if (Object.keys(nextErrors).length) {\n setFieldErrors(nextErrors)\n setGeneralError(Object.values(nextErrors)[0] ?? null)\n setSaving(false)\n return\n }\n }\n const message =\n err instanceof Error && err.message\n ? err.message\n : t('customers.people.detail.addresses.error')\n setGeneralError(message)\n flash(message, 'error')\n } finally {\n setSaving(false)\n }\n }, [draft, editingId, fieldLabels, line1FieldLabel, onCreate, onUpdate, resetForm, t])\n\n const handleDelete = React.useCallback(\n async (id: string) => {\n if (!onDelete) return\n setDeletingId(id)\n try {\n await onDelete(id)\n if (editingId === id) {\n resetForm()\n setIsFormOpen(false)\n }\n } catch (err) {\n const message =\n err instanceof Error && err.message\n ? err.message\n : t('customers.people.detail.addresses.error')\n flash(message, 'error')\n } finally {\n setDeletingId(null)\n }\n },\n [editingId, onDelete, resetForm, t]\n )\n\n const disableActions = saving || isSubmitting || deletingId !== null\n const isEditing = editingId !== null\n const addDisabled = disableActions || isEditing\n const hasAddresses = addresses.length > 0\n const emptyTitle = emptyStateTitle ?? emptyLabel\n const emptyActionLabel = emptyStateActionLabel ?? t('customers.people.detail.addresses.add')\n\n React.useEffect(() => {\n if (!onAddActionChange) return\n onAddActionChange({ openCreateForm, addDisabled })\n }, [onAddActionChange, openCreateForm, addDisabled])\n\n React.useEffect(\n () => () => {\n if (onAddActionChange) onAddActionChange(null)\n },\n [onAddActionChange]\n )\n\n const renderFormTile = React.useCallback(\n (key: string) => (\n <div\n key={key}\n className=\"rounded-lg border-2 border-dashed border-muted-foreground/50 bg-muted/30 p-4 text-sm\"\n onKeyDown={(event) => {\n if (!(event.metaKey || event.ctrlKey)) return\n if (event.key !== 'Enter') return\n event.preventDefault()\n if (disableActions) return\n void handleSave()\n }}\n >\n <div className=\"flex items-center justify-between text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n <span>\n {editingId\n ? t('customers.people.detail.addresses.editTitle')\n : t('customers.people.detail.addresses.addTitle')}\n </span>\n <Button type=\"button\" variant=\"ghost\" size=\"icon\" onClick={handleCancel} disabled={disableActions}>\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n <div className=\"mt-3 space-y-3\">\n {formatLoading ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('customers.people.detail.addresses.formatLoading', 'Loading address preferences\u2026')}\n </p>\n ) : null}\n <AddressEditor\n value={draft}\n onChange={(next) => {\n setDraft(next)\n if (Object.keys(fieldErrors).length) {\n const nextErrors = { ...fieldErrors }\n ;(Object.keys(nextErrors) as DraftFieldKey[]).forEach((key) => {\n const candidate = (next as Record<string, unknown>)[key]\n if (candidate !== undefined && candidate !== null && `${candidate}`.length) {\n delete nextErrors[key]\n }\n })\n setFieldErrors(nextErrors)\n }\n }}\n format={format}\n t={t}\n disabled={disableActions}\n errors={fieldErrors}\n showFormatHint={!formatLoading}\n />\n {generalError ? <p className=\"text-xs text-status-error-text\">{generalError}</p> : null}\n <div className=\"flex flex-wrap justify-end gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={handleCancel} disabled={disableActions}>\n {t('customers.people.detail.addresses.cancel')}\n </Button>\n <Button type=\"button\" onClick={handleSave} disabled={disableActions}>\n {saving ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n {editingId\n ? t('customers.people.detail.addresses.updating')\n : t('customers.people.detail.addresses.saving')}\n </>\n ) : editingId ? (\n t('customers.people.detail.addresses.update')\n ) : (\n t('customers.people.detail.addresses.save')\n )}\n </Button>\n </div>\n </div>\n </div>\n ),\n [\n disableActions,\n draft,\n editingId,\n fieldErrors,\n format,\n formatLoading,\n handleCancel,\n handleSave,\n generalError,\n saving,\n t,\n ]\n )\n\n return (\n <div className=\"space-y-4\">\n {!hideAddButton && hasAddresses ? (\n <div className=\"flex justify-end\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={openCreateForm}\n disabled={addDisabled}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {t('customers.people.detail.addresses.add')}\n </Button>\n </div>\n ) : null}\n {hasAddresses ? (\n <div className={gridClassName}>\n {addresses.map((address) => {\n if (isFormOpen && editingId === address.id) {\n return renderFormTile(address.id)\n }\n const formattedJson = formatAddressJson(address, format)\n const formattedString = formatAddressString(address, format)\n\n return (\n <div\n key={address.id}\n className=\"rounded-lg border bg-background p-4 text-sm shadow-sm\"\n title={formattedString}\n data-address-json={JSON.stringify(formattedJson)}\n data-address-string={formattedString}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div>\n <span className=\"text-xs uppercase tracking-wide text-muted-foreground\">\n {address.name ||\n (address.purpose ? addressTypeMap.get(address.purpose) ?? address.purpose : null) ||\n t('customers.people.detail.address')}\n </span>\n {address.isPrimary ? (\n <span className=\"mt-1 inline-flex w-fit rounded bg-status-success-bg px-2 py-0.5 text-overline font-semibold text-status-success-text\">\n {t('customers.people.detail.primary')}\n </span>\n ) : null}\n </div>\n <div className=\"flex items-center gap-1\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8\"\n onClick={() => openEditForm(address)}\n disabled={disableActions}\n aria-label={t('customers.people.detail.addresses.editAction')}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 text-destructive hover:text-destructive focus-visible:text-destructive\"\n onClick={() => handleDelete(address.id)}\n disabled={disableActions || !onDelete}\n aria-label={t('customers.people.detail.addresses.deleteAction')}\n >\n {deletingId === address.id ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Trash2 className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </div>\n <div className=\"mt-2 space-y-1\">\n {address.purpose ? (\n <p className=\"text-xs text-muted-foreground\">\n {addressTypeMap.get(address.purpose) ?? address.purpose}\n </p>\n ) : null}\n <AddressView address={address} format={format} className=\"space-y-1\" lineClassName=\"text-sm\" />\n </div>\n </div>\n )\n })}\n {isFormOpen && !editingId ? renderFormTile('__new') : null}\n </div>\n ) : isFormOpen && !editingId ? (\n <div className={gridClassName}>{renderFormTile('__new')}</div>\n ) : (\n <TabEmptyState\n title={emptyTitle}\n action={{\n label: emptyActionLabel,\n onClick: openCreateForm,\n disabled: addDisabled,\n }}\n />\n )}\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Loader2, Pencil, Plus, Trash2, X } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { TabEmptyState } from '@open-mercato/ui/backend/detail'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { AddressView, formatAddressJson, formatAddressString, type AddressFormatStrategy } from '../utils/addressFormat'\nimport { normalizeCoordinateInput, validateCoordinateInput } from '@open-mercato/shared/lib/location/coordinates'\nimport AddressEditor from './AddressEditor'\nimport { useAddressTypes } from './detail/hooks/useAddressTypes'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from '@open-mercato/ui/primitives/dialog'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { ensureCustomerDictionary, invalidateCustomerDictionary } from './detail/hooks/useCustomerDictionary'\n\nexport type Translator = (\n key: string,\n fallback?: string,\n params?: Record<string, string | number>,\n) => string\n\nexport type CustomerAddressInput = {\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?: number | null\n longitude?: number | null\n isPrimary?: boolean\n}\n\nexport type CustomerAddressValue = CustomerAddressInput & {\n id: string\n purpose?: string | null\n companyName?: string | null\n latitude?: number | null\n longitude?: number | null\n}\n\ntype CustomerAddressTilesProps = {\n addresses: CustomerAddressValue[]\n onCreate: (payload: CustomerAddressInput) => Promise<void> | void\n onUpdate?: (id: string, payload: CustomerAddressInput) => Promise<void> | void\n onDelete?: (id: string) => Promise<void> | void\n t: Translator\n emptyLabel: string\n isSubmitting?: boolean\n gridClassName?: string\n hideAddButton?: boolean\n onAddActionChange?: (action: { openCreateForm: () => void; addDisabled: boolean } | null) => void\n emptyStateTitle?: string\n emptyStateActionLabel?: string\n showCoordinateFields?: boolean\n}\n\ntype DraftAddressState = {\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\ntype DraftFieldKey = keyof DraftAddressState\n\ntype AddressValidationDetail = {\n path?: Array<string | number>\n code?: string\n message?: string\n minimum?: number\n maximum?: number\n type?: string\n}\n\nconst defaultDraft: DraftAddressState = {\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: false,\n}\n\nconst serverFieldMap: Record<string, DraftFieldKey> = {\n name: 'name',\n purpose: 'purpose',\n companyName: 'companyName',\n addressLine1: 'addressLine1',\n addressLine2: 'addressLine2',\n buildingNumber: 'buildingNumber',\n flatNumber: 'flatNumber',\n city: 'city',\n region: 'region',\n postalCode: 'postalCode',\n country: 'country',\n latitude: 'latitude',\n longitude: 'longitude',\n isPrimary: 'isPrimary',\n}\n\nfunction normalizeOptional(value: string): string | undefined {\n const trimmed = value.trim()\n return trimmed.length ? trimmed : undefined\n}\n\nfunction extractValidationDetails(error: unknown): AddressValidationDetail[] {\n if (!error || typeof error !== 'object') return []\n const candidate = (error as { details?: unknown }).details\n if (!Array.isArray(candidate)) return []\n return candidate\n .map((entry) => (entry && typeof entry === 'object' ? (entry as AddressValidationDetail) : null))\n .filter((entry): entry is AddressValidationDetail => entry !== null)\n}\n\nfunction resolveFieldMessage(detail: AddressValidationDetail, fieldLabel: string, t: Translator): string {\n switch (detail.code) {\n case 'invalid_type':\n return t('customers.people.detail.addresses.validation.invalid', undefined, { field: fieldLabel })\n case 'too_small':\n if (detail.minimum === 1 && detail.type === 'string') {\n return t('customers.people.detail.addresses.validation.required', undefined, { field: fieldLabel })\n }\n return t('customers.people.detail.addresses.validation.generic', undefined, { field: fieldLabel })\n case 'too_big':\n if (typeof detail.maximum === 'number') {\n return t(\n 'customers.people.detail.addresses.validation.tooLong',\n undefined,\n {\n field: fieldLabel,\n max: detail.maximum,\n }\n )\n }\n return t('customers.people.detail.addresses.validation.generic', undefined, { field: fieldLabel })\n default:\n return t('customers.people.detail.addresses.validation.generic', undefined, { field: fieldLabel })\n }\n}\n\nexport function CustomerAddressTiles({\n addresses,\n onCreate,\n onUpdate,\n onDelete,\n t,\n emptyLabel,\n isSubmitting = false,\n gridClassName = 'grid gap-4 min-[480px]:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4',\n hideAddButton = false,\n onAddActionChange,\n emptyStateTitle,\n emptyStateActionLabel,\n showCoordinateFields = false,\n}: CustomerAddressTilesProps) {\n const scopeVersion = useOrganizationScopeVersion()\n const queryClient = useQueryClient()\n const [isFormOpen, setIsFormOpen] = React.useState(false)\n const [editingId, setEditingId] = React.useState<string | null>(null)\n const [draft, setDraft] = React.useState<DraftAddressState>(defaultDraft)\n const [saving, setSaving] = React.useState(false)\n const [deletingId, setDeletingId] = React.useState<string | null>(null)\n const [generalError, setGeneralError] = React.useState<string | null>(null)\n const [fieldErrors, setFieldErrors] = React.useState<Partial<Record<DraftFieldKey, string>>>({})\n const [format, setFormat] = React.useState<AddressFormatStrategy>('line_first')\n const [formatLoading, setFormatLoading] = React.useState(false)\n const { map: addressTypeMap } = useAddressTypes(t)\n\n const fieldLabels = React.useMemo(\n () => ({\n name: t('customers.people.detail.addresses.fields.label'),\n purpose: t('customers.people.detail.addresses.fields.type'),\n companyName: t('customers.people.detail.addresses.fields.companyName', 'Company name'),\n addressLine1: t('customers.people.detail.addresses.fields.line1'),\n addressLine2: t('customers.people.detail.addresses.fields.line2'),\n street: t('customers.people.detail.addresses.fields.street', 'Street'),\n buildingNumber: t('customers.people.detail.addresses.fields.buildingNumber', 'Building number'),\n flatNumber: t('customers.people.detail.addresses.fields.flatNumber', 'Flat number'),\n city: t('customers.people.detail.addresses.fields.city'),\n region: t('customers.people.detail.addresses.fields.region'),\n postalCode: t('customers.people.detail.addresses.fields.postalCode'),\n country: t('customers.people.detail.addresses.fields.country'),\n latitude: t('customers.people.detail.addresses.fields.latitude', 'Latitude'),\n longitude: t('customers.people.detail.addresses.fields.longitude', 'Longitude'),\n isPrimary: t('customers.people.detail.addresses.fields.primary'),\n }),\n [t]\n )\n const line1FieldLabel = React.useMemo(\n () => (format === 'street_first' ? fieldLabels.street : fieldLabels.addressLine1),\n [fieldLabels.addressLine1, fieldLabels.street, format],\n )\n\n\n\n const resetForm = React.useCallback(() => {\n setDraft(defaultDraft)\n setFieldErrors({})\n setGeneralError(null)\n setEditingId(null)\n }, [])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadFormat() {\n setFormatLoading(true)\n try {\n const call = await apiCall<{ addressFormat?: string; error?: string }>(\n '/api/customers/settings/address-format',\n )\n const payload = (call.result ?? {}) as Record<string, unknown>\n if (!call.ok) {\n if (!cancelled) {\n const message =\n typeof (payload as Record<string, unknown>)?.error === 'string'\n ? (payload as Record<string, unknown>).error as string\n : t('customers.people.detail.addresses.formatLoadError', 'Failed to load address configuration')\n flash(message, 'error')\n }\n return\n }\n const valueRaw = payload?.addressFormat\n const value = typeof valueRaw === 'string' ? valueRaw : null\n if (!cancelled && (value === 'street_first' || value === 'line_first')) {\n setFormat(value)\n }\n } catch (err) {\n if (!cancelled) {\n const message =\n err instanceof Error && err.message\n ? err.message\n : t('customers.people.detail.addresses.formatLoadError', 'Failed to load address configuration')\n flash(message, 'error')\n }\n } finally {\n if (!cancelled) setFormatLoading(false)\n }\n }\n loadFormat().catch(() => {})\n return () => {\n cancelled = true\n }\n }, [scopeVersion, t])\n\n\n const openCreateForm = React.useCallback(() => {\n resetForm()\n setIsFormOpen(true)\n }, [resetForm])\n\n const openEditForm = React.useCallback(\n (address: CustomerAddressValue) => {\n setDraft({\n name: address.name ?? '',\n purpose: address.purpose ?? '',\n companyName: address.companyName ?? '',\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2 ?? '',\n buildingNumber: address.buildingNumber ?? '',\n flatNumber: address.flatNumber ?? '',\n city: address.city ?? '',\n region: address.region ?? '',\n postalCode: address.postalCode ?? '',\n country: address.country ? address.country.toUpperCase() : '',\n latitude: address.latitude != null ? String(address.latitude) : '',\n longitude: address.longitude != null ? String(address.longitude) : '',\n isPrimary: address.isPrimary ?? false,\n })\n setFieldErrors({})\n setGeneralError(null)\n setEditingId(address.id)\n setIsFormOpen(true)\n },\n []\n )\n\n const handleCancel = React.useCallback(() => {\n setIsFormOpen(false)\n resetForm()\n }, [resetForm])\n\n const handleSave = React.useCallback(async () => {\n const trimmedLine1 = draft.addressLine1.trim()\n if (!trimmedLine1.length) {\n const message = t(\n 'customers.people.detail.addresses.validation.required',\n undefined,\n { field: line1FieldLabel }\n )\n setFieldErrors((prev) => ({ ...prev, addressLine1: message }))\n setGeneralError(message)\n return\n }\n\n const coordinateErrors: Partial<Record<DraftFieldKey, string>> = {}\n for (const key of ['latitude', 'longitude'] as const) {\n const result = validateCoordinateInput(key, draft[key])\n if (result.status === 'invalid') {\n coordinateErrors[key] = t(\n 'customers.people.detail.addresses.validation.invalid',\n undefined,\n { field: fieldLabels[key] }\n )\n } else if (result.status === 'outOfRange') {\n coordinateErrors[key] = t(\n 'customers.people.detail.addresses.validation.coordinateRange',\n undefined,\n { field: fieldLabels[key], min: result.min, max: result.max }\n )\n }\n }\n if (Object.keys(coordinateErrors).length) {\n setFieldErrors((prev) => ({ ...prev, ...coordinateErrors }))\n setGeneralError(Object.values(coordinateErrors)[0] ?? null)\n return\n }\n\n const payload: CustomerAddressInput = {\n addressLine1: trimmedLine1,\n isPrimary: draft.isPrimary,\n }\n\n const purpose = normalizeOptional(draft.purpose)\n if (purpose !== undefined) payload.purpose = purpose\n const name = normalizeOptional(draft.name)\n if (name !== undefined) payload.name = name\n const companyName = normalizeOptional(draft.companyName)\n if (companyName !== undefined) payload.companyName = companyName\n const line2 = normalizeOptional(draft.addressLine2)\n if (line2 !== undefined) payload.addressLine2 = line2\n const buildingNumber = normalizeOptional(draft.buildingNumber)\n if (buildingNumber !== undefined) payload.buildingNumber = buildingNumber\n const flatNumber = normalizeOptional(draft.flatNumber)\n if (flatNumber !== undefined) payload.flatNumber = flatNumber\n const city = normalizeOptional(draft.city)\n if (city !== undefined) payload.city = city\n const region = normalizeOptional(draft.region)\n if (region !== undefined) payload.region = region\n const postal = normalizeOptional(draft.postalCode)\n if (postal !== undefined) payload.postalCode = postal\n const country = normalizeOptional(draft.country)\n if (country !== undefined) payload.country = country.toUpperCase()\n // On edit, an emptied coordinate must be sent as `null` to clear the stored value; omitting it\n // makes the partial-update handler keep the old coordinate. On create there is nothing to clear.\n const latitude = normalizeCoordinateInput(draft.latitude)\n if (latitude !== undefined) payload.latitude = latitude\n else if (editingId) payload.latitude = null\n const longitude = normalizeCoordinateInput(draft.longitude)\n if (longitude !== undefined) payload.longitude = longitude\n else if (editingId) payload.longitude = null\n\n setSaving(true)\n setGeneralError(null)\n setFieldErrors({})\n try {\n if (editingId && onUpdate) await onUpdate(editingId, payload)\n else await onCreate(payload)\n resetForm()\n setIsFormOpen(false)\n } catch (err) {\n const details = extractValidationDetails(err)\n if (details.length) {\n const nextErrors: Partial<Record<DraftFieldKey, string>> = {}\n for (const detail of details) {\n const path = Array.isArray(detail.path) ? detail.path : []\n const targetKey = path.length ? serverFieldMap[String(path[0])] : undefined\n if (!targetKey) continue\n const message = resolveFieldMessage(\n detail,\n targetKey === 'addressLine1' ? line1FieldLabel : fieldLabels[targetKey],\n t,\n )\n if (message) nextErrors[targetKey] = message\n }\n if (Object.keys(nextErrors).length) {\n setFieldErrors(nextErrors)\n setGeneralError(Object.values(nextErrors)[0] ?? null)\n setSaving(false)\n return\n }\n }\n const message =\n err instanceof Error && err.message\n ? err.message\n : t('customers.people.detail.addresses.error')\n setGeneralError(message)\n flash(message, 'error')\n } finally {\n setSaving(false)\n }\n }, [draft, editingId, fieldLabels, line1FieldLabel, onCreate, onUpdate, resetForm, t])\n\n const handleDelete = React.useCallback(\n async (id: string) => {\n if (!onDelete) return\n setDeletingId(id)\n try {\n await onDelete(id)\n if (editingId === id) {\n resetForm()\n setIsFormOpen(false)\n }\n } catch (err) {\n const message =\n err instanceof Error && err.message\n ? err.message\n : t('customers.people.detail.addresses.error')\n flash(message, 'error')\n } finally {\n setDeletingId(null)\n }\n },\n [editingId, onDelete, resetForm, t]\n )\n\n const disableActions = saving || isSubmitting || deletingId !== null\n const isEditing = editingId !== null\n const addDisabled = disableActions || isEditing\n const hasAddresses = addresses.length > 0\n const emptyTitle = emptyStateTitle ?? emptyLabel\n const emptyActionLabel = emptyStateActionLabel ?? t('customers.people.detail.addresses.add')\n\n React.useEffect(() => {\n if (!onAddActionChange) return\n onAddActionChange({ openCreateForm, addDisabled })\n }, [onAddActionChange, openCreateForm, addDisabled])\n\n React.useEffect(\n () => () => {\n if (onAddActionChange) onAddActionChange(null)\n },\n [onAddActionChange]\n )\n\n const renderFormTile = React.useCallback(\n (key: string) => (\n <div\n key={key}\n className=\"rounded-lg border-2 border-dashed border-muted-foreground/50 bg-muted/30 p-4 text-sm\"\n onKeyDown={(event) => {\n if (!(event.metaKey || event.ctrlKey)) return\n if (event.key !== 'Enter') return\n event.preventDefault()\n if (disableActions) return\n void handleSave()\n }}\n >\n <div className=\"flex items-center justify-between text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n <span>\n {editingId\n ? t('customers.people.detail.addresses.editTitle')\n : t('customers.people.detail.addresses.addTitle')}\n </span>\n <Button type=\"button\" variant=\"ghost\" size=\"icon\" onClick={handleCancel} disabled={disableActions}>\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n <div className=\"mt-3 space-y-3\">\n {formatLoading ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('customers.people.detail.addresses.formatLoading', 'Loading address preferences\u2026')}\n </p>\n ) : null}\n <AddressEditor\n value={draft}\n onChange={(next) => {\n setDraft({ ...next, latitude: next.latitude ?? '', longitude: next.longitude ?? '' })\n if (Object.keys(fieldErrors).length) {\n const nextErrors = { ...fieldErrors }\n ;(Object.keys(nextErrors) as DraftFieldKey[]).forEach((key) => {\n const candidate = (next as Record<string, unknown>)[key]\n if (candidate !== undefined && candidate !== null && `${candidate}`.length) {\n delete nextErrors[key]\n }\n })\n setFieldErrors(nextErrors)\n }\n }}\n format={format}\n t={t}\n disabled={disableActions}\n errors={fieldErrors}\n showFormatHint={!formatLoading}\n showCoordinateFields={showCoordinateFields}\n />\n {generalError ? <p className=\"text-xs text-status-error-text\">{generalError}</p> : null}\n <div className=\"flex flex-wrap justify-end gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={handleCancel} disabled={disableActions}>\n {t('customers.people.detail.addresses.cancel')}\n </Button>\n <Button type=\"button\" onClick={handleSave} disabled={disableActions}>\n {saving ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n {editingId\n ? t('customers.people.detail.addresses.updating')\n : t('customers.people.detail.addresses.saving')}\n </>\n ) : editingId ? (\n t('customers.people.detail.addresses.update')\n ) : (\n t('customers.people.detail.addresses.save')\n )}\n </Button>\n </div>\n </div>\n </div>\n ),\n [\n disableActions,\n draft,\n editingId,\n fieldErrors,\n format,\n formatLoading,\n handleCancel,\n handleSave,\n generalError,\n saving,\n showCoordinateFields,\n t,\n ]\n )\n\n return (\n <div className=\"space-y-4\">\n {!hideAddButton && hasAddresses ? (\n <div className=\"flex justify-end\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={openCreateForm}\n disabled={addDisabled}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {t('customers.people.detail.addresses.add')}\n </Button>\n </div>\n ) : null}\n {hasAddresses ? (\n <div className={gridClassName}>\n {addresses.map((address) => {\n if (isFormOpen && editingId === address.id) {\n return renderFormTile(address.id)\n }\n const formattedJson = formatAddressJson(address, format)\n const formattedString = formatAddressString(address, format)\n\n return (\n <div\n key={address.id}\n className=\"rounded-lg border bg-background p-4 text-sm shadow-sm\"\n title={formattedString}\n data-address-json={JSON.stringify(formattedJson)}\n data-address-string={formattedString}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div>\n <span className=\"text-xs uppercase tracking-wide text-muted-foreground\">\n {address.name ||\n (address.purpose ? addressTypeMap.get(address.purpose) ?? address.purpose : null) ||\n t('customers.people.detail.address')}\n </span>\n {address.isPrimary ? (\n <span className=\"mt-1 inline-flex w-fit rounded bg-status-success-bg px-2 py-0.5 text-overline font-semibold text-status-success-text\">\n {t('customers.people.detail.primary')}\n </span>\n ) : null}\n </div>\n <div className=\"flex items-center gap-1\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8\"\n onClick={() => openEditForm(address)}\n disabled={disableActions}\n aria-label={t('customers.people.detail.addresses.editAction')}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 text-destructive hover:text-destructive focus-visible:text-destructive\"\n onClick={() => handleDelete(address.id)}\n disabled={disableActions || !onDelete}\n aria-label={t('customers.people.detail.addresses.deleteAction')}\n >\n {deletingId === address.id ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Trash2 className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </div>\n <div className=\"mt-2 space-y-1\">\n {address.purpose ? (\n <p className=\"text-xs text-muted-foreground\">\n {addressTypeMap.get(address.purpose) ?? address.purpose}\n </p>\n ) : null}\n <AddressView address={address} format={format} className=\"space-y-1\" lineClassName=\"text-sm\" />\n </div>\n </div>\n )\n })}\n {isFormOpen && !editingId ? renderFormTile('__new') : null}\n </div>\n ) : isFormOpen && !editingId ? (\n <div className={gridClassName}>{renderFormTile('__new')}</div>\n ) : (\n <TabEmptyState\n title={emptyTitle}\n action={{\n label: emptyActionLabel,\n onClick: openCreateForm,\n disabled: addDisabled,\n }}\n />\n )}\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["message", "key"]
7
7
  }
@@ -50,6 +50,8 @@ function AddressesSection({
50
50
  region: typeof record.region === "string" ? record.region : null,
51
51
  postalCode: typeof record.postal_code === "string" ? record.postal_code : typeof record.postalCode === "string" ? record.postalCode : null,
52
52
  country: typeof record.country === "string" ? record.country : null,
53
+ latitude: typeof record.latitude === "number" && Number.isFinite(record.latitude) ? record.latitude : null,
54
+ longitude: typeof record.longitude === "number" && Number.isFinite(record.longitude) ? record.longitude : null,
53
55
  isPrimary: typeof record.is_primary === "boolean" ? record.is_primary : typeof record.isPrimary === "boolean" ? record.isPrimary : false,
54
56
  updatedAt: typeof record.updated_at === "string" ? record.updated_at : typeof record.updatedAt === "string" ? record.updatedAt : null
55
57
  };
@@ -178,7 +180,8 @@ function AddressesSection({
178
180
  translator: t,
179
181
  dataAdapter,
180
182
  addressTypesAdapter,
181
- loadFormat
183
+ loadFormat,
184
+ showCoordinateFields: true
182
185
  }
183
186
  );
184
187
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/components/detail/AddressesSection.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { apiCall, apiCallOrThrow, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { AddressesSection as SharedAddressesSection } from '@open-mercato/ui/backend/detail'\nimport type { AddressDataAdapter, AddressTypesAdapter, AddressFormatStrategy, SectionAction } from '@open-mercato/ui/backend/detail'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nexport type AddressesSectionProps = {\n entityId: string | null\n emptyLabel: string\n addActionLabel: string\n emptyState: { title: string; actionLabel: string; description?: string }\n onActionChange?: (action: SectionAction | null) => void\n translator?: (key: string, fallback?: string, params?: Record<string, string | number>) => string\n onLoadingChange?: (isLoading: boolean) => void\n}\n\ntype ApiAddressPayload = Record<string, unknown>\n\nexport function AddressesSection({\n entityId,\n emptyLabel,\n addActionLabel,\n emptyState,\n onActionChange,\n translator,\n onLoadingChange,\n}: AddressesSectionProps) {\n const tHook = useT()\n const fallbackTranslator = React.useMemo(() => createTranslatorWithFallback(tHook), [tHook])\n const t = translator ?? fallbackTranslator\n\n const dataAdapter = React.useMemo<AddressDataAdapter>(() => ({\n list: async ({ entityId: listEntityId }) => {\n if (!listEntityId) return []\n const params = new URLSearchParams({ entityId: listEntityId, pageSize: '100' })\n const payload = await readApiResultOrThrow<ApiAddressPayload>(\n `/api/customers/addresses?${params.toString()}`,\n undefined,\n { errorMessage: t('customers.people.detail.addresses.error') },\n )\n const items = Array.isArray(payload?.items) ? payload.items : []\n return items\n .map((item) => {\n if (!item || typeof item !== 'object') return null\n const record = item as Record<string, unknown>\n const rawId = record.id ?? record.address_id ?? null\n const id =\n typeof rawId === 'string'\n ? rawId\n : typeof rawId === 'number' || typeof rawId === 'bigint'\n ? String(rawId)\n : null\n if (!id) return null\n const addressLine1 = typeof record.address_line1 === 'string'\n ? record.address_line1\n : typeof record.addressLine1 === 'string'\n ? record.addressLine1\n : null\n if (!addressLine1) return null\n return {\n id,\n name: typeof record.name === 'string' ? record.name : null,\n purpose: typeof record.purpose === 'string' ? record.purpose : null,\n companyName: typeof record.company_name === 'string'\n ? record.company_name\n : typeof record.companyName === 'string'\n ? record.companyName\n : null,\n addressLine1,\n addressLine2: typeof record.address_line2 === 'string'\n ? record.address_line2\n : typeof record.addressLine2 === 'string'\n ? record.addressLine2\n : null,\n buildingNumber: typeof record.building_number === 'string'\n ? record.building_number\n : typeof record.buildingNumber === 'string'\n ? record.buildingNumber\n : null,\n flatNumber: typeof record.flat_number === 'string'\n ? record.flat_number\n : typeof record.flatNumber === 'string'\n ? record.flatNumber\n : null,\n city: typeof record.city === 'string' ? record.city : null,\n region: typeof record.region === 'string' ? record.region : null,\n postalCode: typeof record.postal_code === 'string'\n ? record.postal_code\n : typeof record.postalCode === 'string'\n ? record.postalCode\n : null,\n country: typeof record.country === 'string' ? record.country : null,\n isPrimary:\n typeof record.is_primary === 'boolean'\n ? record.is_primary\n : typeof record.isPrimary === 'boolean'\n ? record.isPrimary\n : false,\n updatedAt:\n typeof record.updated_at === 'string'\n ? record.updated_at\n : typeof record.updatedAt === 'string'\n ? record.updatedAt\n : null,\n }\n })\n .filter((value): value is NonNullable<typeof value> => value !== null)\n },\n create: async ({ entityId: targetId, payload }) => {\n const response = await apiCallOrThrow<Record<string, unknown>>(\n '/api/customers/addresses',\n {\n // optimistic-lock-exempt: address create-only (no prior version to compare)\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n entityId: targetId,\n ...payload,\n country: payload.country ? payload.country.toUpperCase() : undefined,\n }),\n },\n { errorMessage: t('customers.people.detail.addresses.error') },\n )\n return response.result ?? {}\n },\n update: async ({ id, payload, updatedAt }) => {\n try {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(updatedAt ?? null),\n () => apiCallOrThrow(\n '/api/customers/addresses',\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n id,\n ...payload,\n country: payload.country ? payload.country.toUpperCase() : undefined,\n }),\n },\n { errorMessage: t('customers.people.detail.addresses.error') },\n ),\n )\n } catch (err) {\n surfaceRecordConflict(err, t)\n throw err\n }\n },\n delete: async ({ id, updatedAt }) => {\n try {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(updatedAt ?? null),\n () => apiCallOrThrow(\n '/api/customers/addresses',\n {\n method: 'DELETE',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id }),\n },\n { errorMessage: t('customers.people.detail.addresses.error') },\n ),\n )\n } catch (err) {\n surfaceRecordConflict(err, t)\n throw err\n }\n },\n }), [t])\n\n const addressTypesAdapter = React.useMemo<AddressTypesAdapter>(() => ({\n list: async () => {\n const call = await apiCall<Record<string, unknown>>('/api/customers/dictionaries/address-types', {\n method: 'GET',\n })\n const payload = call.result ?? {}\n const rawItems = (payload as { items?: unknown[] }).items\n const items = Array.isArray(rawItems) ? rawItems : []\n return items\n .map((item) => {\n if (!item || typeof item !== 'object') return null\n const record = item as Record<string, unknown>\n const value = typeof record.value === 'string' ? record.value : null\n if (!value) return null\n const label = typeof record.label === 'string' && record.label.trim().length ? record.label : value\n return { value, label }\n })\n .filter((entry): entry is { value: string; label: string } => !!entry)\n },\n create: async (value: string) => {\n const response = await apiCallOrThrow<Record<string, unknown>>(\n '/api/customers/dictionaries/address-types',\n {\n // optimistic-lock-exempt: address-type dictionary create-only\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ value }),\n },\n { errorMessage: t('customers.people.detail.addresses.types.saveError', 'Failed to save address type') },\n )\n const payload = response.result ?? {}\n const createdValue = typeof payload.value === 'string' ? payload.value : value\n const label = typeof payload.label === 'string' && payload.label.trim().length ? payload.label : createdValue\n return { value: createdValue, label }\n },\n manageHref: '/backend/config/customers',\n }), [t])\n\n const loadFormat = React.useCallback(async (): Promise<AddressFormatStrategy> => {\n const call = await apiCall<{ addressFormat?: string; error?: string }>(\n '/api/customers/settings/address-format',\n )\n const payload = (call.result ?? {}) as Record<string, unknown>\n if (!call.ok) {\n const message =\n typeof (payload as Record<string, unknown>)?.error === 'string'\n ? (payload as Record<string, unknown>).error as string\n : t('customers.people.detail.addresses.formatLoadError', 'Failed to load address configuration')\n throw new Error(message)\n }\n const valueRaw = payload?.addressFormat\n const value = typeof valueRaw === 'string' ? valueRaw : null\n if (value === 'street_first' || value === 'line_first') {\n return value\n }\n return 'line_first'\n }, [t])\n\n return (\n <SharedAddressesSection\n entityId={entityId}\n emptyLabel={emptyLabel}\n addActionLabel={addActionLabel}\n emptyState={emptyState}\n onActionChange={onActionChange}\n onLoadingChange={onLoadingChange}\n translator={t}\n dataAdapter={dataAdapter}\n addressTypesAdapter={addressTypesAdapter}\n loadFormat={loadFormat}\n />\n )\n}\n\nexport default AddressesSection\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { apiCall, apiCallOrThrow, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { AddressesSection as SharedAddressesSection } from '@open-mercato/ui/backend/detail'\nimport type { AddressDataAdapter, AddressTypesAdapter, AddressFormatStrategy, SectionAction } from '@open-mercato/ui/backend/detail'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nexport type AddressesSectionProps = {\n entityId: string | null\n emptyLabel: string\n addActionLabel: string\n emptyState: { title: string; actionLabel: string; description?: string }\n onActionChange?: (action: SectionAction | null) => void\n translator?: (key: string, fallback?: string, params?: Record<string, string | number>) => string\n onLoadingChange?: (isLoading: boolean) => void\n}\n\ntype ApiAddressPayload = Record<string, unknown>\n\nexport function AddressesSection({\n entityId,\n emptyLabel,\n addActionLabel,\n emptyState,\n onActionChange,\n translator,\n onLoadingChange,\n}: AddressesSectionProps) {\n const tHook = useT()\n const fallbackTranslator = React.useMemo(() => createTranslatorWithFallback(tHook), [tHook])\n const t = translator ?? fallbackTranslator\n\n const dataAdapter = React.useMemo<AddressDataAdapter>(() => ({\n list: async ({ entityId: listEntityId }) => {\n if (!listEntityId) return []\n const params = new URLSearchParams({ entityId: listEntityId, pageSize: '100' })\n const payload = await readApiResultOrThrow<ApiAddressPayload>(\n `/api/customers/addresses?${params.toString()}`,\n undefined,\n { errorMessage: t('customers.people.detail.addresses.error') },\n )\n const items = Array.isArray(payload?.items) ? payload.items : []\n return items\n .map((item) => {\n if (!item || typeof item !== 'object') return null\n const record = item as Record<string, unknown>\n const rawId = record.id ?? record.address_id ?? null\n const id =\n typeof rawId === 'string'\n ? rawId\n : typeof rawId === 'number' || typeof rawId === 'bigint'\n ? String(rawId)\n : null\n if (!id) return null\n const addressLine1 = typeof record.address_line1 === 'string'\n ? record.address_line1\n : typeof record.addressLine1 === 'string'\n ? record.addressLine1\n : null\n if (!addressLine1) return null\n return {\n id,\n name: typeof record.name === 'string' ? record.name : null,\n purpose: typeof record.purpose === 'string' ? record.purpose : null,\n companyName: typeof record.company_name === 'string'\n ? record.company_name\n : typeof record.companyName === 'string'\n ? record.companyName\n : null,\n addressLine1,\n addressLine2: typeof record.address_line2 === 'string'\n ? record.address_line2\n : typeof record.addressLine2 === 'string'\n ? record.addressLine2\n : null,\n buildingNumber: typeof record.building_number === 'string'\n ? record.building_number\n : typeof record.buildingNumber === 'string'\n ? record.buildingNumber\n : null,\n flatNumber: typeof record.flat_number === 'string'\n ? record.flat_number\n : typeof record.flatNumber === 'string'\n ? record.flatNumber\n : null,\n city: typeof record.city === 'string' ? record.city : null,\n region: typeof record.region === 'string' ? record.region : null,\n postalCode: typeof record.postal_code === 'string'\n ? record.postal_code\n : typeof record.postalCode === 'string'\n ? record.postalCode\n : null,\n country: typeof record.country === 'string' ? record.country : null,\n latitude: typeof record.latitude === 'number' && Number.isFinite(record.latitude) ? record.latitude : null,\n longitude: typeof record.longitude === 'number' && Number.isFinite(record.longitude) ? record.longitude : null,\n isPrimary:\n typeof record.is_primary === 'boolean'\n ? record.is_primary\n : typeof record.isPrimary === 'boolean'\n ? record.isPrimary\n : false,\n updatedAt:\n typeof record.updated_at === 'string'\n ? record.updated_at\n : typeof record.updatedAt === 'string'\n ? record.updatedAt\n : null,\n }\n })\n .filter((value): value is NonNullable<typeof value> => value !== null)\n },\n create: async ({ entityId: targetId, payload }) => {\n const response = await apiCallOrThrow<Record<string, unknown>>(\n '/api/customers/addresses',\n {\n // optimistic-lock-exempt: address create-only (no prior version to compare)\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n entityId: targetId,\n ...payload,\n country: payload.country ? payload.country.toUpperCase() : undefined,\n }),\n },\n { errorMessage: t('customers.people.detail.addresses.error') },\n )\n return response.result ?? {}\n },\n update: async ({ id, payload, updatedAt }) => {\n try {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(updatedAt ?? null),\n () => apiCallOrThrow(\n '/api/customers/addresses',\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n id,\n ...payload,\n country: payload.country ? payload.country.toUpperCase() : undefined,\n }),\n },\n { errorMessage: t('customers.people.detail.addresses.error') },\n ),\n )\n } catch (err) {\n surfaceRecordConflict(err, t)\n throw err\n }\n },\n delete: async ({ id, updatedAt }) => {\n try {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(updatedAt ?? null),\n () => apiCallOrThrow(\n '/api/customers/addresses',\n {\n method: 'DELETE',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id }),\n },\n { errorMessage: t('customers.people.detail.addresses.error') },\n ),\n )\n } catch (err) {\n surfaceRecordConflict(err, t)\n throw err\n }\n },\n }), [t])\n\n const addressTypesAdapter = React.useMemo<AddressTypesAdapter>(() => ({\n list: async () => {\n const call = await apiCall<Record<string, unknown>>('/api/customers/dictionaries/address-types', {\n method: 'GET',\n })\n const payload = call.result ?? {}\n const rawItems = (payload as { items?: unknown[] }).items\n const items = Array.isArray(rawItems) ? rawItems : []\n return items\n .map((item) => {\n if (!item || typeof item !== 'object') return null\n const record = item as Record<string, unknown>\n const value = typeof record.value === 'string' ? record.value : null\n if (!value) return null\n const label = typeof record.label === 'string' && record.label.trim().length ? record.label : value\n return { value, label }\n })\n .filter((entry): entry is { value: string; label: string } => !!entry)\n },\n create: async (value: string) => {\n const response = await apiCallOrThrow<Record<string, unknown>>(\n '/api/customers/dictionaries/address-types',\n {\n // optimistic-lock-exempt: address-type dictionary create-only\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ value }),\n },\n { errorMessage: t('customers.people.detail.addresses.types.saveError', 'Failed to save address type') },\n )\n const payload = response.result ?? {}\n const createdValue = typeof payload.value === 'string' ? payload.value : value\n const label = typeof payload.label === 'string' && payload.label.trim().length ? payload.label : createdValue\n return { value: createdValue, label }\n },\n manageHref: '/backend/config/customers',\n }), [t])\n\n const loadFormat = React.useCallback(async (): Promise<AddressFormatStrategy> => {\n const call = await apiCall<{ addressFormat?: string; error?: string }>(\n '/api/customers/settings/address-format',\n )\n const payload = (call.result ?? {}) as Record<string, unknown>\n if (!call.ok) {\n const message =\n typeof (payload as Record<string, unknown>)?.error === 'string'\n ? (payload as Record<string, unknown>).error as string\n : t('customers.people.detail.addresses.formatLoadError', 'Failed to load address configuration')\n throw new Error(message)\n }\n const valueRaw = payload?.addressFormat\n const value = typeof valueRaw === 'string' ? valueRaw : null\n if (value === 'street_first' || value === 'line_first') {\n return value\n }\n return 'line_first'\n }, [t])\n\n return (\n <SharedAddressesSection\n entityId={entityId}\n emptyLabel={emptyLabel}\n addActionLabel={addActionLabel}\n emptyState={emptyState}\n onActionChange={onActionChange}\n onLoadingChange={onLoadingChange}\n translator={t}\n dataAdapter={dataAdapter}\n addressTypesAdapter={addressTypesAdapter}\n loadFormat={loadFormat}\n showCoordinateFields\n />\n )\n}\n\nexport default AddressesSection\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -715,6 +715,7 @@ const createPersonFormFields = (t) => {
715
715
  t,
716
716
  emptyLabel: t("customers.people.detail.empty.addresses"),
717
717
  gridClassName: "grid gap-4 min-[480px]:grid-cols-1 xl:grid-cols-2",
718
+ showCoordinateFields: true,
718
719
  onCreate: async (payload) => {
719
720
  const nextId = typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : `tmp-${Math.random().toString(36).slice(2)}`;
720
721
  const next = {
@@ -730,6 +731,8 @@ const createPersonFormFields = (t) => {
730
731
  region: payload.region ?? void 0,
731
732
  postalCode: payload.postalCode ?? void 0,
732
733
  country: payload.country ?? void 0,
734
+ latitude: payload.latitude ?? void 0,
735
+ longitude: payload.longitude ?? void 0,
733
736
  isPrimary: payload.isPrimary ?? false
734
737
  };
735
738
  const current = Array.isArray(addresses) ? addresses : [];
@@ -755,6 +758,8 @@ const createPersonFormFields = (t) => {
755
758
  region: payload.region ?? null,
756
759
  postalCode: payload.postalCode ?? null,
757
760
  country: payload.country ?? null,
761
+ latitude: payload.latitude ?? null,
762
+ longitude: payload.longitude ?? null,
758
763
  isPrimary: payload.isPrimary ?? false
759
764
  };
760
765
  });
@@ -977,6 +982,7 @@ const createCompanyFormFields = (t) => {
977
982
  t,
978
983
  emptyLabel: t("customers.companies.detail.empty.addresses"),
979
984
  gridClassName: "grid gap-4 min-[480px]:grid-cols-1 xl:grid-cols-2",
985
+ showCoordinateFields: true,
980
986
  onCreate: async (payload) => {
981
987
  const nextId = typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : `tmp-${Math.random().toString(36).slice(2)}`;
982
988
  const next = {
@@ -992,6 +998,8 @@ const createCompanyFormFields = (t) => {
992
998
  region: payload.region ?? void 0,
993
999
  postalCode: payload.postalCode ?? void 0,
994
1000
  country: payload.country ?? void 0,
1001
+ latitude: payload.latitude ?? void 0,
1002
+ longitude: payload.longitude ?? void 0,
995
1003
  isPrimary: payload.isPrimary ?? false
996
1004
  };
997
1005
  const current = Array.isArray(addresses) ? addresses : [];
@@ -1017,6 +1025,8 @@ const createCompanyFormFields = (t) => {
1017
1025
  region: payload.region ?? null,
1018
1026
  postalCode: payload.postalCode ?? null,
1019
1027
  country: payload.country ?? null,
1028
+ latitude: payload.latitude ?? null,
1029
+ longitude: payload.longitude ?? null,
1020
1030
  isPrimary: payload.isPrimary ?? false
1021
1031
  };
1022
1032
  });