@open-mercato/core 0.7.1-develop.7153.1.7145d295e6 → 0.7.1-develop.7170.1.d95074d7ba

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 (116) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +2 -2
  3. package/dist/modules/auth/commands/users.js +14 -1
  4. package/dist/modules/auth/commands/users.js.map +2 -2
  5. package/dist/modules/auth/data/entities.js +2 -2
  6. package/dist/modules/auth/data/entities.js.map +2 -2
  7. package/dist/modules/auth/lib/backendChrome.js +26 -3
  8. package/dist/modules/auth/lib/backendChrome.js.map +2 -2
  9. package/dist/modules/auth/lib/profile-sections.js +1 -1
  10. package/dist/modules/auth/lib/profile-sections.js.map +2 -2
  11. package/dist/modules/auth/migrations/Migration20260907120000_auth.js +19 -0
  12. package/dist/modules/auth/migrations/Migration20260907120000_auth.js.map +7 -0
  13. package/dist/modules/communication_channels/backend/profile/communication-channels/page.meta.js +2 -2
  14. package/dist/modules/communication_channels/backend/profile/communication-channels/page.meta.js.map +1 -1
  15. package/dist/modules/customer_accounts/api/admin/demo-accounts.js +118 -0
  16. package/dist/modules/customer_accounts/api/admin/demo-accounts.js.map +7 -0
  17. package/dist/modules/customer_accounts/api/invitations/accept.js +23 -6
  18. package/dist/modules/customer_accounts/api/invitations/accept.js.map +2 -2
  19. package/dist/modules/customer_accounts/backend/customer_accounts/settings/CustomerAccountsSettingsPageClient.js +10 -13
  20. package/dist/modules/customer_accounts/backend/customer_accounts/settings/CustomerAccountsSettingsPageClient.js.map +2 -2
  21. package/dist/modules/customer_accounts/backend/customer_accounts/useDemoPortalAccounts.js +28 -0
  22. package/dist/modules/customer_accounts/backend/customer_accounts/useDemoPortalAccounts.js.map +7 -0
  23. package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js +6 -1
  24. package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js.map +2 -2
  25. package/dist/modules/customer_accounts/data/entities.js +4 -1
  26. package/dist/modules/customer_accounts/data/entities.js.map +2 -2
  27. package/dist/modules/customer_accounts/lib/exampleAccounts.js +9 -0
  28. package/dist/modules/customer_accounts/lib/exampleAccounts.js.map +7 -0
  29. package/dist/modules/customer_accounts/migrations/Migration20260827160000_customer_accounts.js +16 -0
  30. package/dist/modules/customer_accounts/migrations/Migration20260827160000_customer_accounts.js.map +7 -0
  31. package/dist/modules/customer_accounts/services/customerInvitationService.js +53 -6
  32. package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
  33. package/dist/modules/customer_accounts/setup.js +2 -6
  34. package/dist/modules/customer_accounts/setup.js.map +2 -2
  35. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +55 -40
  36. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
  37. package/dist/modules/customers/commands/people.js +16 -1
  38. package/dist/modules/customers/commands/people.js.map +2 -2
  39. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +18 -36
  40. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
  41. package/dist/modules/data_sync/lib/sync-schedule-service.js +25 -23
  42. package/dist/modules/data_sync/lib/sync-schedule-service.js.map +2 -2
  43. package/dist/modules/entities/api/records.js +18 -15
  44. package/dist/modules/entities/api/records.js.map +3 -3
  45. package/dist/modules/entities/lib/scoped-field-defs.js +52 -0
  46. package/dist/modules/entities/lib/scoped-field-defs.js.map +7 -0
  47. package/dist/modules/entities/lib/validation.js +4 -35
  48. package/dist/modules/entities/lib/validation.js.map +2 -2
  49. package/dist/modules/integrations/backend/integrations/[id]/page.js +32 -54
  50. package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
  51. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +12 -29
  52. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
  53. package/dist/modules/notifications/backend/profile/notification-preferences/page.meta.js +2 -2
  54. package/dist/modules/notifications/backend/profile/notification-preferences/page.meta.js.map +1 -1
  55. package/dist/modules/progress/lib/progressServiceImpl.js +14 -3
  56. package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
  57. package/dist/modules/sales/backend/sales/documents/[id]/page.js +9 -9
  58. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  59. package/dist/modules/sales/components/documents/LineItemDialog.js +50 -10
  60. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  61. package/dist/modules/sales/components/documents/PaymentsSection.js +8 -3
  62. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  63. package/dist/modules/sales/components/documents/ReturnEditDialog.js +2 -7
  64. package/dist/modules/sales/components/documents/ReturnEditDialog.js.map +2 -2
  65. package/dist/modules/sales/components/documents/ReturnsSection.js +2 -7
  66. package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
  67. package/dist/modules/sales/components/documents/ShipmentsSection.js +3 -8
  68. package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
  69. package/package.json +7 -7
  70. package/src/modules/auth/commands/users.ts +14 -1
  71. package/src/modules/auth/data/entities.ts +2 -2
  72. package/src/modules/auth/lib/backendChrome.tsx +46 -2
  73. package/src/modules/auth/lib/profile-sections.tsx +14 -3
  74. package/src/modules/auth/migrations/.snapshot-open-mercato.json +4 -2
  75. package/src/modules/auth/migrations/Migration20260907120000_auth.ts +21 -0
  76. package/src/modules/communication_channels/backend/profile/communication-channels/page.meta.ts +2 -2
  77. package/src/modules/customer_accounts/AGENTS.md +3 -1
  78. package/src/modules/customer_accounts/api/admin/demo-accounts.ts +149 -0
  79. package/src/modules/customer_accounts/api/invitations/accept.ts +23 -6
  80. package/src/modules/customer_accounts/backend/customer_accounts/settings/CustomerAccountsSettingsPageClient.tsx +43 -41
  81. package/src/modules/customer_accounts/backend/customer_accounts/useDemoPortalAccounts.ts +42 -0
  82. package/src/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.tsx +10 -3
  83. package/src/modules/customer_accounts/data/entities.ts +5 -1
  84. package/src/modules/customer_accounts/i18n/de.json +4 -2
  85. package/src/modules/customer_accounts/i18n/en.json +4 -2
  86. package/src/modules/customer_accounts/i18n/es.json +4 -2
  87. package/src/modules/customer_accounts/i18n/ko.json +4 -2
  88. package/src/modules/customer_accounts/i18n/pl.json +4 -2
  89. package/src/modules/customer_accounts/lib/exampleAccounts.ts +18 -0
  90. package/src/modules/customer_accounts/migrations/.snapshot-open-mercato.json +5 -7
  91. package/src/modules/customer_accounts/migrations/Migration20260827160000_customer_accounts.ts +23 -0
  92. package/src/modules/customer_accounts/services/customerInvitationService.ts +89 -5
  93. package/src/modules/customer_accounts/setup.ts +2 -6
  94. package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +74 -41
  95. package/src/modules/customers/commands/people.ts +15 -0
  96. package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +19 -44
  97. package/src/modules/data_sync/lib/sync-schedule-service.ts +32 -26
  98. package/src/modules/entities/api/records.ts +24 -15
  99. package/src/modules/entities/lib/scoped-field-defs.ts +76 -0
  100. package/src/modules/entities/lib/validation.ts +5 -45
  101. package/src/modules/integrations/backend/integrations/[id]/page.tsx +33 -62
  102. package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +13 -37
  103. package/src/modules/notifications/backend/profile/notification-preferences/page.meta.ts +2 -2
  104. package/src/modules/progress/AGENTS.md +1 -1
  105. package/src/modules/progress/lib/progressServiceImpl.ts +26 -3
  106. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +19 -25
  107. package/src/modules/sales/components/documents/LineItemDialog.tsx +53 -9
  108. package/src/modules/sales/components/documents/PaymentsSection.tsx +8 -8
  109. package/src/modules/sales/components/documents/ReturnEditDialog.tsx +2 -8
  110. package/src/modules/sales/components/documents/ReturnsSection.tsx +8 -7
  111. package/src/modules/sales/components/documents/ShipmentsSection.tsx +9 -8
  112. package/src/modules/sales/i18n/de.json +2 -0
  113. package/src/modules/sales/i18n/en.json +2 -0
  114. package/src/modules/sales/i18n/es.json +2 -0
  115. package/src/modules/sales/i18n/ko.json +2 -0
  116. package/src/modules/sales/i18n/pl.json +2 -0
@@ -9,6 +9,7 @@ import { deleteCrud } from "@open-mercato/ui/backend/utils/crud";
9
9
  import { handleSectionMutationError, readRowUpdatedAt } from "./optimisticLock.js";
10
10
  import { RowActions } from "@open-mercato/ui/backend/RowActions";
11
11
  import { Button } from "@open-mercato/ui/primitives/button";
12
+ import { formatDisplayDate, formatDisplayDateTime, toUtcDateInputValue } from "@open-mercato/ui/primitives/date-format";
12
13
  import { flash } from "@open-mercato/ui/backend/FlashMessages";
13
14
  import { useOrganizationScopeDetail } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
14
15
  import { useT, useLocale } from "@open-mercato/shared/lib/i18n/context";
@@ -219,14 +220,18 @@ function SalesDocumentPaymentsSection({
219
220
  {
220
221
  accessorKey: "receivedAt",
221
222
  header: t("sales.documents.payments.receivedAt", "Received"),
222
- cell: ({ row }) => row.original.receivedAt ? new Date(row.original.receivedAt).toLocaleDateString(locale) : "\u2014"
223
+ // `receivedAt` is written from a date input (`PaymentDialog`), coerced with
224
+ // `z.coerce.date()` and stored as UTC midnight, so its day must be read in UTC.
225
+ // Reading it locally names the previous day west of UTC — and disagrees with the
226
+ // Edit dialog, which seeds from `receivedAt.slice(0, 10)`, i.e. the UTC day.
227
+ cell: ({ row }) => formatDisplayDate(toUtcDateInputValue(row.original.receivedAt), locale) ?? "\u2014"
223
228
  },
224
229
  {
225
230
  accessorKey: "createdAt",
226
231
  header: t("sales.documents.payments.createdAt", "Created"),
227
- cell: ({ row }) => row.original.createdAt ? new Date(row.original.createdAt).toLocaleString(locale) : "\u2014",
232
+ cell: ({ row }) => formatDisplayDateTime(row.original.createdAt, locale) ?? "\u2014",
228
233
  meta: {
229
- tooltipContent: (row) => row.createdAt ? new Date(row.createdAt).toLocaleString(locale) : void 0
234
+ tooltipContent: (row) => formatDisplayDateTime(row.createdAt, locale) ?? void 0
230
235
  }
231
236
  },
232
237
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/sales/components/documents/PaymentsSection.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { LoadingMessage, ErrorMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { handleSectionMutationError, readRowUpdatedAt } from './optimisticLock'\nimport type { SectionAction } from '@open-mercato/ui/backend/detail'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT, useLocale } from '@open-mercato/shared/lib/i18n/context'\nimport { emitSalesDocumentTotalsRefresh } from '@open-mercato/core/modules/sales/lib/frontend/documentTotalsEvents'\nimport { extensionPoints } from '@open-mercato/core/modules/sales/extension-points'\nimport { PaymentDialog, type PaymentFormData, type PaymentTotals } from './PaymentDialog'\nimport { extractCustomFieldValues } from './customFieldHelpers'\nimport { Plus } from 'lucide-react'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('sales')\n\ntype PaymentRow = {\n id: string\n updatedAt: string | null\n paymentReference: string | null\n paymentMethodId: string | null\n paymentMethodName: string | null\n status: string | null\n statusEntryId: string | null\n statusLabel: string | null\n amount: number\n currencyCode: string | null\n receivedAt: string | null\n createdAt: string | null\n customValues?: Record<string, unknown> | null\n customFieldSetId?: string | null\n}\n\ntype SalesDocumentPaymentsSectionProps = {\n orderId: string\n currencyCode: string | null | undefined\n organizationId?: string | null\n tenantId?: string | null\n documentUpdatedAt?: string | null\n onActionChange?: (action: SectionAction | null) => void\n onTotalsChange?: () => void\n onPaymentsChange?: (payments: PaymentRow[]) => void\n}\n\nfunction normalizeNumber(value: unknown): number {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string' && value.trim().length) {\n const parsed = Number(value)\n if (!Number.isNaN(parsed)) return parsed\n }\n return 0\n}\n\nfunction formatMoney(value: number, currency: string | null | undefined, locale?: string): string {\n if (!currency || currency.trim().length !== 3) return value.toFixed(2)\n try {\n return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(value)\n } catch {\n return `${currency.toUpperCase()} ${value.toFixed(2)}`\n }\n}\n\nexport function SalesDocumentPaymentsSection({\n orderId,\n currencyCode,\n organizationId: orgFromProps,\n tenantId: tenantFromProps,\n documentUpdatedAt,\n onActionChange,\n onTotalsChange,\n onPaymentsChange,\n}: SalesDocumentPaymentsSectionProps) {\n const t = useT()\n const locale = useLocale()\n const { organizationId, tenantId } = useOrganizationScopeDetail()\n const resolvedOrganizationId = orgFromProps ?? organizationId ?? null\n const resolvedTenantId = tenantFromProps ?? tenantId ?? null\n const [payments, setPayments] = React.useState<PaymentRow[]>([])\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const [dialogOpen, setDialogOpen] = React.useState(false)\n const [editingPayment, setEditingPayment] = React.useState<PaymentFormData | null>(null)\n const onPaymentsChangeRef = React.useRef<typeof onPaymentsChange>(onPaymentsChange)\n\n React.useEffect(() => {\n onPaymentsChangeRef.current = onPaymentsChange\n }, [onPaymentsChange])\n\n const addActionLabel = t('sales.documents.payments.add', 'Add payment')\n const editActionLabel = t('sales.documents.payments.edit', 'Edit payment')\n const deleteActionLabel = t('sales.documents.payments.delete', 'Delete payment')\n\n const loadPayments = React.useCallback(async () => {\n setLoading(true)\n setError(null)\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '100', orderId })\n const response = await apiCall<{ items?: Array<Record<string, unknown>> }>(\n `/api/sales/payments?${params.toString()}`,\n undefined,\n { fallback: { items: [] } }\n )\n if (response.ok && Array.isArray(response.result?.items)) {\n const mapped = response.result.items.flatMap<PaymentRow>((item) => {\n if (typeof item.id !== 'string') return []\n const customValues =\n item && typeof item === 'object'\n ? extractCustomFieldValues(item as Record<string, unknown>)\n : {}\n const record: PaymentRow = {\n id: item.id,\n updatedAt: readRowUpdatedAt(item),\n paymentReference: typeof item.payment_reference === 'string' ? item.payment_reference : null,\n paymentMethodId: typeof item.payment_method_id === 'string' ? item.payment_method_id : null,\n paymentMethodName:\n typeof item.payment_method_name === 'string'\n ? item.payment_method_name\n : typeof item.payment_method_code === 'string'\n ? item.payment_method_code\n : null,\n status: typeof item.status === 'string' ? item.status : null,\n statusEntryId:\n typeof (item as any).status_entry_id === 'string'\n ? (item as any).status_entry_id\n : typeof (item as any).statusEntryId === 'string'\n ? (item as any).statusEntryId\n : null,\n statusLabel:\n typeof (item as any).status_label === 'string'\n ? (item as any).status_label\n : typeof (item as any).statusLabel === 'string'\n ? (item as any).statusLabel\n : null,\n amount: normalizeNumber(item.amount),\n currencyCode:\n typeof item.currency_code === 'string'\n ? item.currency_code\n : typeof currencyCode === 'string'\n ? currencyCode\n : null,\n receivedAt: typeof item.received_at === 'string' ? item.received_at : null,\n createdAt: typeof item.created_at === 'string' ? item.created_at : null,\n customValues: Object.keys(customValues).length ? customValues : null,\n customFieldSetId:\n typeof (item as any)?.custom_field_set_id === 'string'\n ? (item as any).custom_field_set_id\n : typeof (item as any)?.customFieldSetId === 'string'\n ? (item as any).customFieldSetId\n : null,\n }\n return [record]\n })\n setPayments(mapped)\n onPaymentsChangeRef.current?.(mapped)\n } else {\n setPayments([])\n onPaymentsChangeRef.current?.([])\n }\n } catch (err) {\n logger.error('sales.payments.list', { err })\n setError(t('sales.documents.payments.errorLoad', 'Failed to load payments.'))\n onPaymentsChangeRef.current?.([])\n } finally {\n setLoading(false)\n }\n }, [currencyCode, orderId, t])\n\n React.useEffect(() => {\n void loadPayments()\n }, [loadPayments])\n\n const openCreate = React.useCallback(() => {\n setEditingPayment(null)\n setDialogOpen(true)\n }, [])\n\n const handleDialogChange = React.useCallback((nextOpen: boolean) => {\n setDialogOpen(nextOpen)\n if (!nextOpen) {\n setEditingPayment(null)\n }\n }, [])\n\n const openEditPayment = React.useCallback(\n (record: PaymentRow) => {\n setEditingPayment({\n id: record.id,\n updatedAt: record.updatedAt ?? null,\n amount: record.amount ?? '',\n paymentMethodId: record.paymentMethodId ?? '',\n paymentReference: record.paymentReference ?? '',\n receivedAt: record.receivedAt ? record.receivedAt.slice(0, 10) : '',\n currencyCode: record.currencyCode ?? currencyCode ?? null,\n statusEntryId: record.statusEntryId ?? null,\n customValues: record.customValues ?? null,\n customFieldSetId: record.customFieldSetId ?? null,\n })\n setDialogOpen(true)\n },\n [currencyCode]\n )\n\n const handlePaymentSaved = React.useCallback(\n async (_totals?: PaymentTotals | null) => {\n onTotalsChange?.()\n await loadPayments()\n emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: 'order' })\n handleDialogChange(false)\n },\n [handleDialogChange, loadPayments, onTotalsChange, orderId]\n )\n\n const handleDelete = React.useCallback(\n async (row: PaymentRow) => {\n try {\n const result = await withScopedApiRequestHeaders(\n // The server guards the PARENT order's aggregate version (Gap A), so\n // send the order's `updated_at`, not the payment row's.\n buildOptimisticLockHeader(documentUpdatedAt ?? undefined),\n () =>\n deleteCrud<{ orderTotals?: PaymentTotals | null }>('sales/payments', {\n body: {\n id: row.id,\n orderId,\n organizationId: resolvedOrganizationId ?? undefined,\n tenantId: resolvedTenantId ?? undefined,\n },\n errorMessage: t('sales.documents.payments.errorDelete', 'Failed to delete payment.'),\n })\n )\n if (result.ok) {\n onTotalsChange?.()\n flash(t('sales.documents.payments.deleted', 'Payment deleted.'), 'success')\n await loadPayments()\n emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: 'order' })\n }\n } catch (err) {\n if (handleSectionMutationError(err, t, () => void loadPayments())) {\n return\n }\n logger.error('sales.payments.delete', { err })\n flash(t('sales.documents.payments.errorDelete', 'Failed to delete payment.'), 'error')\n }\n },\n [documentUpdatedAt, loadPayments, onTotalsChange, orderId, resolvedOrganizationId, resolvedTenantId, t]\n )\n\n React.useEffect(() => {\n if (!onActionChange) return\n onActionChange({\n label: addActionLabel,\n onClick: openCreate,\n disabled: false,\n })\n return () => onActionChange(null)\n }, [addActionLabel, onActionChange, openCreate])\n\n const columns = React.useMemo<ColumnDef<PaymentRow>[]>(\n () => [\n {\n accessorKey: 'paymentReference',\n header: t('sales.documents.payments.reference', 'Reference'),\n cell: ({ row }) => row.original.paymentReference || '\u2014',\n },\n {\n accessorKey: 'paymentMethodName',\n header: t('sales.documents.payments.method', 'Method'),\n cell: ({ row }) => row.original.paymentMethodName ?? '\u2014',\n },\n {\n // Injected columns are placed against `ColumnDef.id` before the table is\n // built, so an accessor-derived id is not yet available: the gateway\n // status widget anchors on this explicit id.\n id: 'status',\n accessorKey: 'status',\n header: t('sales.documents.payments.status', 'Status'),\n cell: ({ row }) => row.original.statusLabel ?? row.original.status ?? '\u2014',\n },\n {\n accessorKey: 'amount',\n header: t('sales.documents.payments.amount', 'Amount'),\n cell: ({ row }) => formatMoney(row.original.amount, row.original.currencyCode ?? currencyCode, locale),\n },\n {\n accessorKey: 'receivedAt',\n header: t('sales.documents.payments.receivedAt', 'Received'),\n cell: ({ row }) =>\n row.original.receivedAt\n ? new Date(row.original.receivedAt).toLocaleDateString(locale)\n : '\u2014',\n },\n {\n accessorKey: 'createdAt',\n header: t('sales.documents.payments.createdAt', 'Created'),\n cell: ({ row }) =>\n row.original.createdAt ? new Date(row.original.createdAt).toLocaleString(locale) : '\u2014',\n meta: {\n tooltipContent: (row: PaymentRow) =>\n row.createdAt ? new Date(row.createdAt).toLocaleString(locale) : undefined,\n },\n },\n {\n id: 'actions',\n header: '',\n cell: ({ row }) => {\n return (\n <RowActions\n items={[\n { id: 'edit', label: editActionLabel, onSelect: () => openEditPayment(row.original) },\n {\n id: 'delete',\n label: deleteActionLabel,\n destructive: true,\n onSelect: () => void handleDelete(row.original),\n },\n ]}\n />\n )\n },\n },\n ],\n [currencyCode, deleteActionLabel, editActionLabel, handleDelete, locale, openEditPayment, t]\n )\n\n if (loading) {\n return (\n <LoadingMessage\n label={t('sales.documents.payments.loading', 'Loading payments\u2026')}\n className=\"border-0 bg-transparent p-0 py-8 justify-center\"\n />\n )\n }\n\n if (error) {\n return (\n <ErrorMessage\n label={error}\n action={\n <Button variant=\"outline\" size=\"sm\" onClick={() => void loadPayments()}>\n {t('sales.documents.payments.retry', 'Retry')}\n </Button>\n }\n />\n )\n }\n\n return (\n <div className=\"space-y-4\">\n {payments.length ? (\n <DataTable<PaymentRow>\n columns={columns}\n data={payments}\n onRowClick={openEditPayment}\n extensionTableId={extensionPoints.hosts.paymentsTable.tableId}\n />\n ) : (\n <TabEmptyState\n title={t('sales.documents.payments.emptyTitle', 'No payments yet.')}\n description={t(\n 'sales.documents.payments.emptyDescription',\n 'Track received payments to keep outstanding balances up to date.'\n )}\n action={{\n label: addActionLabel,\n onClick: openCreate,\n icon: <Plus className=\"h-4 w-4\" aria-hidden />,\n disabled: loading,\n }}\n />\n )}\n\n <PaymentDialog\n open={dialogOpen}\n onOpenChange={handleDialogChange}\n mode={editingPayment ? 'edit' : 'create'}\n payment={editingPayment}\n currencyCode={editingPayment?.currencyCode ?? currencyCode}\n orderId={orderId}\n organizationId={resolvedOrganizationId}\n tenantId={resolvedTenantId}\n documentUpdatedAt={documentUpdatedAt ?? null}\n onSaved={handlePaymentSaved}\n />\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { LoadingMessage, ErrorMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { handleSectionMutationError, readRowUpdatedAt } from './optimisticLock'\nimport type { SectionAction } from '@open-mercato/ui/backend/detail'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { formatDisplayDate, formatDisplayDateTime, toUtcDateInputValue } from '@open-mercato/ui/primitives/date-format'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT, useLocale } from '@open-mercato/shared/lib/i18n/context'\nimport { emitSalesDocumentTotalsRefresh } from '@open-mercato/core/modules/sales/lib/frontend/documentTotalsEvents'\nimport { extensionPoints } from '@open-mercato/core/modules/sales/extension-points'\nimport { PaymentDialog, type PaymentFormData, type PaymentTotals } from './PaymentDialog'\nimport { extractCustomFieldValues } from './customFieldHelpers'\nimport { Plus } from 'lucide-react'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('sales')\n\ntype PaymentRow = {\n id: string\n updatedAt: string | null\n paymentReference: string | null\n paymentMethodId: string | null\n paymentMethodName: string | null\n status: string | null\n statusEntryId: string | null\n statusLabel: string | null\n amount: number\n currencyCode: string | null\n receivedAt: string | null\n createdAt: string | null\n customValues?: Record<string, unknown> | null\n customFieldSetId?: string | null\n}\n\ntype SalesDocumentPaymentsSectionProps = {\n orderId: string\n currencyCode: string | null | undefined\n organizationId?: string | null\n tenantId?: string | null\n documentUpdatedAt?: string | null\n onActionChange?: (action: SectionAction | null) => void\n onTotalsChange?: () => void\n onPaymentsChange?: (payments: PaymentRow[]) => void\n}\n\nfunction normalizeNumber(value: unknown): number {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string' && value.trim().length) {\n const parsed = Number(value)\n if (!Number.isNaN(parsed)) return parsed\n }\n return 0\n}\n\nfunction formatMoney(value: number, currency: string | null | undefined, locale?: string): string {\n if (!currency || currency.trim().length !== 3) return value.toFixed(2)\n try {\n return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(value)\n } catch {\n return `${currency.toUpperCase()} ${value.toFixed(2)}`\n }\n}\n\nexport function SalesDocumentPaymentsSection({\n orderId,\n currencyCode,\n organizationId: orgFromProps,\n tenantId: tenantFromProps,\n documentUpdatedAt,\n onActionChange,\n onTotalsChange,\n onPaymentsChange,\n}: SalesDocumentPaymentsSectionProps) {\n const t = useT()\n const locale = useLocale()\n const { organizationId, tenantId } = useOrganizationScopeDetail()\n const resolvedOrganizationId = orgFromProps ?? organizationId ?? null\n const resolvedTenantId = tenantFromProps ?? tenantId ?? null\n const [payments, setPayments] = React.useState<PaymentRow[]>([])\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const [dialogOpen, setDialogOpen] = React.useState(false)\n const [editingPayment, setEditingPayment] = React.useState<PaymentFormData | null>(null)\n const onPaymentsChangeRef = React.useRef<typeof onPaymentsChange>(onPaymentsChange)\n\n React.useEffect(() => {\n onPaymentsChangeRef.current = onPaymentsChange\n }, [onPaymentsChange])\n\n const addActionLabel = t('sales.documents.payments.add', 'Add payment')\n const editActionLabel = t('sales.documents.payments.edit', 'Edit payment')\n const deleteActionLabel = t('sales.documents.payments.delete', 'Delete payment')\n\n const loadPayments = React.useCallback(async () => {\n setLoading(true)\n setError(null)\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '100', orderId })\n const response = await apiCall<{ items?: Array<Record<string, unknown>> }>(\n `/api/sales/payments?${params.toString()}`,\n undefined,\n { fallback: { items: [] } }\n )\n if (response.ok && Array.isArray(response.result?.items)) {\n const mapped = response.result.items.flatMap<PaymentRow>((item) => {\n if (typeof item.id !== 'string') return []\n const customValues =\n item && typeof item === 'object'\n ? extractCustomFieldValues(item as Record<string, unknown>)\n : {}\n const record: PaymentRow = {\n id: item.id,\n updatedAt: readRowUpdatedAt(item),\n paymentReference: typeof item.payment_reference === 'string' ? item.payment_reference : null,\n paymentMethodId: typeof item.payment_method_id === 'string' ? item.payment_method_id : null,\n paymentMethodName:\n typeof item.payment_method_name === 'string'\n ? item.payment_method_name\n : typeof item.payment_method_code === 'string'\n ? item.payment_method_code\n : null,\n status: typeof item.status === 'string' ? item.status : null,\n statusEntryId:\n typeof (item as any).status_entry_id === 'string'\n ? (item as any).status_entry_id\n : typeof (item as any).statusEntryId === 'string'\n ? (item as any).statusEntryId\n : null,\n statusLabel:\n typeof (item as any).status_label === 'string'\n ? (item as any).status_label\n : typeof (item as any).statusLabel === 'string'\n ? (item as any).statusLabel\n : null,\n amount: normalizeNumber(item.amount),\n currencyCode:\n typeof item.currency_code === 'string'\n ? item.currency_code\n : typeof currencyCode === 'string'\n ? currencyCode\n : null,\n receivedAt: typeof item.received_at === 'string' ? item.received_at : null,\n createdAt: typeof item.created_at === 'string' ? item.created_at : null,\n customValues: Object.keys(customValues).length ? customValues : null,\n customFieldSetId:\n typeof (item as any)?.custom_field_set_id === 'string'\n ? (item as any).custom_field_set_id\n : typeof (item as any)?.customFieldSetId === 'string'\n ? (item as any).customFieldSetId\n : null,\n }\n return [record]\n })\n setPayments(mapped)\n onPaymentsChangeRef.current?.(mapped)\n } else {\n setPayments([])\n onPaymentsChangeRef.current?.([])\n }\n } catch (err) {\n logger.error('sales.payments.list', { err })\n setError(t('sales.documents.payments.errorLoad', 'Failed to load payments.'))\n onPaymentsChangeRef.current?.([])\n } finally {\n setLoading(false)\n }\n }, [currencyCode, orderId, t])\n\n React.useEffect(() => {\n void loadPayments()\n }, [loadPayments])\n\n const openCreate = React.useCallback(() => {\n setEditingPayment(null)\n setDialogOpen(true)\n }, [])\n\n const handleDialogChange = React.useCallback((nextOpen: boolean) => {\n setDialogOpen(nextOpen)\n if (!nextOpen) {\n setEditingPayment(null)\n }\n }, [])\n\n const openEditPayment = React.useCallback(\n (record: PaymentRow) => {\n setEditingPayment({\n id: record.id,\n updatedAt: record.updatedAt ?? null,\n amount: record.amount ?? '',\n paymentMethodId: record.paymentMethodId ?? '',\n paymentReference: record.paymentReference ?? '',\n receivedAt: record.receivedAt ? record.receivedAt.slice(0, 10) : '',\n currencyCode: record.currencyCode ?? currencyCode ?? null,\n statusEntryId: record.statusEntryId ?? null,\n customValues: record.customValues ?? null,\n customFieldSetId: record.customFieldSetId ?? null,\n })\n setDialogOpen(true)\n },\n [currencyCode]\n )\n\n const handlePaymentSaved = React.useCallback(\n async (_totals?: PaymentTotals | null) => {\n onTotalsChange?.()\n await loadPayments()\n emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: 'order' })\n handleDialogChange(false)\n },\n [handleDialogChange, loadPayments, onTotalsChange, orderId]\n )\n\n const handleDelete = React.useCallback(\n async (row: PaymentRow) => {\n try {\n const result = await withScopedApiRequestHeaders(\n // The server guards the PARENT order's aggregate version (Gap A), so\n // send the order's `updated_at`, not the payment row's.\n buildOptimisticLockHeader(documentUpdatedAt ?? undefined),\n () =>\n deleteCrud<{ orderTotals?: PaymentTotals | null }>('sales/payments', {\n body: {\n id: row.id,\n orderId,\n organizationId: resolvedOrganizationId ?? undefined,\n tenantId: resolvedTenantId ?? undefined,\n },\n errorMessage: t('sales.documents.payments.errorDelete', 'Failed to delete payment.'),\n })\n )\n if (result.ok) {\n onTotalsChange?.()\n flash(t('sales.documents.payments.deleted', 'Payment deleted.'), 'success')\n await loadPayments()\n emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: 'order' })\n }\n } catch (err) {\n if (handleSectionMutationError(err, t, () => void loadPayments())) {\n return\n }\n logger.error('sales.payments.delete', { err })\n flash(t('sales.documents.payments.errorDelete', 'Failed to delete payment.'), 'error')\n }\n },\n [documentUpdatedAt, loadPayments, onTotalsChange, orderId, resolvedOrganizationId, resolvedTenantId, t]\n )\n\n React.useEffect(() => {\n if (!onActionChange) return\n onActionChange({\n label: addActionLabel,\n onClick: openCreate,\n disabled: false,\n })\n return () => onActionChange(null)\n }, [addActionLabel, onActionChange, openCreate])\n\n const columns = React.useMemo<ColumnDef<PaymentRow>[]>(\n () => [\n {\n accessorKey: 'paymentReference',\n header: t('sales.documents.payments.reference', 'Reference'),\n cell: ({ row }) => row.original.paymentReference || '\u2014',\n },\n {\n accessorKey: 'paymentMethodName',\n header: t('sales.documents.payments.method', 'Method'),\n cell: ({ row }) => row.original.paymentMethodName ?? '\u2014',\n },\n {\n // Injected columns are placed against `ColumnDef.id` before the table is\n // built, so an accessor-derived id is not yet available: the gateway\n // status widget anchors on this explicit id.\n id: 'status',\n accessorKey: 'status',\n header: t('sales.documents.payments.status', 'Status'),\n cell: ({ row }) => row.original.statusLabel ?? row.original.status ?? '\u2014',\n },\n {\n accessorKey: 'amount',\n header: t('sales.documents.payments.amount', 'Amount'),\n cell: ({ row }) => formatMoney(row.original.amount, row.original.currencyCode ?? currencyCode, locale),\n },\n {\n accessorKey: 'receivedAt',\n header: t('sales.documents.payments.receivedAt', 'Received'),\n // `receivedAt` is written from a date input (`PaymentDialog`), coerced with\n // `z.coerce.date()` and stored as UTC midnight, so its day must be read in UTC.\n // Reading it locally names the previous day west of UTC \u2014 and disagrees with the\n // Edit dialog, which seeds from `receivedAt.slice(0, 10)`, i.e. the UTC day.\n cell: ({ row }) => formatDisplayDate(toUtcDateInputValue(row.original.receivedAt), locale) ?? '\u2014',\n },\n {\n accessorKey: 'createdAt',\n header: t('sales.documents.payments.createdAt', 'Created'),\n cell: ({ row }) => formatDisplayDateTime(row.original.createdAt, locale) ?? '\u2014',\n meta: {\n tooltipContent: (row: PaymentRow) => formatDisplayDateTime(row.createdAt, locale) ?? undefined,\n },\n },\n {\n id: 'actions',\n header: '',\n cell: ({ row }) => {\n return (\n <RowActions\n items={[\n { id: 'edit', label: editActionLabel, onSelect: () => openEditPayment(row.original) },\n {\n id: 'delete',\n label: deleteActionLabel,\n destructive: true,\n onSelect: () => void handleDelete(row.original),\n },\n ]}\n />\n )\n },\n },\n ],\n [currencyCode, deleteActionLabel, editActionLabel, handleDelete, locale, openEditPayment, t]\n )\n\n if (loading) {\n return (\n <LoadingMessage\n label={t('sales.documents.payments.loading', 'Loading payments\u2026')}\n className=\"border-0 bg-transparent p-0 py-8 justify-center\"\n />\n )\n }\n\n if (error) {\n return (\n <ErrorMessage\n label={error}\n action={\n <Button variant=\"outline\" size=\"sm\" onClick={() => void loadPayments()}>\n {t('sales.documents.payments.retry', 'Retry')}\n </Button>\n }\n />\n )\n }\n\n return (\n <div className=\"space-y-4\">\n {payments.length ? (\n <DataTable<PaymentRow>\n columns={columns}\n data={payments}\n onRowClick={openEditPayment}\n extensionTableId={extensionPoints.hosts.paymentsTable.tableId}\n />\n ) : (\n <TabEmptyState\n title={t('sales.documents.payments.emptyTitle', 'No payments yet.')}\n description={t(\n 'sales.documents.payments.emptyDescription',\n 'Track received payments to keep outstanding balances up to date.'\n )}\n action={{\n label: addActionLabel,\n onClick: openCreate,\n icon: <Plus className=\"h-4 w-4\" aria-hidden />,\n disabled: loading,\n }}\n />\n )}\n\n <PaymentDialog\n open={dialogOpen}\n onOpenChange={handleDialogChange}\n mode={editingPayment ? 'edit' : 'create'}\n payment={editingPayment}\n currencyCode={editingPayment?.currencyCode ?? currencyCode}\n orderId={orderId}\n organizationId={resolvedOrganizationId}\n tenantId={resolvedTenantId}\n documentUpdatedAt={documentUpdatedAt ?? null}\n onSaved={handlePaymentSaved}\n />\n </div>\n )\n}\n"],
5
+ "mappings": ";AA2TY,cAyCR,YAzCQ;AAzTZ,YAAY,WAAW;AAEvB,SAAS,iBAAiB;AAC1B,SAAS,gBAAgB,cAAc,qBAAqB;AAC5D,SAAS,SAAS,mCAAmC;AACrD,SAAS,iCAAiC;AAC1C,SAAS,kBAAkB;AAC3B,SAAS,4BAA4B,wBAAwB;AAE7D,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AACvB,SAAS,mBAAmB,uBAAuB,2BAA2B;AAC9E,SAAS,aAAa;AACtB,SAAS,kCAAkC;AAC3C,SAAS,MAAM,iBAAiB;AAChC,SAAS,sCAAsC;AAC/C,SAAS,uBAAuB;AAChC,SAAS,qBAA+D;AACxE,SAAS,gCAAgC;AACzC,SAAS,YAAY;AACrB,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,OAAO;AA8BnC,SAAS,gBAAgB,OAAwB;AAC/C,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO;AAChE,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,QAAQ;AACpD,UAAM,SAAS,OAAO,KAAK;AAC3B,QAAI,CAAC,OAAO,MAAM,MAAM,EAAG,QAAO;AAAA,EACpC;AACA,SAAO;AACT;AAEA,SAAS,YAAY,OAAe,UAAqC,QAAyB;AAChG,MAAI,CAAC,YAAY,SAAS,KAAK,EAAE,WAAW,EAAG,QAAO,MAAM,QAAQ,CAAC;AACrE,MAAI;AACF,WAAO,IAAI,KAAK,aAAa,QAAQ,EAAE,OAAO,YAAY,SAAS,CAAC,EAAE,OAAO,KAAK;AAAA,EACpF,QAAQ;AACN,WAAO,GAAG,SAAS,YAAY,CAAC,IAAI,MAAM,QAAQ,CAAC,CAAC;AAAA,EACtD;AACF;AAEO,SAAS,6BAA6B;AAAA,EAC3C;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAsC;AACpC,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,UAAU;AACzB,QAAM,EAAE,gBAAgB,SAAS,IAAI,2BAA2B;AAChE,QAAM,yBAAyB,gBAAgB,kBAAkB;AACjE,QAAM,mBAAmB,mBAAmB,YAAY;AACxD,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAAuB,CAAC,CAAC;AAC/D,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAS,KAAK;AAClD,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAwB,IAAI;AAC5D,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,KAAK;AACxD,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,MAAM,SAAiC,IAAI;AACvF,QAAM,sBAAsB,MAAM,OAAgC,gBAAgB;AAElF,QAAM,UAAU,MAAM;AACpB,wBAAoB,UAAU;AAAA,EAChC,GAAG,CAAC,gBAAgB,CAAC;AAErB,QAAM,iBAAiB,EAAE,gCAAgC,aAAa;AACtE,QAAM,kBAAkB,EAAE,iCAAiC,cAAc;AACzE,QAAM,oBAAoB,EAAE,mCAAmC,gBAAgB;AAE/E,QAAM,eAAe,MAAM,YAAY,YAAY;AACjD,eAAW,IAAI;AACf,aAAS,IAAI;AACb,QAAI;AACF,YAAM,SAAS,IAAI,gBAAgB,EAAE,MAAM,KAAK,UAAU,OAAO,QAAQ,CAAC;AAC1E,YAAM,WAAW,MAAM;AAAA,QACrB,uBAAuB,OAAO,SAAS,CAAC;AAAA,QACxC;AAAA,QACA,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,MAC5B;AACA,UAAI,SAAS,MAAM,MAAM,QAAQ,SAAS,QAAQ,KAAK,GAAG;AACxD,cAAM,SAAS,SAAS,OAAO,MAAM,QAAoB,CAAC,SAAS;AACjE,cAAI,OAAO,KAAK,OAAO,SAAU,QAAO,CAAC;AACzC,gBAAM,eACJ,QAAQ,OAAO,SAAS,WACpB,yBAAyB,IAA+B,IACxD,CAAC;AACP,gBAAM,SAAqB;AAAA,YACzB,IAAI,KAAK;AAAA,YACT,WAAW,iBAAiB,IAAI;AAAA,YAChC,kBAAkB,OAAO,KAAK,sBAAsB,WAAW,KAAK,oBAAoB;AAAA,YACxF,iBAAiB,OAAO,KAAK,sBAAsB,WAAW,KAAK,oBAAoB;AAAA,YACvF,mBACE,OAAO,KAAK,wBAAwB,WAChC,KAAK,sBACL,OAAO,KAAK,wBAAwB,WAClC,KAAK,sBACL;AAAA,YACR,QAAQ,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS;AAAA,YACxD,eACE,OAAQ,KAAa,oBAAoB,WACpC,KAAa,kBACd,OAAQ,KAAa,kBAAkB,WACpC,KAAa,gBACd;AAAA,YACR,aACE,OAAQ,KAAa,iBAAiB,WACjC,KAAa,eACd,OAAQ,KAAa,gBAAgB,WAClC,KAAa,cACd;AAAA,YACR,QAAQ,gBAAgB,KAAK,MAAM;AAAA,YACnC,cACE,OAAO,KAAK,kBAAkB,WAC1B,KAAK,gBACL,OAAO,iBAAiB,WACtB,eACA;AAAA,YACR,YAAY,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AAAA,YACtE,WAAW,OAAO,KAAK,eAAe,WAAW,KAAK,aAAa;AAAA,YACnE,cAAc,OAAO,KAAK,YAAY,EAAE,SAAS,eAAe;AAAA,YAChE,kBACE,OAAQ,MAAc,wBAAwB,WACzC,KAAa,sBACd,OAAQ,MAAc,qBAAqB,WACxC,KAAa,mBACd;AAAA,UACV;AACA,iBAAO,CAAC,MAAM;AAAA,QAChB,CAAC;AACD,oBAAY,MAAM;AAClB,4BAAoB,UAAU,MAAM;AAAA,MACtC,OAAO;AACL,oBAAY,CAAC,CAAC;AACd,4BAAoB,UAAU,CAAC,CAAC;AAAA,MAClC;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,MAAM,uBAAuB,EAAE,IAAI,CAAC;AAC3C,eAAS,EAAE,sCAAsC,0BAA0B,CAAC;AAC5E,0BAAoB,UAAU,CAAC,CAAC;AAAA,IAClC,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,cAAc,SAAS,CAAC,CAAC;AAE7B,QAAM,UAAU,MAAM;AACpB,SAAK,aAAa;AAAA,EACpB,GAAG,CAAC,YAAY,CAAC;AAEjB,QAAM,aAAa,MAAM,YAAY,MAAM;AACzC,sBAAkB,IAAI;AACtB,kBAAc,IAAI;AAAA,EACpB,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB,MAAM,YAAY,CAAC,aAAsB;AAClE,kBAAc,QAAQ;AACtB,QAAI,CAAC,UAAU;AACb,wBAAkB,IAAI;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAkB,MAAM;AAAA,IAC5B,CAAC,WAAuB;AACtB,wBAAkB;AAAA,QAChB,IAAI,OAAO;AAAA,QACX,WAAW,OAAO,aAAa;AAAA,QAC/B,QAAQ,OAAO,UAAU;AAAA,QACzB,iBAAiB,OAAO,mBAAmB;AAAA,QAC3C,kBAAkB,OAAO,oBAAoB;AAAA,QAC7C,YAAY,OAAO,aAAa,OAAO,WAAW,MAAM,GAAG,EAAE,IAAI;AAAA,QACjE,cAAc,OAAO,gBAAgB,gBAAgB;AAAA,QACrD,eAAe,OAAO,iBAAiB;AAAA,QACvC,cAAc,OAAO,gBAAgB;AAAA,QACrC,kBAAkB,OAAO,oBAAoB;AAAA,MAC/C,CAAC;AACD,oBAAc,IAAI;AAAA,IACpB;AAAA,IACA,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,qBAAqB,MAAM;AAAA,IAC/B,OAAO,YAAmC;AACxC,uBAAiB;AACjB,YAAM,aAAa;AACnB,qCAA+B,EAAE,YAAY,SAAS,MAAM,QAAQ,CAAC;AACrE,yBAAmB,KAAK;AAAA,IAC1B;AAAA,IACA,CAAC,oBAAoB,cAAc,gBAAgB,OAAO;AAAA,EAC5D;AAEA,QAAM,eAAe,MAAM;AAAA,IACzB,OAAO,QAAoB;AACzB,UAAI;AACF,cAAM,SAAS,MAAM;AAAA;AAAA;AAAA,UAGnB,0BAA0B,qBAAqB,MAAS;AAAA,UACxD,MACE,WAAmD,kBAAkB;AAAA,YACnE,MAAM;AAAA,cACJ,IAAI,IAAI;AAAA,cACR;AAAA,cACA,gBAAgB,0BAA0B;AAAA,cAC1C,UAAU,oBAAoB;AAAA,YAChC;AAAA,YACA,cAAc,EAAE,wCAAwC,2BAA2B;AAAA,UACrF,CAAC;AAAA,QACL;AACA,YAAI,OAAO,IAAI;AACb,2BAAiB;AACjB,gBAAM,EAAE,oCAAoC,kBAAkB,GAAG,SAAS;AAC1E,gBAAM,aAAa;AACnB,yCAA+B,EAAE,YAAY,SAAS,MAAM,QAAQ,CAAC;AAAA,QACvE;AAAA,MACF,SAAS,KAAK;AACZ,YAAI,2BAA2B,KAAK,GAAG,MAAM,KAAK,aAAa,CAAC,GAAG;AACjE;AAAA,QACF;AACA,eAAO,MAAM,yBAAyB,EAAE,IAAI,CAAC;AAC7C,cAAM,EAAE,wCAAwC,2BAA2B,GAAG,OAAO;AAAA,MACvF;AAAA,IACF;AAAA,IACA,CAAC,mBAAmB,cAAc,gBAAgB,SAAS,wBAAwB,kBAAkB,CAAC;AAAA,EACxG;AAEA,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,eAAgB;AACrB,mBAAe;AAAA,MACb,OAAO;AAAA,MACP,SAAS;AAAA,MACT,UAAU;AAAA,IACZ,CAAC;AACD,WAAO,MAAM,eAAe,IAAI;AAAA,EAClC,GAAG,CAAC,gBAAgB,gBAAgB,UAAU,CAAC;AAE/C,QAAM,UAAU,MAAM;AAAA,IACpB,MAAM;AAAA,MACJ;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,sCAAsC,WAAW;AAAA,QAC3D,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,oBAAoB;AAAA,MACtD;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,mCAAmC,QAAQ;AAAA,QACrD,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,qBAAqB;AAAA,MACvD;AAAA,MACA;AAAA;AAAA;AAAA;AAAA,QAIE,IAAI;AAAA,QACJ,aAAa;AAAA,QACb,QAAQ,EAAE,mCAAmC,QAAQ;AAAA,QACrD,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,eAAe,IAAI,SAAS,UAAU;AAAA,MACxE;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,mCAAmC,QAAQ;AAAA,QACrD,MAAM,CAAC,EAAE,IAAI,MAAM,YAAY,IAAI,SAAS,QAAQ,IAAI,SAAS,gBAAgB,cAAc,MAAM;AAAA,MACvG;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,uCAAuC,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,QAK3D,MAAM,CAAC,EAAE,IAAI,MAAM,kBAAkB,oBAAoB,IAAI,SAAS,UAAU,GAAG,MAAM,KAAK;AAAA,MAChG;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,sCAAsC,SAAS;AAAA,QACzD,MAAM,CAAC,EAAE,IAAI,MAAM,sBAAsB,IAAI,SAAS,WAAW,MAAM,KAAK;AAAA,QAC5E,MAAM;AAAA,UACJ,gBAAgB,CAAC,QAAoB,sBAAsB,IAAI,WAAW,MAAM,KAAK;AAAA,QACvF;AAAA,MACF;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,MAAM,CAAC,EAAE,IAAI,MAAM;AACjB,iBACE;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,EAAE,IAAI,QAAQ,OAAO,iBAAiB,UAAU,MAAM,gBAAgB,IAAI,QAAQ,EAAE;AAAA,gBACpF;AAAA,kBACE,IAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,aAAa;AAAA,kBACb,UAAU,MAAM,KAAK,aAAa,IAAI,QAAQ;AAAA,gBAChD;AAAA,cACF;AAAA;AAAA,UACF;AAAA,QAEJ;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,cAAc,mBAAmB,iBAAiB,cAAc,QAAQ,iBAAiB,CAAC;AAAA,EAC7F;AAEA,MAAI,SAAS;AACX,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,oCAAoC,wBAAmB;AAAA,QAChE,WAAU;AAAA;AAAA,IACZ;AAAA,EAEJ;AAEA,MAAI,OAAO;AACT,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,QACP,QACE,oBAAC,UAAO,SAAQ,WAAU,MAAK,MAAK,SAAS,MAAM,KAAK,aAAa,GAClE,YAAE,kCAAkC,OAAO,GAC9C;AAAA;AAAA,IAEJ;AAAA,EAEJ;AAEA,SACE,qBAAC,SAAI,WAAU,aACZ;AAAA,aAAS,SACR;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,kBAAkB,gBAAgB,MAAM,cAAc;AAAA;AAAA,IACxD,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,uCAAuC,kBAAkB;AAAA,QAClE,aAAa;AAAA,UACX;AAAA,UACA;AAAA,QACF;AAAA,QACA,QAAQ;AAAA,UACN,OAAO;AAAA,UACP,SAAS;AAAA,UACT,MAAM,oBAAC,QAAK,WAAU,WAAU,eAAW,MAAC;AAAA,UAC5C,UAAU;AAAA,QACZ;AAAA;AAAA,IACF;AAAA,IAGF;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,cAAc;AAAA,QACd,MAAM,iBAAiB,SAAS;AAAA,QAChC,SAAS;AAAA,QACT,cAAc,gBAAgB,gBAAgB;AAAA,QAC9C;AAAA,QACA,gBAAgB;AAAA,QAChB,UAAU;AAAA,QACV,mBAAmB,qBAAqB;AAAA,QACxC,SAAS;AAAA;AAAA,IACX;AAAA,KACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
+ import { toUtcDateInputValue } from "@open-mercato/ui/primitives/date-format";
4
5
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@open-mercato/ui/primitives/dialog";
5
6
  import { useDialogKeyHandler } from "@open-mercato/ui/hooks/useDialogKeyHandler";
6
7
  import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
@@ -9,12 +10,6 @@ import { flash } from "@open-mercato/ui/backend/FlashMessages";
9
10
  import { useT } from "@open-mercato/shared/lib/i18n/context";
10
11
  import { E } from "../../../../generated/entities.ids.generated.js";
11
12
  import { handleSectionMutationError } from "./optimisticLock.js";
12
- function toDateInputValue(value) {
13
- if (!value) return "";
14
- const date = new Date(value);
15
- if (Number.isNaN(date.getTime())) return "";
16
- return date.toISOString().slice(0, 10);
17
- }
18
13
  function ReturnEditDialog({
19
14
  open,
20
15
  returnRecord,
@@ -33,7 +28,7 @@ function ReturnEditDialog({
33
28
  updatedAt: returnRecord?.updatedAt ?? null,
34
29
  reason: returnRecord?.reason ?? "",
35
30
  notes: returnRecord?.notes ?? "",
36
- returnedAt: toDateInputValue(returnRecord?.returnedAt)
31
+ returnedAt: toUtcDateInputValue(returnRecord?.returnedAt) ?? ""
37
32
  }),
38
33
  [returnRecord]
39
34
  );
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/sales/components/documents/ReturnEditDialog.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { useDialogKeyHandler } from '@open-mercato/ui/hooks/useDialogKeyHandler'\nimport { CrudForm, type CrudField } from '@open-mercato/ui/backend/CrudForm'\nimport { updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { E } from '#generated/entities.ids.generated'\nimport { handleSectionMutationError } from './optimisticLock'\n\nexport type ReturnEditRecord = {\n id: string\n reason: string | null\n notes: string | null\n returnedAt: string | null\n updatedAt: string | null\n}\n\ntype ReturnEditFormValues = {\n id: string\n updatedAt: string | null\n reason: string\n notes: string\n returnedAt: string\n}\n\ntype ReturnEditDialogProps = {\n open: boolean\n returnRecord: ReturnEditRecord | null\n orderId: string\n organizationId: string | null\n tenantId: string | null\n onClose: () => void\n onSaved: () => Promise<void>\n}\n\nfunction toDateInputValue(value: string | null | undefined): string {\n if (!value) return ''\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return ''\n return date.toISOString().slice(0, 10)\n}\n\nexport function ReturnEditDialog({\n open,\n returnRecord,\n orderId,\n organizationId,\n tenantId,\n onClose,\n onSaved,\n}: ReturnEditDialogProps) {\n const t = useT()\n const dialogContentRef = React.useRef<HTMLDivElement | null>(null)\n\n const initialValues = React.useMemo<ReturnEditFormValues>(\n () => ({\n id: returnRecord?.id ?? '',\n // Drives CrudForm's automatic optimistic-lock header derivation.\n updatedAt: returnRecord?.updatedAt ?? null,\n reason: returnRecord?.reason ?? '',\n notes: returnRecord?.notes ?? '',\n returnedAt: toDateInputValue(returnRecord?.returnedAt),\n }),\n [returnRecord],\n )\n\n const fields = React.useMemo<CrudField[]>(\n () => [\n {\n id: 'reason',\n label: t('sales.returns.reason', 'Reason'),\n type: 'text',\n placeholder: t('sales.returns.reason.placeholder', 'Optional'),\n },\n {\n id: 'returnedAt',\n label: t('sales.returns.returnedAt', 'Returned at'),\n type: 'date',\n maxDate: new Date(),\n },\n {\n id: 'notes',\n label: t('sales.returns.notes', 'Notes'),\n type: 'textarea',\n placeholder: t('sales.returns.notes.placeholder', 'Optional'),\n },\n ],\n [t],\n )\n\n const handleSubmit = React.useCallback(\n async (values: ReturnEditFormValues) => {\n if (!returnRecord) return\n const reason = typeof values.reason === 'string' ? values.reason.trim() : ''\n const notes = typeof values.notes === 'string' ? values.notes.trim() : ''\n const returnedAt = typeof values.returnedAt === 'string' ? values.returnedAt.trim() : ''\n try {\n const result = await updateCrud(\n 'sales/returns',\n {\n id: returnRecord.id,\n orderId,\n ...(organizationId ? { organizationId } : {}),\n ...(tenantId ? { tenantId } : {}),\n reason,\n notes,\n ...(returnedAt ? { returnedAt } : {}),\n },\n {\n errorMessage: t('sales.returns.errors.update', 'Failed to update return.'),\n },\n )\n if (result.ok) {\n flash(t('sales.returns.updated', 'Return updated.'), 'success')\n onClose()\n await onSaved()\n }\n } catch (err) {\n if (handleSectionMutationError(err, t, () => void onSaved())) {\n onClose()\n return\n }\n throw err\n }\n },\n [onClose, onSaved, orderId, organizationId, returnRecord, t, tenantId],\n )\n\n const handleSubmitForm = React.useCallback(\n () => dialogContentRef.current?.querySelector('form')?.requestSubmit(),\n [],\n )\n const handleKeyDown = useDialogKeyHandler({\n onConfirm: handleSubmitForm,\n onCancel: onClose,\n })\n\n return (\n <Dialog open={open} onOpenChange={(next) => (!next ? onClose() : undefined)}>\n <DialogContent className=\"max-w-2xl\" onKeyDown={handleKeyDown} ref={dialogContentRef}>\n <DialogHeader>\n <DialogTitle>{t('sales.returns.edit.title', 'Edit return')}</DialogTitle>\n </DialogHeader>\n <CrudForm<ReturnEditFormValues>\n embedded\n fields={fields}\n entityId={E.sales.sales_return}\n initialValues={initialValues}\n submitLabel={t('sales.returns.edit.submit', 'Save changes')}\n onSubmit={handleSubmit}\n />\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { toUtcDateInputValue } from '@open-mercato/ui/primitives/date-format'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { useDialogKeyHandler } from '@open-mercato/ui/hooks/useDialogKeyHandler'\nimport { CrudForm, type CrudField } from '@open-mercato/ui/backend/CrudForm'\nimport { updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { E } from '#generated/entities.ids.generated'\nimport { handleSectionMutationError } from './optimisticLock'\n\nexport type ReturnEditRecord = {\n id: string\n reason: string | null\n notes: string | null\n returnedAt: string | null\n updatedAt: string | null\n}\n\ntype ReturnEditFormValues = {\n id: string\n updatedAt: string | null\n reason: string\n notes: string\n returnedAt: string\n}\n\ntype ReturnEditDialogProps = {\n open: boolean\n returnRecord: ReturnEditRecord | null\n orderId: string\n organizationId: string | null\n tenantId: string | null\n onClose: () => void\n onSaved: () => Promise<void>\n}\n\nexport function ReturnEditDialog({\n open,\n returnRecord,\n orderId,\n organizationId,\n tenantId,\n onClose,\n onSaved,\n}: ReturnEditDialogProps) {\n const t = useT()\n const dialogContentRef = React.useRef<HTMLDivElement | null>(null)\n\n const initialValues = React.useMemo<ReturnEditFormValues>(\n () => ({\n id: returnRecord?.id ?? '',\n // Drives CrudForm's automatic optimistic-lock header derivation.\n updatedAt: returnRecord?.updatedAt ?? null,\n reason: returnRecord?.reason ?? '',\n notes: returnRecord?.notes ?? '',\n returnedAt: toUtcDateInputValue(returnRecord?.returnedAt) ?? '',\n }),\n [returnRecord],\n )\n\n const fields = React.useMemo<CrudField[]>(\n () => [\n {\n id: 'reason',\n label: t('sales.returns.reason', 'Reason'),\n type: 'text',\n placeholder: t('sales.returns.reason.placeholder', 'Optional'),\n },\n {\n id: 'returnedAt',\n label: t('sales.returns.returnedAt', 'Returned at'),\n type: 'date',\n maxDate: new Date(),\n },\n {\n id: 'notes',\n label: t('sales.returns.notes', 'Notes'),\n type: 'textarea',\n placeholder: t('sales.returns.notes.placeholder', 'Optional'),\n },\n ],\n [t],\n )\n\n const handleSubmit = React.useCallback(\n async (values: ReturnEditFormValues) => {\n if (!returnRecord) return\n const reason = typeof values.reason === 'string' ? values.reason.trim() : ''\n const notes = typeof values.notes === 'string' ? values.notes.trim() : ''\n const returnedAt = typeof values.returnedAt === 'string' ? values.returnedAt.trim() : ''\n try {\n const result = await updateCrud(\n 'sales/returns',\n {\n id: returnRecord.id,\n orderId,\n ...(organizationId ? { organizationId } : {}),\n ...(tenantId ? { tenantId } : {}),\n reason,\n notes,\n ...(returnedAt ? { returnedAt } : {}),\n },\n {\n errorMessage: t('sales.returns.errors.update', 'Failed to update return.'),\n },\n )\n if (result.ok) {\n flash(t('sales.returns.updated', 'Return updated.'), 'success')\n onClose()\n await onSaved()\n }\n } catch (err) {\n if (handleSectionMutationError(err, t, () => void onSaved())) {\n onClose()\n return\n }\n throw err\n }\n },\n [onClose, onSaved, orderId, organizationId, returnRecord, t, tenantId],\n )\n\n const handleSubmitForm = React.useCallback(\n () => dialogContentRef.current?.querySelector('form')?.requestSubmit(),\n [],\n )\n const handleKeyDown = useDialogKeyHandler({\n onConfirm: handleSubmitForm,\n onCancel: onClose,\n })\n\n return (\n <Dialog open={open} onOpenChange={(next) => (!next ? onClose() : undefined)}>\n <DialogContent className=\"max-w-2xl\" onKeyDown={handleKeyDown} ref={dialogContentRef}>\n <DialogHeader>\n <DialogTitle>{t('sales.returns.edit.title', 'Edit return')}</DialogTitle>\n </DialogHeader>\n <CrudForm<ReturnEditFormValues>\n embedded\n fields={fields}\n entityId={E.sales.sales_return}\n initialValues={initialValues}\n submitLabel={t('sales.returns.edit.submit', 'Save changes')}\n onSubmit={handleSubmit}\n />\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
+ import { formatDisplayDate, toUtcDateInputValue } from "@open-mercato/ui/primitives/date-format";
4
5
  import { Undo2, Plus } from "lucide-react";
5
6
  import { Button } from "@open-mercato/ui/primitives/button";
6
7
  import { Badge } from "@open-mercato/ui/primitives/badge";
@@ -22,12 +23,6 @@ import { formatMoney, normalizeNumber } from "./lineItemUtils.js";
22
23
  import { ReturnDialog } from "./ReturnDialog.js";
23
24
  import { ReturnEditDialog } from "./ReturnEditDialog.js";
24
25
  import { handleSectionMutationError, readRowUpdatedAt, rowOptimisticVersion } from "./optimisticLock.js";
25
- function formatDisplayDate(value, locale) {
26
- if (!value) return null;
27
- const date = new Date(value);
28
- if (Number.isNaN(date.getTime())) return null;
29
- return new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(date);
30
- }
31
26
  function SalesReturnsSection({ orderId, currencyCode, documentUpdatedAt }) {
32
27
  const t = useT();
33
28
  const locale = useLocale();
@@ -239,7 +234,7 @@ function SalesReturnsSection({ orderId, currencyCode, documentUpdatedAt }) {
239
234
  /* @__PURE__ */ jsx("div", { className: "truncate text-sm font-medium", children: ret.returnNumber }),
240
235
  ret.status ? /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: ret.status }) : null
241
236
  ] }) }),
242
- /* @__PURE__ */ jsx("div", { className: "whitespace-nowrap text-right text-sm text-muted-foreground", children: formatDisplayDate(ret.returnedAt, locale) ?? t("sales.returns.notSet", "Not set") }),
237
+ /* @__PURE__ */ jsx("div", { className: "whitespace-nowrap text-right text-sm text-muted-foreground", children: formatDisplayDate(toUtcDateInputValue(ret.returnedAt), locale) ?? t("sales.returns.notSet", "Not set") }),
243
238
  /* @__PURE__ */ jsx("div", { className: "whitespace-nowrap text-right text-sm font-medium", children: formatMoney(ret.total, currencyCode ?? null, locale) }),
244
239
  /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
245
240
  RowActions,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/sales/components/documents/ReturnsSection.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Undo2, Plus } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { ErrorMessage, LoadingMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT, useLocale } from '@open-mercato/shared/lib/i18n/context'\nimport {\n emitSalesDocumentTotalsRefresh,\n subscribeSalesDocumentTotalsRefresh,\n} from '@open-mercato/core/modules/sales/lib/frontend/documentTotalsEvents'\nimport { sumShippedQuantityByLine } from '@open-mercato/core/modules/sales/lib/returnQuantity'\nimport { formatMoney, normalizeNumber } from './lineItemUtils'\nimport { ReturnDialog, type ReturnOrderLine } from './ReturnDialog'\nimport { ReturnEditDialog, type ReturnEditRecord } from './ReturnEditDialog'\nimport { handleSectionMutationError, readRowUpdatedAt, rowOptimisticVersion } from './optimisticLock'\n\ntype ReturnRow = {\n id: string\n returnNumber: string\n status: string | null\n reason: string | null\n notes: string | null\n returnedAt: string | null\n updatedAt: string | null\n totalNetAmount: number | null\n totalGrossAmount: number | null\n}\n\ntype SalesReturnsSectionProps = {\n orderId: string\n currencyCode?: string | null\n documentUpdatedAt?: string | null\n}\n\nexport function formatDisplayDate(value: string | null | undefined, locale?: string): string | null {\n if (!value) return null\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return null\n return new Intl.DateTimeFormat(locale, { dateStyle: 'medium' }).format(date)\n}\n\nexport function SalesReturnsSection({ orderId, currencyCode, documentUpdatedAt }: SalesReturnsSectionProps) {\n const t = useT()\n const locale = useLocale()\n const { organizationId, tenantId } = useOrganizationScopeDetail()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [returns, setReturns] = React.useState<ReturnRow[]>([])\n const [lines, setLines] = React.useState<ReturnOrderLine[]>([])\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const [dialogOpen, setDialogOpen] = React.useState(false)\n const [editRecord, setEditRecord] = React.useState<ReturnEditRecord | null>(null)\n\n const loadLines = React.useCallback(async () => {\n const params = new URLSearchParams({ page: '1', pageSize: '100', orderId })\n const shipmentParams = new URLSearchParams({ page: '1', pageSize: '200', orderId })\n const [response, shipmentsResponse] = await Promise.all([\n apiCall<{ items?: Array<Record<string, unknown>> }>(\n `/api/sales/order-lines?${params.toString()}`,\n undefined,\n { fallback: { items: [] } },\n ),\n apiCall<{ items?: Array<Record<string, unknown>> }>(\n `/api/sales/shipments?${shipmentParams.toString()}`,\n undefined,\n { fallback: { items: [] } },\n ),\n ])\n const shippedByLine = sumShippedQuantityByLine(\n Array.isArray(shipmentsResponse.result?.items) ? shipmentsResponse.result?.items : [],\n )\n const items = Array.isArray(response.result?.items) ? response.result?.items ?? [] : []\n const mapped: ReturnOrderLine[] = items\n .map((item): ReturnOrderLine | null => {\n const map = item as Record<string, unknown>\n const id = typeof map.id === 'string' ? map.id : null\n if (!id) return null\n const snapshot = map['catalog_snapshot']\n const snapshotName =\n snapshot && typeof snapshot === 'object' && !Array.isArray(snapshot)\n ? (snapshot as Record<string, unknown>)['name']\n : null\n const name =\n typeof map.name === 'string'\n ? map.name\n : typeof snapshotName === 'string'\n ? snapshotName\n : null\n const lineNumber =\n typeof map['line_number'] === 'number'\n ? (map['line_number'] as number)\n : typeof map.lineNumber === 'number'\n ? (map.lineNumber as number)\n : null\n const quantity =\n typeof map.quantity === 'number'\n ? (map.quantity as number)\n : typeof map.quantity === 'string'\n ? Number(map.quantity)\n : 0\n const returnedQuantity =\n typeof map['returned_quantity'] === 'number'\n ? (map['returned_quantity'] as number)\n : typeof map.returnedQuantity === 'number'\n ? (map.returnedQuantity as number)\n : typeof map['returned_quantity'] === 'string'\n ? Number(map['returned_quantity'])\n : typeof map.returnedQuantity === 'string'\n ? Number(map.returnedQuantity)\n : 0\n return {\n id,\n title: name ?? id,\n lineNumber,\n quantity: Number.isFinite(quantity) ? quantity : 0,\n returnedQuantity: Number.isFinite(returnedQuantity) ? returnedQuantity : 0,\n shippedQuantity: shippedByLine.get(id) ?? 0,\n }\n })\n .filter((entry): entry is ReturnOrderLine => Boolean(entry?.id))\n setLines(mapped)\n }, [orderId])\n\n const loadReturns = React.useCallback(async () => {\n setLoading(true)\n setError(null)\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '100', orderId })\n const response = await apiCall<{ items?: Array<Record<string, unknown>> }>(\n `/api/sales/returns?${params.toString()}`,\n undefined,\n { fallback: { items: [] } },\n )\n const items = Array.isArray(response.result?.items) ? response.result?.items ?? [] : []\n const mapped: ReturnRow[] = items\n .map((item) => {\n const map = item as Record<string, unknown>\n const id = typeof map.id === 'string' ? map.id : null\n if (!id) return null\n const returnNumber =\n typeof map['return_number'] === 'string'\n ? (map['return_number'] as string)\n : typeof map.returnNumber === 'string'\n ? (map.returnNumber as string)\n : id\n const returnedAt =\n typeof map['returned_at'] === 'string'\n ? (map['returned_at'] as string)\n : typeof map.returnedAt === 'string'\n ? (map.returnedAt as string)\n : null\n const totalNetAmount =\n typeof map['total_net_amount'] === 'number'\n ? (map['total_net_amount'] as number)\n : typeof map.totalNetAmount === 'number'\n ? (map.totalNetAmount as number)\n : null\n const totalGrossAmount =\n typeof map['total_gross_amount'] === 'number'\n ? (map['total_gross_amount'] as number)\n : typeof map.totalGrossAmount === 'number'\n ? (map.totalGrossAmount as number)\n : null\n const reason =\n typeof map.reason === 'string' ? (map.reason as string) : null\n const notes =\n typeof map.notes === 'string' ? (map.notes as string) : null\n return {\n id,\n returnNumber,\n status: typeof map.status === 'string' ? (map.status as string) : null,\n reason,\n notes,\n returnedAt,\n updatedAt: readRowUpdatedAt(map),\n totalNetAmount,\n totalGrossAmount,\n }\n })\n .filter((entry): entry is ReturnRow => Boolean(entry?.id))\n setReturns(mapped)\n await loadLines()\n } catch {\n setError(t('sales.returns.errors.load', 'Failed to load returns.'))\n } finally {\n setLoading(false)\n }\n }, [loadLines, orderId, t])\n\n React.useEffect(() => {\n loadReturns()\n }, [loadReturns])\n\n React.useEffect(() => {\n return subscribeSalesDocumentTotalsRefresh((detail) => {\n if (detail.documentId !== orderId) return\n loadReturns()\n })\n }, [loadReturns, orderId])\n\n const emptyState = React.useMemo(\n () => ({\n title: t('sales.returns.empty.title', 'No returns yet.'),\n description: t('sales.returns.empty.description', 'Create a return to generate credit adjustments for returned items.'),\n }),\n [t],\n )\n\n const rows = React.useMemo(() => {\n return returns.map((ret) => {\n const total = normalizeNumber(ret.totalGrossAmount ?? ret.totalNetAmount ?? 0, 0)\n return {\n ...ret,\n total,\n }\n })\n }, [returns])\n\n const handleEdit = React.useCallback((row: ReturnRow) => {\n setEditRecord({\n id: row.id,\n reason: row.reason,\n notes: row.notes,\n returnedAt: row.returnedAt,\n updatedAt: row.updatedAt,\n })\n }, [])\n\n const handleDelete = React.useCallback(\n async (row: ReturnRow) => {\n const confirmed = await confirm({\n title: t('sales.returns.confirmDelete', 'Delete this return?'),\n description: t(\n 'sales.returns.confirmDelete.description',\n 'This reverses the returned quantities and the related credit adjustments.',\n ),\n variant: 'destructive',\n })\n if (!confirmed) return\n try {\n const result = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(rowOptimisticVersion(row)),\n () =>\n deleteCrud('sales/returns', {\n body: {\n id: row.id,\n orderId,\n ...(organizationId ? { organizationId } : {}),\n ...(tenantId ? { tenantId } : {}),\n },\n errorMessage: t('sales.returns.errors.delete', 'Failed to delete return.'),\n }),\n )\n if (result.ok) {\n emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: 'order' })\n await loadReturns()\n }\n } catch (err) {\n if (handleSectionMutationError(err, t, () => void loadReturns())) return\n flash(t('sales.returns.errors.delete', 'Failed to delete return.'), 'error')\n }\n },\n [confirm, loadReturns, orderId, organizationId, tenantId, t],\n )\n\n if (loading) return <LoadingMessage label={t('sales.returns.loading', 'Loading returns\u2026')} />\n if (error) return <ErrorMessage label={error} />\n\n if (!rows.length) {\n return (\n <div className=\"space-y-4\">\n <TabEmptyState\n title={emptyState.title}\n description={emptyState.description}\n action={{\n label: t('sales.returns.create', 'Create return'),\n icon: <Plus className=\"mr-2 h-4 w-4\" aria-hidden />,\n onClick: () => setDialogOpen(true),\n }}\n />\n <ReturnDialog\n open={dialogOpen}\n orderId={orderId}\n lines={lines}\n documentUpdatedAt={documentUpdatedAt}\n onClose={() => setDialogOpen(false)}\n onSaved={async () => {\n emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: 'order' })\n await loadReturns()\n }}\n />\n </div>\n )\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-end\">\n <Button type=\"button\" onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-2 h-4 w-4\" aria-hidden />\n {t('sales.returns.create', 'Create return')}\n </Button>\n </div>\n\n <div className=\"overflow-hidden rounded-md border\">\n <div className=\"grid grid-cols-[1fr_auto_auto_auto] gap-3 border-b bg-muted/30 px-4 py-2 text-xs font-medium text-muted-foreground\">\n <div>{t('sales.returns.returnNumber', 'Return')}</div>\n <div className=\"text-right\">{t('sales.returns.returnedAt', 'Returned at')}</div>\n <div className=\"text-right\">{t('sales.returns.total', 'Total')}</div>\n <div className=\"sr-only\">{t('sales.returns.actions', 'Actions')}</div>\n </div>\n <div className=\"divide-y\">\n {rows.map((ret) => (\n <div key={ret.id} className=\"grid grid-cols-[1fr_auto_auto_auto] items-center gap-3 px-4 py-3\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2\">\n <Undo2 className=\"h-4 w-4 text-muted-foreground\" aria-hidden />\n <div className=\"truncate text-sm font-medium\">{ret.returnNumber}</div>\n {ret.status ? <Badge variant=\"secondary\">{ret.status}</Badge> : null}\n </div>\n </div>\n <div className=\"whitespace-nowrap text-right text-sm text-muted-foreground\">\n {formatDisplayDate(ret.returnedAt, locale) ?? t('sales.returns.notSet', 'Not set')}\n </div>\n <div className=\"whitespace-nowrap text-right text-sm font-medium\">\n {formatMoney(ret.total, currencyCode ?? null, locale)}\n </div>\n <div className=\"flex justify-end\">\n <RowActions\n items={[\n {\n id: 'edit',\n label: t('ui.actions.edit', 'Edit'),\n onSelect: () => handleEdit(ret),\n },\n {\n id: 'delete',\n label: t('ui.actions.delete', 'Delete'),\n destructive: true,\n onSelect: () => void handleDelete(ret),\n },\n ]}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n\n <ReturnDialog\n open={dialogOpen}\n orderId={orderId}\n lines={lines}\n documentUpdatedAt={documentUpdatedAt}\n onClose={() => setDialogOpen(false)}\n onSaved={async () => {\n emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: 'order' })\n await loadReturns()\n }}\n />\n\n <ReturnEditDialog\n open={editRecord !== null}\n returnRecord={editRecord}\n orderId={orderId}\n organizationId={organizationId ?? null}\n tenantId={tenantId ?? null}\n onClose={() => setEditRecord(null)}\n onSaved={async () => {\n setEditRecord(null)\n emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: 'order' })\n await loadReturns()\n }}\n />\n\n {ConfirmDialogElement}\n </div>\n )\n}\n\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { formatDisplayDate, toUtcDateInputValue } from '@open-mercato/ui/primitives/date-format'\nimport { Undo2, Plus } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { ErrorMessage, LoadingMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT, useLocale } from '@open-mercato/shared/lib/i18n/context'\nimport {\n emitSalesDocumentTotalsRefresh,\n subscribeSalesDocumentTotalsRefresh,\n} from '@open-mercato/core/modules/sales/lib/frontend/documentTotalsEvents'\nimport { sumShippedQuantityByLine } from '@open-mercato/core/modules/sales/lib/returnQuantity'\nimport { formatMoney, normalizeNumber } from './lineItemUtils'\nimport { ReturnDialog, type ReturnOrderLine } from './ReturnDialog'\nimport { ReturnEditDialog, type ReturnEditRecord } from './ReturnEditDialog'\nimport { handleSectionMutationError, readRowUpdatedAt, rowOptimisticVersion } from './optimisticLock'\n\ntype ReturnRow = {\n id: string\n returnNumber: string\n status: string | null\n reason: string | null\n notes: string | null\n returnedAt: string | null\n updatedAt: string | null\n totalNetAmount: number | null\n totalGrossAmount: number | null\n}\n\ntype SalesReturnsSectionProps = {\n orderId: string\n currencyCode?: string | null\n documentUpdatedAt?: string | null\n}\n\n// One date formatter for this page rather than three with incompatible semantics.\nexport { formatDisplayDate }\n\nexport function SalesReturnsSection({ orderId, currencyCode, documentUpdatedAt }: SalesReturnsSectionProps) {\n const t = useT()\n const locale = useLocale()\n const { organizationId, tenantId } = useOrganizationScopeDetail()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [returns, setReturns] = React.useState<ReturnRow[]>([])\n const [lines, setLines] = React.useState<ReturnOrderLine[]>([])\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const [dialogOpen, setDialogOpen] = React.useState(false)\n const [editRecord, setEditRecord] = React.useState<ReturnEditRecord | null>(null)\n\n const loadLines = React.useCallback(async () => {\n const params = new URLSearchParams({ page: '1', pageSize: '100', orderId })\n const shipmentParams = new URLSearchParams({ page: '1', pageSize: '200', orderId })\n const [response, shipmentsResponse] = await Promise.all([\n apiCall<{ items?: Array<Record<string, unknown>> }>(\n `/api/sales/order-lines?${params.toString()}`,\n undefined,\n { fallback: { items: [] } },\n ),\n apiCall<{ items?: Array<Record<string, unknown>> }>(\n `/api/sales/shipments?${shipmentParams.toString()}`,\n undefined,\n { fallback: { items: [] } },\n ),\n ])\n const shippedByLine = sumShippedQuantityByLine(\n Array.isArray(shipmentsResponse.result?.items) ? shipmentsResponse.result?.items : [],\n )\n const items = Array.isArray(response.result?.items) ? response.result?.items ?? [] : []\n const mapped: ReturnOrderLine[] = items\n .map((item): ReturnOrderLine | null => {\n const map = item as Record<string, unknown>\n const id = typeof map.id === 'string' ? map.id : null\n if (!id) return null\n const snapshot = map['catalog_snapshot']\n const snapshotName =\n snapshot && typeof snapshot === 'object' && !Array.isArray(snapshot)\n ? (snapshot as Record<string, unknown>)['name']\n : null\n const name =\n typeof map.name === 'string'\n ? map.name\n : typeof snapshotName === 'string'\n ? snapshotName\n : null\n const lineNumber =\n typeof map['line_number'] === 'number'\n ? (map['line_number'] as number)\n : typeof map.lineNumber === 'number'\n ? (map.lineNumber as number)\n : null\n const quantity =\n typeof map.quantity === 'number'\n ? (map.quantity as number)\n : typeof map.quantity === 'string'\n ? Number(map.quantity)\n : 0\n const returnedQuantity =\n typeof map['returned_quantity'] === 'number'\n ? (map['returned_quantity'] as number)\n : typeof map.returnedQuantity === 'number'\n ? (map.returnedQuantity as number)\n : typeof map['returned_quantity'] === 'string'\n ? Number(map['returned_quantity'])\n : typeof map.returnedQuantity === 'string'\n ? Number(map.returnedQuantity)\n : 0\n return {\n id,\n title: name ?? id,\n lineNumber,\n quantity: Number.isFinite(quantity) ? quantity : 0,\n returnedQuantity: Number.isFinite(returnedQuantity) ? returnedQuantity : 0,\n shippedQuantity: shippedByLine.get(id) ?? 0,\n }\n })\n .filter((entry): entry is ReturnOrderLine => Boolean(entry?.id))\n setLines(mapped)\n }, [orderId])\n\n const loadReturns = React.useCallback(async () => {\n setLoading(true)\n setError(null)\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '100', orderId })\n const response = await apiCall<{ items?: Array<Record<string, unknown>> }>(\n `/api/sales/returns?${params.toString()}`,\n undefined,\n { fallback: { items: [] } },\n )\n const items = Array.isArray(response.result?.items) ? response.result?.items ?? [] : []\n const mapped: ReturnRow[] = items\n .map((item) => {\n const map = item as Record<string, unknown>\n const id = typeof map.id === 'string' ? map.id : null\n if (!id) return null\n const returnNumber =\n typeof map['return_number'] === 'string'\n ? (map['return_number'] as string)\n : typeof map.returnNumber === 'string'\n ? (map.returnNumber as string)\n : id\n const returnedAt =\n typeof map['returned_at'] === 'string'\n ? (map['returned_at'] as string)\n : typeof map.returnedAt === 'string'\n ? (map.returnedAt as string)\n : null\n const totalNetAmount =\n typeof map['total_net_amount'] === 'number'\n ? (map['total_net_amount'] as number)\n : typeof map.totalNetAmount === 'number'\n ? (map.totalNetAmount as number)\n : null\n const totalGrossAmount =\n typeof map['total_gross_amount'] === 'number'\n ? (map['total_gross_amount'] as number)\n : typeof map.totalGrossAmount === 'number'\n ? (map.totalGrossAmount as number)\n : null\n const reason =\n typeof map.reason === 'string' ? (map.reason as string) : null\n const notes =\n typeof map.notes === 'string' ? (map.notes as string) : null\n return {\n id,\n returnNumber,\n status: typeof map.status === 'string' ? (map.status as string) : null,\n reason,\n notes,\n returnedAt,\n updatedAt: readRowUpdatedAt(map),\n totalNetAmount,\n totalGrossAmount,\n }\n })\n .filter((entry): entry is ReturnRow => Boolean(entry?.id))\n setReturns(mapped)\n await loadLines()\n } catch {\n setError(t('sales.returns.errors.load', 'Failed to load returns.'))\n } finally {\n setLoading(false)\n }\n }, [loadLines, orderId, t])\n\n React.useEffect(() => {\n loadReturns()\n }, [loadReturns])\n\n React.useEffect(() => {\n return subscribeSalesDocumentTotalsRefresh((detail) => {\n if (detail.documentId !== orderId) return\n loadReturns()\n })\n }, [loadReturns, orderId])\n\n const emptyState = React.useMemo(\n () => ({\n title: t('sales.returns.empty.title', 'No returns yet.'),\n description: t('sales.returns.empty.description', 'Create a return to generate credit adjustments for returned items.'),\n }),\n [t],\n )\n\n const rows = React.useMemo(() => {\n return returns.map((ret) => {\n const total = normalizeNumber(ret.totalGrossAmount ?? ret.totalNetAmount ?? 0, 0)\n return {\n ...ret,\n total,\n }\n })\n }, [returns])\n\n const handleEdit = React.useCallback((row: ReturnRow) => {\n setEditRecord({\n id: row.id,\n reason: row.reason,\n notes: row.notes,\n returnedAt: row.returnedAt,\n updatedAt: row.updatedAt,\n })\n }, [])\n\n const handleDelete = React.useCallback(\n async (row: ReturnRow) => {\n const confirmed = await confirm({\n title: t('sales.returns.confirmDelete', 'Delete this return?'),\n description: t(\n 'sales.returns.confirmDelete.description',\n 'This reverses the returned quantities and the related credit adjustments.',\n ),\n variant: 'destructive',\n })\n if (!confirmed) return\n try {\n const result = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(rowOptimisticVersion(row)),\n () =>\n deleteCrud('sales/returns', {\n body: {\n id: row.id,\n orderId,\n ...(organizationId ? { organizationId } : {}),\n ...(tenantId ? { tenantId } : {}),\n },\n errorMessage: t('sales.returns.errors.delete', 'Failed to delete return.'),\n }),\n )\n if (result.ok) {\n emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: 'order' })\n await loadReturns()\n }\n } catch (err) {\n if (handleSectionMutationError(err, t, () => void loadReturns())) return\n flash(t('sales.returns.errors.delete', 'Failed to delete return.'), 'error')\n }\n },\n [confirm, loadReturns, orderId, organizationId, tenantId, t],\n )\n\n if (loading) return <LoadingMessage label={t('sales.returns.loading', 'Loading returns\u2026')} />\n if (error) return <ErrorMessage label={error} />\n\n if (!rows.length) {\n return (\n <div className=\"space-y-4\">\n <TabEmptyState\n title={emptyState.title}\n description={emptyState.description}\n action={{\n label: t('sales.returns.create', 'Create return'),\n icon: <Plus className=\"mr-2 h-4 w-4\" aria-hidden />,\n onClick: () => setDialogOpen(true),\n }}\n />\n <ReturnDialog\n open={dialogOpen}\n orderId={orderId}\n lines={lines}\n documentUpdatedAt={documentUpdatedAt}\n onClose={() => setDialogOpen(false)}\n onSaved={async () => {\n emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: 'order' })\n await loadReturns()\n }}\n />\n </div>\n )\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-end\">\n <Button type=\"button\" onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-2 h-4 w-4\" aria-hidden />\n {t('sales.returns.create', 'Create return')}\n </Button>\n </div>\n\n <div className=\"overflow-hidden rounded-md border\">\n <div className=\"grid grid-cols-[1fr_auto_auto_auto] gap-3 border-b bg-muted/30 px-4 py-2 text-xs font-medium text-muted-foreground\">\n <div>{t('sales.returns.returnNumber', 'Return')}</div>\n <div className=\"text-right\">{t('sales.returns.returnedAt', 'Returned at')}</div>\n <div className=\"text-right\">{t('sales.returns.total', 'Total')}</div>\n <div className=\"sr-only\">{t('sales.returns.actions', 'Actions')}</div>\n </div>\n <div className=\"divide-y\">\n {rows.map((ret) => (\n <div key={ret.id} className=\"grid grid-cols-[1fr_auto_auto_auto] items-center gap-3 px-4 py-3\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2\">\n <Undo2 className=\"h-4 w-4 text-muted-foreground\" aria-hidden />\n <div className=\"truncate text-sm font-medium\">{ret.returnNumber}</div>\n {ret.status ? <Badge variant=\"secondary\">{ret.status}</Badge> : null}\n </div>\n </div>\n <div className=\"whitespace-nowrap text-right text-sm text-muted-foreground\">\n {/* `returnedAt` is submitted as a bare `yyyy-MM-dd` by `ReturnEditDialog`, coerced by\n `z.coerce.date()` and returned via `.toISOString()`, and that dialog seeds itself\n back from the UTC day \u2014 unconditionally, however the row was written. Matching the\n dialog is the invariant, so the row cannot contradict itself west of UTC. */}\n {formatDisplayDate(toUtcDateInputValue(ret.returnedAt), locale) ?? t('sales.returns.notSet', 'Not set')}\n </div>\n <div className=\"whitespace-nowrap text-right text-sm font-medium\">\n {formatMoney(ret.total, currencyCode ?? null, locale)}\n </div>\n <div className=\"flex justify-end\">\n <RowActions\n items={[\n {\n id: 'edit',\n label: t('ui.actions.edit', 'Edit'),\n onSelect: () => handleEdit(ret),\n },\n {\n id: 'delete',\n label: t('ui.actions.delete', 'Delete'),\n destructive: true,\n onSelect: () => void handleDelete(ret),\n },\n ]}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n\n <ReturnDialog\n open={dialogOpen}\n orderId={orderId}\n lines={lines}\n documentUpdatedAt={documentUpdatedAt}\n onClose={() => setDialogOpen(false)}\n onSaved={async () => {\n emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: 'order' })\n await loadReturns()\n }}\n />\n\n <ReturnEditDialog\n open={editRecord !== null}\n returnRecord={editRecord}\n orderId={orderId}\n organizationId={organizationId ?? null}\n tenantId={tenantId ?? null}\n onClose={() => setEditRecord(null)}\n onSaved={async () => {\n setEditRecord(null)\n emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: 'order' })\n await loadReturns()\n }}\n />\n\n {ConfirmDialogElement}\n </div>\n )\n}\n\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
+ import { formatDisplayDate, toUtcDateInputValue } from "@open-mercato/ui/primitives/date-format";
4
5
  import { Pencil, Plus, Trash2, Truck } from "lucide-react";
5
6
  import { Button } from "@open-mercato/ui/primitives/button";
6
7
  import { Badge } from "@open-mercato/ui/primitives/badge";
@@ -25,12 +26,6 @@ import { createLogger } from "@open-mercato/shared/lib/logger";
25
26
  const logger = createLogger("sales");
26
27
  const ADDRESS_SNAPSHOT_KEY = "shipmentAddressSnapshot";
27
28
  const ADDRESS_FORMAT = "line_first";
28
- function formatDisplayDate(value, locale) {
29
- if (!value) return null;
30
- const date = new Date(value);
31
- if (Number.isNaN(date.getTime())) return null;
32
- return new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(date);
33
- }
34
29
  const formatShipmentAddress = (metadata) => {
35
30
  if (!metadata || typeof metadata !== "object") return null;
36
31
  const snapshot = metadata[ADDRESS_SNAPSHOT_KEY];
@@ -317,8 +312,8 @@ function SalesShipmentsSection({
317
312
  }
318
313
  }
319
314
  ) : /* @__PURE__ */ jsx("div", { className: "grid gap-3 md:grid-cols-2", children: shipments.map((shipment) => {
320
- const shippedAt = formatDisplayDate(shipment.shippedAt, locale);
321
- const deliveredAt = formatDisplayDate(shipment.deliveredAt, locale);
315
+ const shippedAt = formatDisplayDate(toUtcDateInputValue(shipment.shippedAt), locale);
316
+ const deliveredAt = formatDisplayDate(toUtcDateInputValue(shipment.deliveredAt), locale);
322
317
  const addressSummary = formatShipmentAddress(shipment.metadata);
323
318
  const statusLabel = shipment.statusLabel ?? shipment.status ?? t("sales.documents.shipments.statusMissing", "Status pending");
324
319
  return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-4 shadow-sm", children: [