@open-mercato/core 0.4.6-develop-af28b566dd → 0.4.6-develop-4d77832982

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 (47) hide show
  1. package/AGENTS.md +22 -0
  2. package/dist/modules/customers/backend/customers/companies/page.js +3 -3
  3. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  4. package/dist/modules/customers/backend/customers/deals/page.js +3 -3
  5. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  6. package/dist/modules/customers/backend/customers/people/page.js +3 -3
  7. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  8. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +3 -3
  9. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  10. package/dist/modules/resources/backend/resources/resource-types/page.js +2 -2
  11. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  12. package/dist/modules/resources/backend/resources/resources/page.js +3 -3
  13. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  14. package/dist/modules/sales/backend/sales/channels/page.js +3 -3
  15. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  16. package/dist/modules/sales/components/channels/offerTableUtils.js +3 -2
  17. package/dist/modules/sales/components/channels/offerTableUtils.js.map +2 -2
  18. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +3 -3
  19. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  20. package/dist/modules/staff/backend/staff/leave-requests/page.js +3 -3
  21. package/dist/modules/staff/backend/staff/leave-requests/page.js.map +2 -2
  22. package/dist/modules/staff/backend/staff/my-leave-requests/page.js +3 -3
  23. package/dist/modules/staff/backend/staff/my-leave-requests/page.js.map +2 -2
  24. package/dist/modules/staff/backend/staff/team-members/page.js +3 -3
  25. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  26. package/dist/modules/staff/backend/staff/team-roles/page.js +2 -2
  27. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  28. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +3 -3
  29. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  30. package/dist/modules/staff/backend/staff/teams/page.js +2 -2
  31. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  32. package/package.json +2 -2
  33. package/src/modules/customers/backend/customers/companies/page.tsx +3 -3
  34. package/src/modules/customers/backend/customers/deals/page.tsx +3 -3
  35. package/src/modules/customers/backend/customers/people/page.tsx +3 -3
  36. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +3 -4
  37. package/src/modules/resources/backend/resources/resource-types/page.tsx +2 -3
  38. package/src/modules/resources/backend/resources/resources/page.tsx +3 -3
  39. package/src/modules/sales/backend/sales/channels/page.tsx +3 -3
  40. package/src/modules/sales/components/channels/offerTableUtils.tsx +3 -2
  41. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +3 -3
  42. package/src/modules/staff/backend/staff/leave-requests/page.tsx +3 -3
  43. package/src/modules/staff/backend/staff/my-leave-requests/page.tsx +3 -3
  44. package/src/modules/staff/backend/staff/team-members/page.tsx +3 -3
  45. package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
  46. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +3 -4
  47. package/src/modules/staff/backend/staff/teams/page.tsx +2 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/sales/components/channels/offerTableUtils.tsx"],
4
- "sourcesContent": ["import * as React from 'react'\n\ntype Translator = (key: string, fallback: string, vars?: Record<string, unknown>) => string\n\nexport type OfferPriceRow = {\n id?: string\n priceKindId?: string | null\n priceKindCode?: string | null\n priceKindTitle?: string | null\n currencyCode?: string | null\n unitPriceNet?: string | number | null\n unitPriceGross?: string | number | null\n displayMode?: string | null\n}\n\nexport type OfferRow = {\n id: string\n channelId?: string | null\n title: string\n description: string | null\n productId: string | null\n productTitle: string | null\n productSku: string | null\n productMediaUrl: string | null\n prices: OfferPriceRow[]\n productDefaultPrices: OfferPriceRow[]\n productChannelPrice: OfferPriceRow | null\n isActive: boolean\n updatedAt: string | null\n}\n\nexport function mapOfferRow(item: Record<string, unknown>): OfferRow {\n const product = item.product && typeof item.product === 'object'\n ? item.product as Record<string, unknown>\n : null\n const prices = Array.isArray(item.prices) ? item.prices as Array<Record<string, unknown>> : []\n const productDefaultPrices = Array.isArray(item.productDefaultPrices)\n ? item.productDefaultPrices as Array<Record<string, unknown>>\n : Array.isArray(item.product_default_prices)\n ? item.product_default_prices as Array<Record<string, unknown>>\n : []\n const productChannelPriceSource =\n item.productChannelPrice && typeof item.productChannelPrice === 'object'\n ? item.productChannelPrice as Record<string, unknown>\n : item.product_channel_price && typeof item.product_channel_price === 'object'\n ? item.product_channel_price as Record<string, unknown>\n : null\n return {\n id: typeof item.id === 'string' ? item.id : '',\n channelId: typeof item.channelId === 'string'\n ? item.channelId\n : typeof item.channel_id === 'string'\n ? item.channel_id\n : null,\n title: typeof item.title === 'string' && item.title.length ? item.title : 'Untitled offer',\n description: typeof item.description === 'string' ? item.description : null,\n productId: typeof item.productId === 'string'\n ? item.productId\n : typeof item.product_id === 'string'\n ? item.product_id\n : null,\n productTitle: typeof product?.title === 'string' ? product.title : null,\n productSku: typeof product?.sku === 'string' ? product.sku : null,\n productMediaUrl:\n typeof item.defaultMediaUrl === 'string'\n ? item.defaultMediaUrl\n : typeof item.default_media_url === 'string'\n ? item.default_media_url\n : typeof product?.defaultMediaUrl === 'string'\n ? product.defaultMediaUrl\n : typeof product?.default_media_url === 'string'\n ? product.default_media_url\n : null,\n prices: prices.map(mapPriceRow),\n productDefaultPrices: productDefaultPrices.map(mapPriceRow),\n productChannelPrice: mapPriceSummary(productChannelPriceSource),\n isActive: item.isActive === true || item.is_active === true,\n updatedAt: typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null,\n }\n}\n\nexport function renderOfferPriceSummary(\n row: OfferRow,\n t: Translator,\n): React.ReactNode {\n if (!row.prices.length) {\n if (row.productDefaultPrices.length) {\n return (\n <div className=\"flex flex-wrap gap-2\">\n {row.productDefaultPrices.map((price) => renderPriceBadge(price, t, true))}\n </div>\n )\n }\n if (row.productChannelPrice) {\n return (\n <span className=\"text-xs text-muted-foreground\">\n {t('sales.channels.offers.table.channelPrice', 'Original product price {{price}}', {\n price: formatPriceValue(row.productChannelPrice),\n })}\n </span>\n )\n }\n return <span className=\"text-xs text-muted-foreground\">{t('sales.channels.offers.table.noOverrides', 'No overrides')}</span>\n }\n return (\n <div className=\"flex flex-wrap gap-2\">\n {row.prices.map((price) => renderPriceBadge(price, t))}\n </div>\n )\n}\n\nfunction mapPriceSummary(source: Record<string, unknown> | null): OfferPriceRow | null {\n if (!source) return null\n return mapPriceRow(source)\n}\n\nfunction formatPriceValue(price: OfferPriceRow | null): string {\n if (!price) return '\u2014'\n const amount = price.displayMode === 'including-tax'\n ? price.unitPriceGross ?? price.unitPriceNet\n : price.unitPriceNet ?? price.unitPriceGross\n if (amount === null || amount === undefined) return price.currencyCode ?? '\u2014'\n return `${price.currencyCode ?? ''} ${String(amount)}`\n}\n\nfunction mapPriceRow(source: Record<string, unknown>): OfferPriceRow {\n return {\n id: readString(source.id) ?? undefined,\n priceKindId: readString(source.priceKindId ?? source.price_kind_id),\n priceKindCode: readString(source.priceKindCode ?? source.price_kind_code),\n priceKindTitle: readString(source.priceKindTitle ?? source.price_kind_title),\n currencyCode: readString(source.currencyCode ?? source.currency_code),\n unitPriceNet: readPriceValue(source.unitPriceNet ?? source.unit_price_net),\n unitPriceGross: readPriceValue(source.unitPriceGross ?? source.unit_price_gross),\n displayMode: readString(source.displayMode ?? source.display_mode),\n }\n}\n\nfunction readPriceValue(value: unknown): string | number | null {\n if (typeof value === 'number' || typeof value === 'string') return value\n return null\n}\n\nfunction readString(value: unknown): string | null {\n if (typeof value === 'string') return value\n if (typeof value === 'number') return value.toString()\n return null\n}\n\nfunction renderPriceBadge(price: OfferPriceRow, t: Translator, muted?: boolean) {\n const label = price.priceKindTitle || price.priceKindCode || t('sales.channels.offers.table.price', 'Price')\n const numeric = price.displayMode === 'including-tax'\n ? price.unitPriceGross ?? price.unitPriceNet\n : price.unitPriceNet ?? price.unitPriceGross\n const amount = numeric === null || numeric === undefined ? '\u2014' : String(numeric)\n const className = ['rounded border px-2 py-1 text-xs', muted ? 'bg-muted' : null].filter(Boolean).join(' ')\n return (\n <div key={`${price.id ?? 'price'}-${label}`} className={className}>\n <div className=\"font-medium\">{label}</div>\n <div className=\"text-muted-foreground\">\n {price.currencyCode ?? ''} {amount}\n </div>\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import * as React from 'react'\nimport { withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'\n\ntype Translator = (key: string, fallback: string, vars?: Record<string, unknown>) => string\n\nexport type OfferPriceRow = {\n id?: string\n priceKindId?: string | null\n priceKindCode?: string | null\n priceKindTitle?: string | null\n currencyCode?: string | null\n unitPriceNet?: string | number | null\n unitPriceGross?: string | number | null\n displayMode?: string | null\n}\n\nexport type OfferRow = {\n id: string\n channelId?: string | null\n title: string\n description: string | null\n productId: string | null\n productTitle: string | null\n productSku: string | null\n productMediaUrl: string | null\n prices: OfferPriceRow[]\n productDefaultPrices: OfferPriceRow[]\n productChannelPrice: OfferPriceRow | null\n isActive: boolean\n updatedAt: string | null\n}\n\nexport function mapOfferRow(item: Record<string, unknown>): OfferRow {\n const product = item.product && typeof item.product === 'object'\n ? item.product as Record<string, unknown>\n : null\n const prices = Array.isArray(item.prices) ? item.prices as Array<Record<string, unknown>> : []\n const productDefaultPrices = Array.isArray(item.productDefaultPrices)\n ? item.productDefaultPrices as Array<Record<string, unknown>>\n : Array.isArray(item.product_default_prices)\n ? item.product_default_prices as Array<Record<string, unknown>>\n : []\n const productChannelPriceSource =\n item.productChannelPrice && typeof item.productChannelPrice === 'object'\n ? item.productChannelPrice as Record<string, unknown>\n : item.product_channel_price && typeof item.product_channel_price === 'object'\n ? item.product_channel_price as Record<string, unknown>\n : null\n return withDataTableNamespaces({\n id: typeof item.id === 'string' ? item.id : '',\n channelId: typeof item.channelId === 'string'\n ? item.channelId\n : typeof item.channel_id === 'string'\n ? item.channel_id\n : null,\n title: typeof item.title === 'string' && item.title.length ? item.title : 'Untitled offer',\n description: typeof item.description === 'string' ? item.description : null,\n productId: typeof item.productId === 'string'\n ? item.productId\n : typeof item.product_id === 'string'\n ? item.product_id\n : null,\n productTitle: typeof product?.title === 'string' ? product.title : null,\n productSku: typeof product?.sku === 'string' ? product.sku : null,\n productMediaUrl:\n typeof item.defaultMediaUrl === 'string'\n ? item.defaultMediaUrl\n : typeof item.default_media_url === 'string'\n ? item.default_media_url\n : typeof product?.defaultMediaUrl === 'string'\n ? product.defaultMediaUrl\n : typeof product?.default_media_url === 'string'\n ? product.default_media_url\n : null,\n prices: prices.map(mapPriceRow),\n productDefaultPrices: productDefaultPrices.map(mapPriceRow),\n productChannelPrice: mapPriceSummary(productChannelPriceSource),\n isActive: item.isActive === true || item.is_active === true,\n updatedAt: typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null,\n }, item)\n}\n\nexport function renderOfferPriceSummary(\n row: OfferRow,\n t: Translator,\n): React.ReactNode {\n if (!row.prices.length) {\n if (row.productDefaultPrices.length) {\n return (\n <div className=\"flex flex-wrap gap-2\">\n {row.productDefaultPrices.map((price) => renderPriceBadge(price, t, true))}\n </div>\n )\n }\n if (row.productChannelPrice) {\n return (\n <span className=\"text-xs text-muted-foreground\">\n {t('sales.channels.offers.table.channelPrice', 'Original product price {{price}}', {\n price: formatPriceValue(row.productChannelPrice),\n })}\n </span>\n )\n }\n return <span className=\"text-xs text-muted-foreground\">{t('sales.channels.offers.table.noOverrides', 'No overrides')}</span>\n }\n return (\n <div className=\"flex flex-wrap gap-2\">\n {row.prices.map((price) => renderPriceBadge(price, t))}\n </div>\n )\n}\n\nfunction mapPriceSummary(source: Record<string, unknown> | null): OfferPriceRow | null {\n if (!source) return null\n return mapPriceRow(source)\n}\n\nfunction formatPriceValue(price: OfferPriceRow | null): string {\n if (!price) return '\u2014'\n const amount = price.displayMode === 'including-tax'\n ? price.unitPriceGross ?? price.unitPriceNet\n : price.unitPriceNet ?? price.unitPriceGross\n if (amount === null || amount === undefined) return price.currencyCode ?? '\u2014'\n return `${price.currencyCode ?? ''} ${String(amount)}`\n}\n\nfunction mapPriceRow(source: Record<string, unknown>): OfferPriceRow {\n return {\n id: readString(source.id) ?? undefined,\n priceKindId: readString(source.priceKindId ?? source.price_kind_id),\n priceKindCode: readString(source.priceKindCode ?? source.price_kind_code),\n priceKindTitle: readString(source.priceKindTitle ?? source.price_kind_title),\n currencyCode: readString(source.currencyCode ?? source.currency_code),\n unitPriceNet: readPriceValue(source.unitPriceNet ?? source.unit_price_net),\n unitPriceGross: readPriceValue(source.unitPriceGross ?? source.unit_price_gross),\n displayMode: readString(source.displayMode ?? source.display_mode),\n }\n}\n\nfunction readPriceValue(value: unknown): string | number | null {\n if (typeof value === 'number' || typeof value === 'string') return value\n return null\n}\n\nfunction readString(value: unknown): string | null {\n if (typeof value === 'string') return value\n if (typeof value === 'number') return value.toString()\n return null\n}\n\nfunction renderPriceBadge(price: OfferPriceRow, t: Translator, muted?: boolean) {\n const label = price.priceKindTitle || price.priceKindCode || t('sales.channels.offers.table.price', 'Price')\n const numeric = price.displayMode === 'including-tax'\n ? price.unitPriceGross ?? price.unitPriceNet\n : price.unitPriceNet ?? price.unitPriceGross\n const amount = numeric === null || numeric === undefined ? '\u2014' : String(numeric)\n const className = ['rounded border px-2 py-1 text-xs', muted ? 'bg-muted' : null].filter(Boolean).join(' ')\n return (\n <div key={`${price.id ?? 'price'}-${label}`} className={className}>\n <div className=\"font-medium\">{label}</div>\n <div className=\"text-muted-foreground\">\n {price.currencyCode ?? ''} {amount}\n </div>\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  import Link from "next/link";
5
5
  import { useRouter } from "next/navigation";
6
6
  import { Page, PageBody } from "@open-mercato/ui/backend/Page";
7
- import { DataTable } from "@open-mercato/ui/backend/DataTable";
7
+ import { DataTable, withDataTableNamespaces } from "@open-mercato/ui/backend/DataTable";
8
8
  import { RowActions } from "@open-mercato/ui/backend/RowActions";
9
9
  import { Button } from "@open-mercato/ui/primitives/button";
10
10
  import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
@@ -345,7 +345,7 @@ function SalesDocumentsTable({ kind }) {
345
345
  const validUntil = doc.validUntil ?? null;
346
346
  const createdAt = doc.createdAt ?? null;
347
347
  const date = placedAt ?? validUntil ?? createdAt ?? null;
348
- return {
348
+ return withDataTableNamespaces({
349
349
  id,
350
350
  number,
351
351
  status: doc.status ?? null,
@@ -357,7 +357,7 @@ function SalesDocumentsTable({ kind }) {
357
357
  totalGross,
358
358
  currency: doc.currencyCode ?? null,
359
359
  date
360
- };
360
+ }, item);
361
361
  },
362
362
  [kind]
363
363
  );
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/sales/components/documents/SalesDocumentsTable.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, type DataTableExportFormat } from '@open-mercato/ui/backend/DataTable'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildCrudExportUrl, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n DictionaryValue,\n type DictionaryMap,\n createDictionaryMap,\n normalizeDictionaryEntries,\n} from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\n\ntype SalesDocumentKind = 'order' | 'quote'\n\ntype FilterOption = { value: string; label: string }\n\ntype CustomerSnapshot = {\n customer?: {\n displayName?: string | null\n primaryEmail?: string | null\n } | null\n contact?: {\n firstName?: string | null\n lastName?: string | null\n preferredName?: string | null\n } | null\n}\n\ntype ApiDocument = {\n id: string\n orderNumber?: string | null\n quoteNumber?: string | null\n status?: string | null\n customerEntityId?: string | null\n customerSnapshot?: Record<string, unknown> | null\n channelId?: string | null\n lineItemCount?: number | null\n grandTotalNetAmount?: number | null\n grandTotalGrossAmount?: number | null\n currencyCode?: string | null\n placedAt?: string | null\n validUntil?: string | null\n validFrom?: string | null\n createdAt?: string | null\n updatedAt?: string | null\n}\n\ntype DocumentsResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\ntype SalesDocumentRow = {\n id: string\n number: string\n status?: string | null\n customerName?: string | null\n customerEmail?: string | null\n channelId?: string | null\n lineItemCount?: number | null\n totalNet?: number | null\n totalGross?: number | null\n currency?: string | null\n date?: string | null\n}\n\nconst PAGE_SIZE = 20\n\nfunction resolveCustomerName(snapshot: CustomerSnapshot | null | undefined, fallback?: string | null) {\n if (!snapshot) return fallback ?? null\n const base = snapshot.customer?.displayName ?? null\n if (base) return base\n const contact = snapshot.contact\n if (contact) {\n const parts = [contact.preferredName, contact.firstName, contact.lastName].filter(\n (part) => part && part.trim().length\n ) as string[]\n if (parts.length) return parts.join(' ')\n }\n return fallback ?? null\n}\n\nfunction resolveCustomerEmail(snapshot: CustomerSnapshot | null | undefined) {\n if (!snapshot) return null\n if (snapshot.customer?.primaryEmail) return snapshot.customer.primaryEmail\n return null\n}\n\nfunction toNumber(value: unknown): number | null {\n if (typeof value === 'number') return Number.isNaN(value) ? null : value\n if (typeof value === 'string' && value.trim().length) {\n const parsed = Number(value)\n return Number.isNaN(parsed) ? null : parsed\n }\n return null\n}\n\nfunction formatCurrency(amount: number | null | undefined, currency: string | null | undefined, fallback = '\u2014') {\n if (amount == null || Number.isNaN(amount)) return fallback\n try {\n if (currency && currency.trim().length) {\n const formatter = new Intl.NumberFormat(undefined, { style: 'currency', currency })\n return formatter.format(amount)\n }\n return new Intl.NumberFormat(undefined, { style: 'decimal', maximumFractionDigits: 2 }).format(amount)\n } catch {\n return String(amount)\n }\n}\n\nfunction mergeOptions(existing: FilterOption[], next: FilterOption[]): FilterOption[] {\n const map = new Map<string, FilterOption>()\n existing.forEach((opt) => map.set(opt.value, opt))\n next.forEach((opt) => map.set(opt.value, opt))\n return Array.from(map.values()).sort((a, b) => a.label.localeCompare(b.label))\n}\n\nfunction normalizeNumberInput(value: unknown): number | null {\n if (typeof value === 'number') return Number.isNaN(value) ? null : value\n if (typeof value === 'string' && value.trim().length) {\n const parsed = Number(value)\n return Number.isNaN(parsed) ? null : parsed\n }\n return null\n}\n\nexport function SalesDocumentsTable({ kind }: { kind: SalesDocumentKind }) {\n const t = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [rows, setRows] = React.useState<SalesDocumentRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'createdAt', desc: true }])\n const [search, setSearch] = React.useState('')\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [isLoading, setLoading] = React.useState(false)\n const [cacheStatus, setCacheStatus] = React.useState<'hit' | 'miss' | null>(null)\n const [reloadToken, setReloadToken] = React.useState(0)\n const [channelOptions, setChannelOptions] = React.useState<FilterOption[]>([])\n const [tagOptions, setTagOptions] = React.useState<FilterOption[]>([])\n const [customerOptions, setCustomerOptions] = React.useState<FilterOption[]>([])\n const [statusMap, setStatusMap] = React.useState<DictionaryMap>({})\n\n const resource = kind === 'order' ? 'orders' : 'quotes'\n const entityId = kind === 'order' ? E.sales.sales_order : E.sales.sales_quote\n const title = kind === 'order'\n ? t('sales.documents.list.ordersTitle', 'Sales orders')\n : t('sales.documents.list.quotesTitle', 'Sales quotes')\n const subtitle = t(\n 'sales.documents.list.subtitle',\n 'Review documents with customer context, totals, and channels.'\n )\n\n const fetchChannelOptions = React.useCallback(async (query?: string): Promise<FilterOption[]> => {\n const params = new URLSearchParams({ page: '1', pageSize: '50' })\n if (query && query.trim()) params.set('search', query.trim())\n try {\n const call = await apiCall<{ items?: unknown[] }>(`/api/sales/channels?${params.toString()}`)\n if (!call.ok) return []\n const items = Array.isArray(call.result?.items) ? call.result!.items : []\n return items\n .map((item: any): FilterOption | null => {\n const id = typeof item?.id === 'string' ? item.id : null\n const name = typeof item?.name === 'string' ? item.name : null\n if (!id || !name) return null\n return { value: id, label: name }\n })\n .filter((opt): opt is FilterOption => opt !== null)\n } catch {\n return []\n }\n }, [])\n\n const fetchTagOptions = React.useCallback(async (query?: string): Promise<FilterOption[]> => {\n const params = new URLSearchParams({ page: '1', pageSize: '50' })\n if (query && query.trim()) params.set('search', query.trim())\n try {\n const call = await apiCall<{ items?: unknown[] }>(`/api/sales/tags?${params.toString()}`)\n if (!call.ok) return []\n const items = Array.isArray(call.result?.items) ? call.result!.items : []\n return items\n .map((item: any): FilterOption | null => {\n const id = typeof item?.id === 'string' ? item.id : null\n const label = typeof item?.label === 'string' ? item.label : null\n if (!id || !label) return null\n return { value: id, label }\n })\n .filter((opt): opt is FilterOption => opt !== null)\n } catch {\n return []\n }\n }, [])\n\n const fetchCustomerOptions = React.useCallback(async (query?: string): Promise<FilterOption[]> => {\n const params = new URLSearchParams({ page: '1', pageSize: '20' })\n if (query && query.trim().length) params.set('search', query.trim())\n try {\n const [people, companies] = await Promise.all([\n apiCall<{ items?: unknown[] }>(`/api/customers/people?${params.toString()}`),\n apiCall<{ items?: unknown[] }>(`/api/customers/companies?${params.toString()}`),\n ])\n const peopleItems = Array.isArray(people.result?.items) ? people.result?.items ?? [] : []\n const companyItems = Array.isArray(companies.result?.items) ? companies.result?.items ?? [] : []\n const parseOption = (item: any, kind: 'person' | 'company'): FilterOption | null => {\n const id = typeof item?.id === 'string' ? item.id : null\n if (!id) return null\n const name =\n typeof item?.display_name === 'string' && item.display_name.trim().length\n ? item.display_name\n : typeof item?.name === 'string' && item.name.trim().length\n ? item.name\n : id\n const email =\n typeof item?.primary_email === 'string' && item.primary_email.trim().length\n ? item.primary_email.trim()\n : null\n const label = email ? `${name} (${email})` : name\n return { value: id, label: kind === 'company' ? label : label }\n }\n const options = [...peopleItems.map((i) => parseOption(i, 'person')), ...companyItems.map((i) => parseOption(i, 'company'))]\n .filter((opt): opt is FilterOption => !!opt)\n return options\n } catch {\n return []\n }\n }, [])\n\n const loadStatusMap = React.useCallback(async () => {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '100' })\n const response = await apiCall<{ items?: Array<Record<string, unknown>> }>(\n `/api/sales/order-statuses?${params.toString()}`,\n undefined,\n { fallback: { items: [] } }\n )\n const entries = normalizeDictionaryEntries(response.result?.items ?? [])\n setStatusMap(createDictionaryMap(entries))\n } catch (err) {\n console.error('sales.documents.statuses.load', err)\n setStatusMap({})\n }\n }, [])\n\n const loadChannelOptions = React.useCallback(\n async (query?: string) => {\n const opts = await fetchChannelOptions(query)\n if (opts.length) setChannelOptions((prev) => mergeOptions(prev, opts))\n return opts\n },\n [fetchChannelOptions]\n )\n\n const loadTagOptions = React.useCallback(\n async (query?: string) => {\n const opts = await fetchTagOptions(query)\n if (opts.length) setTagOptions((prev) => mergeOptions(prev, opts))\n return opts\n },\n [fetchTagOptions]\n )\n\n const loadCustomerOptions = React.useCallback(\n async (query?: string) => {\n const opts = await fetchCustomerOptions(query)\n if (opts.length) setCustomerOptions((prev) => mergeOptions(prev, opts))\n return opts\n },\n [fetchCustomerOptions]\n )\n\n React.useEffect(() => {\n loadChannelOptions().catch(() => {})\n loadTagOptions().catch(() => {})\n loadCustomerOptions().catch(() => {})\n loadStatusMap().catch(() => setStatusMap({}))\n }, [loadChannelOptions, loadCustomerOptions, loadStatusMap, loadTagOptions, scopeVersion])\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'channelId',\n label: t('sales.documents.list.filters.channel', 'Channel'),\n type: 'select',\n options: channelOptions,\n loadOptions: loadChannelOptions,\n },\n {\n id: 'date',\n label: t('sales.documents.list.filters.date', 'Date'),\n type: 'dateRange',\n },\n {\n id: 'lineItemCountMin',\n label: t('sales.documents.list.filters.itemsMin', 'Min items'),\n type: 'text',\n },\n {\n id: 'lineItemCountMax',\n label: t('sales.documents.list.filters.itemsMax', 'Max items'),\n type: 'text',\n },\n {\n id: 'totalNetMin',\n label: t('sales.documents.list.filters.totalNetMin', 'Min total (net)'),\n type: 'text',\n },\n {\n id: 'totalNetMax',\n label: t('sales.documents.list.filters.totalNetMax', 'Max total (net)'),\n type: 'text',\n },\n {\n id: 'totalGrossMin',\n label: t('sales.documents.list.filters.totalGrossMin', 'Min total (gross)'),\n type: 'text',\n },\n {\n id: 'totalGrossMax',\n label: t('sales.documents.list.filters.totalGrossMax', 'Max total (gross)'),\n type: 'text',\n },\n {\n id: 'customerId',\n label: t('sales.documents.list.filters.customer', 'Customer'),\n type: 'tags',\n options: customerOptions,\n loadOptions: loadCustomerOptions,\n placeholder: t('sales.documents.list.filters.customerPlaceholder', 'Search customers'),\n formatValue: (val: string) => {\n const match = customerOptions.find((opt) => opt.value === val)\n return match?.label ?? val\n },\n },\n {\n id: 'tagIds',\n label: t('sales.documents.list.filters.tags', 'Tags'),\n type: 'tags',\n options: tagOptions,\n loadOptions: loadTagOptions,\n },\n ], [channelOptions, loadChannelOptions, loadTagOptions, tagOptions, t])\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', String(PAGE_SIZE))\n if (search.trim()) params.set('search', search.trim())\n const sort = sorting[0]\n if (sort?.id) {\n params.set('sortField', sort.id)\n params.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n const channelId = typeof filterValues.channelId === 'string' ? filterValues.channelId : ''\n if (channelId) params.set('channelId', channelId)\n const customerIds = Array.isArray(filterValues.customerId)\n ? filterValues.customerId\n .map((value) => (typeof value === 'string' ? value.trim() : String(value || '').trim()))\n .filter((value) => value.length > 0)\n : []\n if (customerIds.length > 0) {\n params.set('customerId', customerIds[0])\n }\n const date = filterValues.date\n if (date && typeof date === 'object') {\n if (date.from) params.set('dateFrom', date.from)\n if (date.to) params.set('dateTo', date.to)\n }\n const numberFilters: Array<[keyof FilterValues, string]> = [\n ['lineItemCountMin', 'lineItemCountMin'],\n ['lineItemCountMax', 'lineItemCountMax'],\n ['totalNetMin', 'totalNetMin'],\n ['totalNetMax', 'totalNetMax'],\n ['totalGrossMin', 'totalGrossMin'],\n ['totalGrossMax', 'totalGrossMax'],\n ]\n numberFilters.forEach(([key, queryKey]) => {\n const value = normalizeNumberInput((filterValues as any)[key])\n if (value != null) params.set(queryKey, String(value))\n })\n const tagIds = Array.isArray(filterValues.tagIds)\n ? filterValues.tagIds.map((value) => (typeof value === 'string' ? value.trim() : String(value || '').trim())).filter((v) => v.length > 0)\n : []\n if (tagIds.length > 0) {\n params.set('tagIds', tagIds.join(','))\n }\n Object.entries(filterValues).forEach(([key, value]) => {\n if (!key.startsWith('cf_') || value == null) return\n if (Array.isArray(value)) {\n const normalized = value\n .map((item) => {\n if (item == null) return ''\n if (typeof item === 'string') return item.trim()\n return String(item).trim()\n })\n .filter((item) => item.length > 0)\n if (normalized.length) params.set(key, normalized.join(','))\n } else if (typeof value === 'object') {\n return\n } else if (value !== '') {\n const stringValue = typeof value === 'string' ? value.trim() : String(value)\n if (stringValue) params.set(key, stringValue)\n }\n })\n return params.toString()\n }, [filterValues, page, search, sorting])\n\n const currentParams = React.useMemo(() => Object.fromEntries(new URLSearchParams(queryParams)), [queryParams])\n\n const exportConfig = React.useMemo(() => ({\n view: {\n getUrl: (format: DataTableExportFormat) =>\n buildCrudExportUrl(`sales/${resource}`, { ...currentParams, exportScope: 'view' }, format),\n },\n full: {\n getUrl: (format: DataTableExportFormat) =>\n buildCrudExportUrl(`sales/${resource}`, { ...currentParams, exportScope: 'full', all: 'true' }, format),\n },\n }), [currentParams, resource])\n\n const mapApiDocument = React.useCallback(\n (item: Record<string, unknown>): SalesDocumentRow => {\n const doc = item as ApiDocument\n const id = typeof doc.id === 'string' ? doc.id : ''\n const number = kind === 'order'\n ? doc.orderNumber ?? (item as any)?.order_number ?? id\n : doc.quoteNumber ?? (item as any)?.quote_number ?? id\n const customerSnapshot = (doc.customerSnapshot ?? null) as CustomerSnapshot | null\n const customerName = resolveCustomerName(customerSnapshot, doc.customerEntityId ?? null)\n const customerEmail = resolveCustomerEmail(customerSnapshot)\n const totalNet = toNumber(doc.grandTotalNetAmount)\n const totalGross = toNumber(doc.grandTotalGrossAmount)\n const placedAt = doc.placedAt ?? null\n const validUntil = doc.validUntil ?? null\n const createdAt = doc.createdAt ?? null\n const date = placedAt ?? validUntil ?? createdAt ?? null\n return {\n id,\n number,\n status: doc.status ?? null,\n customerName,\n customerEmail,\n channelId: doc.channelId ?? null,\n lineItemCount: doc.lineItemCount ?? null,\n totalNet,\n totalGross,\n currency: doc.currencyCode ?? null,\n date,\n }\n },\n [kind]\n )\n\n const loadDocuments = React.useCallback(async () => {\n setLoading(true)\n setCacheStatus(null)\n try {\n const call = await apiCall<DocumentsResponse>(`/api/sales/${resource}?${queryParams}`)\n if (!call.ok) {\n flash(t('sales.documents.list.errors.load', 'Failed to load documents.'), 'error')\n setRows([])\n setTotal(0)\n setTotalPages(1)\n return\n }\n const payload = call.result ?? {}\n const items = Array.isArray(payload.items) ? payload.items : []\n setRows(items.map((item) => mapApiDocument(item)))\n const count = typeof payload.total === 'number' ? payload.total : items.length\n setTotal(count)\n const pages = typeof payload.totalPages === 'number'\n ? payload.totalPages\n : Math.max(1, Math.ceil(count / PAGE_SIZE))\n setTotalPages(pages)\n setCacheStatus(call.cacheStatus ?? null)\n } catch (err) {\n console.error('sales.documents.list', err)\n flash(t('sales.documents.list.errors.load', 'Failed to load documents.'), 'error')\n } finally {\n setLoading(false)\n }\n }, [mapApiDocument, queryParams, resource, t])\n\n React.useEffect(() => {\n void loadDocuments()\n }, [loadDocuments, reloadToken, scopeVersion])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n setFilterValues(values)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n }, [])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [])\n\n const handleRefresh = React.useCallback(() => {\n setReloadToken((token) => token + 1)\n }, [])\n\n const handleDelete = React.useCallback(\n async (row: SalesDocumentRow) => {\n const confirmMessage =\n kind === 'order'\n ? t(\n 'sales.documents.list.table.deleteOrderConfirm',\n 'Delete this sales order? Related shipments, payments, addresses, and items will be removed.'\n )\n : t(\n 'sales.documents.list.table.deleteQuoteConfirm',\n 'Delete this sales quote? Related addresses, comments, and items will be removed.'\n )\n const confirmed = await confirm({\n title: confirmMessage,\n variant: 'destructive',\n })\n if (!confirmed) return\n try {\n const result = await deleteCrud(`sales/${resource}`, row.id, {\n errorMessage: t('sales.documents.list.table.deleteError', 'Failed to delete document.'),\n })\n if (result.ok) {\n flash(\n kind === 'order'\n ? t('sales.documents.list.table.orderDeleted', 'Sales order deleted.')\n : t('sales.documents.list.table.quoteDeleted', 'Sales quote deleted.'),\n 'success'\n )\n handleRefresh()\n }\n } catch (err) {\n console.error('sales.documents.delete', err)\n flash(t('sales.documents.list.table.deleteError', 'Failed to delete document.'), 'error')\n }\n },\n [confirm, handleRefresh, kind, resource, t]\n )\n\n const handleRowClick = React.useCallback((row: SalesDocumentRow) => {\n router.push(`/backend/sales/${resource}/${row.id}?kind=${kind}`)\n }, [kind, resource, router])\n\n const columns = React.useMemo<ColumnDef<SalesDocumentRow>[]>(() => [\n {\n id: 'number',\n accessorKey: 'number',\n header: kind === 'order'\n ? t('sales.documents.list.table.order', 'Order')\n : t('sales.documents.list.table.quote', 'Quote'),\n cell: ({ row }) => (\n <div className=\"flex flex-col\">\n <span className=\"font-semibold\">{row.original.number}</span>\n {row.original.status ? (\n <DictionaryValue\n value={row.original.status}\n map={statusMap}\n fallback={<span className=\"text-xs text-muted-foreground\">{row.original.status}</span>}\n className=\"text-xs text-muted-foreground font-medium\"\n iconWrapperClassName=\"inline-flex h-5 w-5 items-center justify-center rounded bg-muted text-muted-foreground\"\n iconClassName=\"h-3.5 w-3.5\"\n colorClassName=\"h-3 w-3 rounded-full border border-border/70\"\n />\n ) : null}\n </div>\n ),\n meta: { sticky: true },\n },\n {\n accessorKey: 'customerName',\n header: t('sales.documents.list.table.customer', 'Customer'),\n cell: ({ row }) => (\n <div className=\"flex flex-col\">\n <span className=\"text-sm font-medium\">\n {row.original.customerName ?? t('sales.documents.list.table.noCustomer', 'No customer')}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {row.original.customerEmail ?? t('sales.documents.list.table.noEmail', 'No email')}\n </span>\n </div>\n ),\n enableSorting: false,\n },\n {\n accessorKey: 'channelId',\n header: t('sales.documents.list.table.channel', 'Channel'),\n cell: ({ row }) => {\n const channelId = row.original.channelId\n if (!channelId) return <span className=\"text-xs text-muted-foreground\">{t('sales.documents.list.table.unassigned', 'Unassigned')}</span>\n const channel = channelOptions.find((opt) => opt.value === channelId)\n return (\n <span className=\"text-sm\">{channel?.label ?? channelId}</span>\n )\n },\n enableSorting: false,\n },\n {\n id: 'lineItemCount',\n accessorKey: 'lineItemCount',\n header: t('sales.documents.list.table.items', 'Items'),\n cell: ({ row }) => (\n <span className=\"text-sm font-semibold\">{typeof row.original.lineItemCount === 'number' ? row.original.lineItemCount : '\u2014'}</span>\n ),\n },\n {\n id: 'grandTotalNetAmount',\n accessorKey: 'totalNet',\n header: t('sales.documents.list.table.totalNet', 'Total (net)'),\n cell: ({ row }) => (\n <span className=\"text-sm\">{formatCurrency(row.original.totalNet ?? null, row.original.currency)}</span>\n ),\n },\n {\n id: 'grandTotalGrossAmount',\n accessorKey: 'totalGross',\n header: t('sales.documents.list.table.totalGross', 'Total (gross)'),\n cell: ({ row }) => (\n <span className=\"text-sm\">{formatCurrency(row.original.totalGross ?? null, row.original.currency)}</span>\n ),\n },\n {\n id: 'createdAt',\n accessorKey: 'date',\n header: t('sales.documents.list.table.date', 'Date'),\n cell: ({ row }) =>\n row.original.date\n ? <span className=\"text-xs text-muted-foreground\">{new Date(row.original.date).toLocaleString()}</span>\n : <span className=\"text-xs text-muted-foreground\">\u2014</span>,\n },\n ], [channelOptions, kind, statusMap, t])\n\n const emptyLabel = kind === 'order'\n ? t('sales.documents.list.table.emptyOrders', 'No orders yet.')\n : t('sales.documents.list.table.emptyQuotes', 'No quotes yet.')\n\n return (\n <Page>\n <PageBody>\n <DataTable<SalesDocumentRow>\n title={(\n <div className=\"flex flex-col\">\n <span>{title}</span>\n <span className=\"text-sm font-normal text-muted-foreground\">{subtitle}</span>\n </div>\n )}\n actions={(\n <Button asChild>\n <Link href={`/backend/sales/documents/create?kind=${kind}`}>\n {t('sales.documents.create.title', 'Create sales document')}\n </Link>\n </Button>\n )}\n columns={columns}\n data={rows}\n sorting={sorting}\n onSortingChange={setSorting}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={\n kind === 'order'\n ? t('sales.documents.list.search.orders', 'Search orders\u2026')\n : t('sales.documents.list.search.quotes', 'Search quotes\u2026')\n }\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n entityId={entityId}\n exporter={exportConfig}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n onPageChange: setPage,\n cacheStatus,\n }}\n refreshButton={{\n label: t('sales.documents.list.table.refresh', 'Refresh'),\n onRefresh: handleRefresh,\n isRefreshing: isLoading,\n }}\n rowActions={(row) => (\n <RowActions\n items={[\n {\n id: 'open',\n label: t('sales.documents.list.table.open', 'Open'),\n href: `/backend/sales/${resource}/${row.id}?kind=${kind}`,\n },\n {\n id: 'delete',\n label:\n kind === 'order'\n ? t('sales.documents.list.table.deleteOrder', 'Delete order')\n : t('sales.documents.list.table.deleteQuote', 'Delete quote'),\n onSelect: () => handleDelete(row),\n },\n ]}\n />\n )}\n onRowClick={handleRowClick}\n emptyState={\n <div className=\"py-10 text-center text-sm text-muted-foreground\">\n {emptyLabel}\n </div>\n }\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n\nexport default SalesDocumentsTable\n"],
5
- "mappings": ";AA2jBQ,SACE,KADF;AAzjBR,YAAY,WAAW;AACvB,OAAO,UAAU;AACjB,SAAS,iBAAiB;AAE1B,SAAS,MAAM,gBAAgB;AAC/B,SAAS,iBAA6C;AAEtD,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AACvB,SAAS,eAAe;AACxB,SAAS,oBAAoB,kBAAkB;AAC/C,SAAS,aAAa;AACtB,SAAS,mCAAmC;AAC5C,SAAS,YAAY;AACrB,SAAS,wBAAwB;AACjC,SAAS,SAAS;AAClB;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,OACK;AAyDP,MAAM,YAAY;AAElB,SAAS,oBAAoB,UAA+C,UAA0B;AACpG,MAAI,CAAC,SAAU,QAAO,YAAY;AAClC,QAAM,OAAO,SAAS,UAAU,eAAe;AAC/C,MAAI,KAAM,QAAO;AACjB,QAAM,UAAU,SAAS;AACzB,MAAI,SAAS;AACX,UAAM,QAAQ,CAAC,QAAQ,eAAe,QAAQ,WAAW,QAAQ,QAAQ,EAAE;AAAA,MACzE,CAAC,SAAS,QAAQ,KAAK,KAAK,EAAE;AAAA,IAChC;AACA,QAAI,MAAM,OAAQ,QAAO,MAAM,KAAK,GAAG;AAAA,EACzC;AACA,SAAO,YAAY;AACrB;AAEA,SAAS,qBAAqB,UAA+C;AAC3E,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI,SAAS,UAAU,aAAc,QAAO,SAAS,SAAS;AAC9D,SAAO;AACT;AAEA,SAAS,SAAS,OAA+B;AAC/C,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,MAAM,KAAK,IAAI,OAAO;AACnE,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,QAAQ;AACpD,UAAM,SAAS,OAAO,KAAK;AAC3B,WAAO,OAAO,MAAM,MAAM,IAAI,OAAO;AAAA,EACvC;AACA,SAAO;AACT;AAEA,SAAS,eAAe,QAAmC,UAAqC,WAAW,UAAK;AAC9G,MAAI,UAAU,QAAQ,OAAO,MAAM,MAAM,EAAG,QAAO;AACnD,MAAI;AACF,QAAI,YAAY,SAAS,KAAK,EAAE,QAAQ;AACtC,YAAM,YAAY,IAAI,KAAK,aAAa,QAAW,EAAE,OAAO,YAAY,SAAS,CAAC;AAClF,aAAO,UAAU,OAAO,MAAM;AAAA,IAChC;AACA,WAAO,IAAI,KAAK,aAAa,QAAW,EAAE,OAAO,WAAW,uBAAuB,EAAE,CAAC,EAAE,OAAO,MAAM;AAAA,EACvG,QAAQ;AACN,WAAO,OAAO,MAAM;AAAA,EACtB;AACF;AAEA,SAAS,aAAa,UAA0B,MAAsC;AACpF,QAAM,MAAM,oBAAI,IAA0B;AAC1C,WAAS,QAAQ,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,GAAG,CAAC;AACjD,OAAK,QAAQ,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,GAAG,CAAC;AAC7C,SAAO,MAAM,KAAK,IAAI,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,cAAc,EAAE,KAAK,CAAC;AAC/E;AAEA,SAAS,qBAAqB,OAA+B;AAC3D,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,MAAM,KAAK,IAAI,OAAO;AACnE,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,QAAQ;AACpD,UAAM,SAAS,OAAO,KAAK;AAC3B,WAAO,OAAO,MAAM,MAAM,IAAI,OAAO;AAAA,EACvC;AACA,SAAO;AACT;AAEO,SAAS,oBAAoB,EAAE,KAAK,GAAgC;AACzE,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,UAAU;AACzB,QAAM,eAAe,4BAA4B;AACjD,QAAM,EAAE,SAAS,qBAAqB,IAAI,iBAAiB;AAC3D,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAA6B,CAAC,CAAC;AAC7D,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAS,CAAC;AACxC,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAS,CAAC;AAC1C,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,CAAC;AACpD,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAuB,CAAC,EAAE,IAAI,aAAa,MAAM,KAAK,CAAC,CAAC;AAC5F,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE;AAC7C,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAuB,CAAC,CAAC;AACvE,QAAM,CAAC,WAAW,UAAU,IAAI,MAAM,SAAS,KAAK;AACpD,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAgC,IAAI;AAChF,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAS,CAAC;AACtD,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,MAAM,SAAyB,CAAC,CAAC;AAC7E,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAyB,CAAC,CAAC;AACrE,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,MAAM,SAAyB,CAAC,CAAC;AAC/E,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAwB,CAAC,CAAC;AAElE,QAAM,WAAW,SAAS,UAAU,WAAW;AAC/C,QAAM,WAAW,SAAS,UAAU,EAAE,MAAM,cAAc,EAAE,MAAM;AAClE,QAAM,QAAQ,SAAS,UACnB,EAAE,oCAAoC,cAAc,IACpD,EAAE,oCAAoC,cAAc;AACxD,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,EACF;AAEA,QAAM,sBAAsB,MAAM,YAAY,OAAO,UAA4C;AAC/F,UAAM,SAAS,IAAI,gBAAgB,EAAE,MAAM,KAAK,UAAU,KAAK,CAAC;AAChE,QAAI,SAAS,MAAM,KAAK,EAAG,QAAO,IAAI,UAAU,MAAM,KAAK,CAAC;AAC5D,QAAI;AACF,YAAM,OAAO,MAAM,QAA+B,uBAAuB,OAAO,SAAS,CAAC,EAAE;AAC5F,UAAI,CAAC,KAAK,GAAI,QAAO,CAAC;AACtB,YAAM,QAAQ,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,KAAK,OAAQ,QAAQ,CAAC;AACxE,aAAO,MACJ,IAAI,CAAC,SAAmC;AACvC,cAAM,KAAK,OAAO,MAAM,OAAO,WAAW,KAAK,KAAK;AACpD,cAAM,OAAO,OAAO,MAAM,SAAS,WAAW,KAAK,OAAO;AAC1D,YAAI,CAAC,MAAM,CAAC,KAAM,QAAO;AACzB,eAAO,EAAE,OAAO,IAAI,OAAO,KAAK;AAAA,MAClC,CAAC,EACA,OAAO,CAAC,QAA6B,QAAQ,IAAI;AAAA,IACtD,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAkB,MAAM,YAAY,OAAO,UAA4C;AAC3F,UAAM,SAAS,IAAI,gBAAgB,EAAE,MAAM,KAAK,UAAU,KAAK,CAAC;AAChE,QAAI,SAAS,MAAM,KAAK,EAAG,QAAO,IAAI,UAAU,MAAM,KAAK,CAAC;AAC5D,QAAI;AACF,YAAM,OAAO,MAAM,QAA+B,mBAAmB,OAAO,SAAS,CAAC,EAAE;AACxF,UAAI,CAAC,KAAK,GAAI,QAAO,CAAC;AACtB,YAAM,QAAQ,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,KAAK,OAAQ,QAAQ,CAAC;AACxE,aAAO,MACJ,IAAI,CAAC,SAAmC;AACvC,cAAM,KAAK,OAAO,MAAM,OAAO,WAAW,KAAK,KAAK;AACpD,cAAM,QAAQ,OAAO,MAAM,UAAU,WAAW,KAAK,QAAQ;AAC7D,YAAI,CAAC,MAAM,CAAC,MAAO,QAAO;AAC1B,eAAO,EAAE,OAAO,IAAI,MAAM;AAAA,MAC5B,CAAC,EACA,OAAO,CAAC,QAA6B,QAAQ,IAAI;AAAA,IACtD,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,uBAAuB,MAAM,YAAY,OAAO,UAA4C;AAChG,UAAM,SAAS,IAAI,gBAAgB,EAAE,MAAM,KAAK,UAAU,KAAK,CAAC;AAChE,QAAI,SAAS,MAAM,KAAK,EAAE,OAAQ,QAAO,IAAI,UAAU,MAAM,KAAK,CAAC;AACnE,QAAI;AACF,YAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,QAC5C,QAA+B,yBAAyB,OAAO,SAAS,CAAC,EAAE;AAAA,QAC3E,QAA+B,4BAA4B,OAAO,SAAS,CAAC,EAAE;AAAA,MAChF,CAAC;AACD,YAAM,cAAc,MAAM,QAAQ,OAAO,QAAQ,KAAK,IAAI,OAAO,QAAQ,SAAS,CAAC,IAAI,CAAC;AACxF,YAAM,eAAe,MAAM,QAAQ,UAAU,QAAQ,KAAK,IAAI,UAAU,QAAQ,SAAS,CAAC,IAAI,CAAC;AAC/F,YAAM,cAAc,CAAC,MAAWA,UAAoD;AAClF,cAAM,KAAK,OAAO,MAAM,OAAO,WAAW,KAAK,KAAK;AACpD,YAAI,CAAC,GAAI,QAAO;AAChB,cAAM,OACJ,OAAO,MAAM,iBAAiB,YAAY,KAAK,aAAa,KAAK,EAAE,SAC/D,KAAK,eACL,OAAO,MAAM,SAAS,YAAY,KAAK,KAAK,KAAK,EAAE,SACjD,KAAK,OACL;AACR,cAAM,QACJ,OAAO,MAAM,kBAAkB,YAAY,KAAK,cAAc,KAAK,EAAE,SACjE,KAAK,cAAc,KAAK,IACxB;AACN,cAAM,QAAQ,QAAQ,GAAG,IAAI,KAAK,KAAK,MAAM;AAC7C,eAAO,EAAE,OAAO,IAAI,OAAOA,UAAS,YAAY,QAAQ,MAAM;AAAA,MAChE;AACA,YAAM,UAAU,CAAC,GAAG,YAAY,IAAI,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,GAAG,aAAa,IAAI,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,EACxH,OAAO,CAAC,QAA6B,CAAC,CAAC,GAAG;AAC7C,aAAO;AAAA,IACT,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgB,MAAM,YAAY,YAAY;AAClD,QAAI;AACF,YAAM,SAAS,IAAI,gBAAgB,EAAE,MAAM,KAAK,UAAU,MAAM,CAAC;AACjE,YAAM,WAAW,MAAM;AAAA,QACrB,6BAA6B,OAAO,SAAS,CAAC;AAAA,QAC9C;AAAA,QACA,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,MAC5B;AACA,YAAM,UAAU,2BAA2B,SAAS,QAAQ,SAAS,CAAC,CAAC;AACvE,mBAAa,oBAAoB,OAAO,CAAC;AAAA,IAC3C,SAAS,KAAK;AACZ,cAAQ,MAAM,iCAAiC,GAAG;AAClD,mBAAa,CAAC,CAAC;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB,MAAM;AAAA,IAC/B,OAAO,UAAmB;AACxB,YAAM,OAAO,MAAM,oBAAoB,KAAK;AAC5C,UAAI,KAAK,OAAQ,mBAAkB,CAAC,SAAS,aAAa,MAAM,IAAI,CAAC;AACrE,aAAO;AAAA,IACT;AAAA,IACA,CAAC,mBAAmB;AAAA,EACtB;AAEA,QAAM,iBAAiB,MAAM;AAAA,IAC3B,OAAO,UAAmB;AACxB,YAAM,OAAO,MAAM,gBAAgB,KAAK;AACxC,UAAI,KAAK,OAAQ,eAAc,CAAC,SAAS,aAAa,MAAM,IAAI,CAAC;AACjE,aAAO;AAAA,IACT;AAAA,IACA,CAAC,eAAe;AAAA,EAClB;AAEA,QAAM,sBAAsB,MAAM;AAAA,IAChC,OAAO,UAAmB;AACxB,YAAM,OAAO,MAAM,qBAAqB,KAAK;AAC7C,UAAI,KAAK,OAAQ,oBAAmB,CAAC,SAAS,aAAa,MAAM,IAAI,CAAC;AACtE,aAAO;AAAA,IACT;AAAA,IACA,CAAC,oBAAoB;AAAA,EACvB;AAEA,QAAM,UAAU,MAAM;AACpB,uBAAmB,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACnC,mBAAe,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC/B,wBAAoB,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACpC,kBAAc,EAAE,MAAM,MAAM,aAAa,CAAC,CAAC,CAAC;AAAA,EAC9C,GAAG,CAAC,oBAAoB,qBAAqB,eAAe,gBAAgB,YAAY,CAAC;AAEzF,QAAM,UAAU,MAAM,QAAqB,MAAM;AAAA,IAC/C;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,wCAAwC,SAAS;AAAA,MAC1D,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,qCAAqC,MAAM;AAAA,MACpD,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,yCAAyC,WAAW;AAAA,MAC7D,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,yCAAyC,WAAW;AAAA,MAC7D,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,4CAA4C,iBAAiB;AAAA,MACtE,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,4CAA4C,iBAAiB;AAAA,MACtE,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,8CAA8C,mBAAmB;AAAA,MAC1E,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,8CAA8C,mBAAmB;AAAA,MAC1E,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,yCAAyC,UAAU;AAAA,MAC5D,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa,EAAE,oDAAoD,kBAAkB;AAAA,MACrF,aAAa,CAAC,QAAgB;AAC5B,cAAM,QAAQ,gBAAgB,KAAK,CAAC,QAAQ,IAAI,UAAU,GAAG;AAC7D,eAAO,OAAO,SAAS;AAAA,MACzB;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,qCAAqC,MAAM;AAAA,MACpD,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,EACF,GAAG,CAAC,gBAAgB,oBAAoB,gBAAgB,YAAY,CAAC,CAAC;AAEtE,QAAM,cAAc,MAAM,QAAQ,MAAM;AACtC,UAAM,SAAS,IAAI,gBAAgB;AACnC,WAAO,IAAI,QAAQ,OAAO,IAAI,CAAC;AAC/B,WAAO,IAAI,YAAY,OAAO,SAAS,CAAC;AACxC,QAAI,OAAO,KAAK,EAAG,QAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AACrD,UAAM,OAAO,QAAQ,CAAC;AACtB,QAAI,MAAM,IAAI;AACZ,aAAO,IAAI,aAAa,KAAK,EAAE;AAC/B,aAAO,IAAI,WAAW,KAAK,OAAO,SAAS,KAAK;AAAA,IAClD;AACA,UAAM,YAAY,OAAO,aAAa,cAAc,WAAW,aAAa,YAAY;AACxF,QAAI,UAAW,QAAO,IAAI,aAAa,SAAS;AAChD,UAAM,cAAc,MAAM,QAAQ,aAAa,UAAU,IACrD,aAAa,WACV,IAAI,CAAC,UAAW,OAAO,UAAU,WAAW,MAAM,KAAK,IAAI,OAAO,SAAS,EAAE,EAAE,KAAK,CAAE,EACtF,OAAO,CAAC,UAAU,MAAM,SAAS,CAAC,IACrC,CAAC;AACL,QAAI,YAAY,SAAS,GAAG;AAC1B,aAAO,IAAI,cAAc,YAAY,CAAC,CAAC;AAAA,IACzC;AACA,UAAM,OAAO,aAAa;AAC1B,QAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,UAAI,KAAK,KAAM,QAAO,IAAI,YAAY,KAAK,IAAI;AAC/C,UAAI,KAAK,GAAI,QAAO,IAAI,UAAU,KAAK,EAAE;AAAA,IAC3C;AACA,UAAM,gBAAqD;AAAA,MACzD,CAAC,oBAAoB,kBAAkB;AAAA,MACvC,CAAC,oBAAoB,kBAAkB;AAAA,MACvC,CAAC,eAAe,aAAa;AAAA,MAC7B,CAAC,eAAe,aAAa;AAAA,MAC7B,CAAC,iBAAiB,eAAe;AAAA,MACjC,CAAC,iBAAiB,eAAe;AAAA,IACnC;AACA,kBAAc,QAAQ,CAAC,CAAC,KAAK,QAAQ,MAAM;AACzC,YAAM,QAAQ,qBAAsB,aAAqB,GAAG,CAAC;AAC7D,UAAI,SAAS,KAAM,QAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AAAA,IACvD,CAAC;AACD,UAAM,SAAS,MAAM,QAAQ,aAAa,MAAM,IAC5C,aAAa,OAAO,IAAI,CAAC,UAAW,OAAO,UAAU,WAAW,MAAM,KAAK,IAAI,OAAO,SAAS,EAAE,EAAE,KAAK,CAAE,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,IACtI,CAAC;AACL,QAAI,OAAO,SAAS,GAAG;AACrB,aAAO,IAAI,UAAU,OAAO,KAAK,GAAG,CAAC;AAAA,IACvC;AACA,WAAO,QAAQ,YAAY,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACrD,UAAI,CAAC,IAAI,WAAW,KAAK,KAAK,SAAS,KAAM;AAC7C,UAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,cAAM,aAAa,MAChB,IAAI,CAAC,SAAS;AACb,cAAI,QAAQ,KAAM,QAAO;AACzB,cAAI,OAAO,SAAS,SAAU,QAAO,KAAK,KAAK;AAC/C,iBAAO,OAAO,IAAI,EAAE,KAAK;AAAA,QAC3B,CAAC,EACA,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AACnC,YAAI,WAAW,OAAQ,QAAO,IAAI,KAAK,WAAW,KAAK,GAAG,CAAC;AAAA,MAC7D,WAAW,OAAO,UAAU,UAAU;AACpC;AAAA,MACF,WAAW,UAAU,IAAI;AACvB,cAAM,cAAc,OAAO,UAAU,WAAW,MAAM,KAAK,IAAI,OAAO,KAAK;AAC3E,YAAI,YAAa,QAAO,IAAI,KAAK,WAAW;AAAA,MAC9C;AAAA,IACF,CAAC;AACD,WAAO,OAAO,SAAS;AAAA,EACzB,GAAG,CAAC,cAAc,MAAM,QAAQ,OAAO,CAAC;AAExC,QAAM,gBAAgB,MAAM,QAAQ,MAAM,OAAO,YAAY,IAAI,gBAAgB,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC;AAE7G,QAAM,eAAe,MAAM,QAAQ,OAAO;AAAA,IACxC,MAAM;AAAA,MACJ,QAAQ,CAAC,WACP,mBAAmB,SAAS,QAAQ,IAAI,EAAE,GAAG,eAAe,aAAa,OAAO,GAAG,MAAM;AAAA,IAC7F;AAAA,IACA,MAAM;AAAA,MACJ,QAAQ,CAAC,WACP,mBAAmB,SAAS,QAAQ,IAAI,EAAE,GAAG,eAAe,aAAa,QAAQ,KAAK,OAAO,GAAG,MAAM;AAAA,IAC1G;AAAA,EACF,IAAI,CAAC,eAAe,QAAQ,CAAC;AAE7B,QAAM,iBAAiB,MAAM;AAAA,IAC3B,CAAC,SAAoD;AACnD,YAAM,MAAM;AACZ,YAAM,KAAK,OAAO,IAAI,OAAO,WAAW,IAAI,KAAK;AACjD,YAAM,SAAS,SAAS,UACpB,IAAI,eAAgB,MAAc,gBAAgB,KAClD,IAAI,eAAgB,MAAc,gBAAgB;AACtD,YAAM,mBAAoB,IAAI,oBAAoB;AAClD,YAAM,eAAe,oBAAoB,kBAAkB,IAAI,oBAAoB,IAAI;AACvF,YAAM,gBAAgB,qBAAqB,gBAAgB;AAC3D,YAAM,WAAW,SAAS,IAAI,mBAAmB;AACjD,YAAM,aAAa,SAAS,IAAI,qBAAqB;AACrD,YAAM,WAAW,IAAI,YAAY;AACjC,YAAM,aAAa,IAAI,cAAc;AACrC,YAAM,YAAY,IAAI,aAAa;AACnC,YAAM,OAAO,YAAY,cAAc,aAAa;AACpD,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,QAAQ,IAAI,UAAU;AAAA,QACtB;AAAA,QACA;AAAA,QACA,WAAW,IAAI,aAAa;AAAA,QAC5B,eAAe,IAAI,iBAAiB;AAAA,QACpC;AAAA,QACA;AAAA,QACA,UAAU,IAAI,gBAAgB;AAAA,QAC9B;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,IAAI;AAAA,EACP;AAEA,QAAM,gBAAgB,MAAM,YAAY,YAAY;AAClD,eAAW,IAAI;AACf,mBAAe,IAAI;AACnB,QAAI;AACF,YAAM,OAAO,MAAM,QAA2B,cAAc,QAAQ,IAAI,WAAW,EAAE;AACrF,UAAI,CAAC,KAAK,IAAI;AACZ,cAAM,EAAE,oCAAoC,2BAA2B,GAAG,OAAO;AACjF,gBAAQ,CAAC,CAAC;AACV,iBAAS,CAAC;AACV,sBAAc,CAAC;AACf;AAAA,MACF;AACA,YAAM,UAAU,KAAK,UAAU,CAAC;AAChC,YAAM,QAAQ,MAAM,QAAQ,QAAQ,KAAK,IAAI,QAAQ,QAAQ,CAAC;AAC9D,cAAQ,MAAM,IAAI,CAAC,SAAS,eAAe,IAAI,CAAC,CAAC;AACjD,YAAM,QAAQ,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,MAAM;AACxE,eAAS,KAAK;AACd,YAAM,QAAQ,OAAO,QAAQ,eAAe,WACxC,QAAQ,aACR,KAAK,IAAI,GAAG,KAAK,KAAK,QAAQ,SAAS,CAAC;AAC5C,oBAAc,KAAK;AACnB,qBAAe,KAAK,eAAe,IAAI;AAAA,IACzC,SAAS,KAAK;AACZ,cAAQ,MAAM,wBAAwB,GAAG;AACzC,YAAM,EAAE,oCAAoC,2BAA2B,GAAG,OAAO;AAAA,IACnF,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,gBAAgB,aAAa,UAAU,CAAC,CAAC;AAE7C,QAAM,UAAU,MAAM;AACpB,SAAK,cAAc;AAAA,EACrB,GAAG,CAAC,eAAe,aAAa,YAAY,CAAC;AAE7C,QAAM,qBAAqB,MAAM,YAAY,CAAC,WAAyB;AACrE,oBAAgB,MAAM;AACtB,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB,MAAM,YAAY,MAAM;AACjD,oBAAgB,CAAC,CAAC;AAClB,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB,MAAM,YAAY,CAAC,UAAkB;AAC9D,cAAU,KAAK;AACf,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgB,MAAM,YAAY,MAAM;AAC5C,mBAAe,CAAC,UAAU,QAAQ,CAAC;AAAA,EACrC,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,MAAM;AAAA,IACzB,OAAO,QAA0B;AAC/B,YAAM,iBACJ,SAAS,UACL;AAAA,QACE;AAAA,QACA;AAAA,MACF,IACA;AAAA,QACE;AAAA,QACA;AAAA,MACF;AACN,YAAM,YAAY,MAAM,QAAQ;AAAA,QAC9B,OAAO;AAAA,QACP,SAAS;AAAA,MACX,CAAC;AACD,UAAI,CAAC,UAAW;AAChB,UAAI;AACF,cAAM,SAAS,MAAM,WAAW,SAAS,QAAQ,IAAI,IAAI,IAAI;AAAA,UAC3D,cAAc,EAAE,0CAA0C,4BAA4B;AAAA,QACxF,CAAC;AACD,YAAI,OAAO,IAAI;AACb;AAAA,YACE,SAAS,UACL,EAAE,2CAA2C,sBAAsB,IACnE,EAAE,2CAA2C,sBAAsB;AAAA,YACvE;AAAA,UACF;AACA,wBAAc;AAAA,QAChB;AAAA,MACF,SAAS,KAAK;AACZ,gBAAQ,MAAM,0BAA0B,GAAG;AAC3C,cAAM,EAAE,0CAA0C,4BAA4B,GAAG,OAAO;AAAA,MAC1F;AAAA,IACF;AAAA,IACA,CAAC,SAAS,eAAe,MAAM,UAAU,CAAC;AAAA,EAC5C;AAEA,QAAM,iBAAiB,MAAM,YAAY,CAAC,QAA0B;AAClE,WAAO,KAAK,kBAAkB,QAAQ,IAAI,IAAI,EAAE,SAAS,IAAI,EAAE;AAAA,EACjE,GAAG,CAAC,MAAM,UAAU,MAAM,CAAC;AAE3B,QAAM,UAAU,MAAM,QAAuC,MAAM;AAAA,IACjE;AAAA,MACE,IAAI;AAAA,MACJ,aAAa;AAAA,MACb,QAAQ,SAAS,UACb,EAAE,oCAAoC,OAAO,IAC7C,EAAE,oCAAoC,OAAO;AAAA,MACjD,MAAM,CAAC,EAAE,IAAI,MACX,qBAAC,SAAI,WAAU,iBACb;AAAA,4BAAC,UAAK,WAAU,iBAAiB,cAAI,SAAS,QAAO;AAAA,QACpD,IAAI,SAAS,SACZ;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,IAAI,SAAS;AAAA,YACpB,KAAK;AAAA,YACL,UAAU,oBAAC,UAAK,WAAU,iCAAiC,cAAI,SAAS,QAAO;AAAA,YAC/E,WAAU;AAAA,YACV,sBAAqB;AAAA,YACrB,eAAc;AAAA,YACd,gBAAe;AAAA;AAAA,QACjB,IACE;AAAA,SACN;AAAA,MAEF,MAAM,EAAE,QAAQ,KAAK;AAAA,IACvB;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,uCAAuC,UAAU;AAAA,MAC3D,MAAM,CAAC,EAAE,IAAI,MACX,qBAAC,SAAI,WAAU,iBACb;AAAA,4BAAC,UAAK,WAAU,uBACb,cAAI,SAAS,gBAAgB,EAAE,yCAAyC,aAAa,GACxF;AAAA,QACA,oBAAC,UAAK,WAAU,iCACb,cAAI,SAAS,iBAAiB,EAAE,sCAAsC,UAAU,GACnF;AAAA,SACF;AAAA,MAEF,eAAe;AAAA,IACjB;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,sCAAsC,SAAS;AAAA,MACzD,MAAM,CAAC,EAAE,IAAI,MAAM;AACjB,cAAM,YAAY,IAAI,SAAS;AAC/B,YAAI,CAAC,UAAW,QAAO,oBAAC,UAAK,WAAU,iCAAiC,YAAE,yCAAyC,YAAY,GAAE;AACjI,cAAM,UAAU,eAAe,KAAK,CAAC,QAAQ,IAAI,UAAU,SAAS;AACpE,eACE,oBAAC,UAAK,WAAU,WAAW,mBAAS,SAAS,WAAU;AAAA,MAE3D;AAAA,MACA,eAAe;AAAA,IACjB;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,aAAa;AAAA,MACb,QAAQ,EAAE,oCAAoC,OAAO;AAAA,MACrD,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,UAAK,WAAU,yBAAyB,iBAAO,IAAI,SAAS,kBAAkB,WAAW,IAAI,SAAS,gBAAgB,UAAI;AAAA,IAE/H;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,aAAa;AAAA,MACb,QAAQ,EAAE,uCAAuC,aAAa;AAAA,MAC9D,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,UAAK,WAAU,WAAW,yBAAe,IAAI,SAAS,YAAY,MAAM,IAAI,SAAS,QAAQ,GAAE;AAAA,IAEpG;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,aAAa;AAAA,MACb,QAAQ,EAAE,yCAAyC,eAAe;AAAA,MAClE,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,UAAK,WAAU,WAAW,yBAAe,IAAI,SAAS,cAAc,MAAM,IAAI,SAAS,QAAQ,GAAE;AAAA,IAEtG;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,aAAa;AAAA,MACb,QAAQ,EAAE,mCAAmC,MAAM;AAAA,MACnD,MAAM,CAAC,EAAE,IAAI,MACX,IAAI,SAAS,OACT,oBAAC,UAAK,WAAU,iCAAiC,cAAI,KAAK,IAAI,SAAS,IAAI,EAAE,eAAe,GAAE,IAC9F,oBAAC,UAAK,WAAU,iCAAgC,oBAAC;AAAA,IACzD;AAAA,EACF,GAAG,CAAC,gBAAgB,MAAM,WAAW,CAAC,CAAC;AAEvC,QAAM,aAAa,SAAS,UACxB,EAAE,0CAA0C,gBAAgB,IAC5D,EAAE,0CAA0C,gBAAgB;AAEhE,SACE,qBAAC,QACC;AAAA,wBAAC,YACC;AAAA,MAAC;AAAA;AAAA,QACC,OACE,qBAAC,SAAI,WAAU,iBACb;AAAA,8BAAC,UAAM,iBAAM;AAAA,UACb,oBAAC,UAAK,WAAU,6CAA6C,oBAAS;AAAA,WACxE;AAAA,QAEF,SACE,oBAAC,UAAO,SAAO,MACb,8BAAC,QAAK,MAAM,wCAAwC,IAAI,IACrD,YAAE,gCAAgC,uBAAuB,GAC5D,GACF;AAAA,QAEF;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA,iBAAiB;AAAA,QACjB;AAAA,QACA,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,mBACE,SAAS,UACL,EAAE,sCAAsC,qBAAgB,IACxD,EAAE,sCAAsC,qBAAgB;AAAA,QAE9D;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,QAChB;AAAA,QACA,UAAU;AAAA,QACV,YAAY;AAAA,UACV;AAAA,UACA,UAAU;AAAA,UACV;AAAA,UACA;AAAA,UACA,cAAc;AAAA,UACd;AAAA,QACF;AAAA,QACA,eAAe;AAAA,UACb,OAAO,EAAE,sCAAsC,SAAS;AAAA,UACxD,WAAW;AAAA,UACX,cAAc;AAAA,QAChB;AAAA,QACA,YAAY,CAAC,QACX;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL;AAAA,gBACE,IAAI;AAAA,gBACJ,OAAO,EAAE,mCAAmC,MAAM;AAAA,gBAClD,MAAM,kBAAkB,QAAQ,IAAI,IAAI,EAAE,SAAS,IAAI;AAAA,cACzD;AAAA,cACA;AAAA,gBACE,IAAI;AAAA,gBACJ,OACE,SAAS,UACL,EAAE,0CAA0C,cAAc,IAC1D,EAAE,0CAA0C,cAAc;AAAA,gBAChE,UAAU,MAAM,aAAa,GAAG;AAAA,cAClC;AAAA,YACF;AAAA;AAAA,QACF;AAAA,QAEF,YAAY;AAAA,QACZ,YACE,oBAAC,SAAI,WAAU,mDACZ,sBACH;AAAA;AAAA,IAEJ,GACF;AAAA,IACC;AAAA,KACH;AAEJ;AAEA,IAAO,8BAAQ;",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, type DataTableExportFormat, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildCrudExportUrl, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n DictionaryValue,\n type DictionaryMap,\n createDictionaryMap,\n normalizeDictionaryEntries,\n} from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\n\ntype SalesDocumentKind = 'order' | 'quote'\n\ntype FilterOption = { value: string; label: string }\n\ntype CustomerSnapshot = {\n customer?: {\n displayName?: string | null\n primaryEmail?: string | null\n } | null\n contact?: {\n firstName?: string | null\n lastName?: string | null\n preferredName?: string | null\n } | null\n}\n\ntype ApiDocument = {\n id: string\n orderNumber?: string | null\n quoteNumber?: string | null\n status?: string | null\n customerEntityId?: string | null\n customerSnapshot?: Record<string, unknown> | null\n channelId?: string | null\n lineItemCount?: number | null\n grandTotalNetAmount?: number | null\n grandTotalGrossAmount?: number | null\n currencyCode?: string | null\n placedAt?: string | null\n validUntil?: string | null\n validFrom?: string | null\n createdAt?: string | null\n updatedAt?: string | null\n}\n\ntype DocumentsResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\ntype SalesDocumentRow = {\n id: string\n number: string\n status?: string | null\n customerName?: string | null\n customerEmail?: string | null\n channelId?: string | null\n lineItemCount?: number | null\n totalNet?: number | null\n totalGross?: number | null\n currency?: string | null\n date?: string | null\n}\n\nconst PAGE_SIZE = 20\n\nfunction resolveCustomerName(snapshot: CustomerSnapshot | null | undefined, fallback?: string | null) {\n if (!snapshot) return fallback ?? null\n const base = snapshot.customer?.displayName ?? null\n if (base) return base\n const contact = snapshot.contact\n if (contact) {\n const parts = [contact.preferredName, contact.firstName, contact.lastName].filter(\n (part) => part && part.trim().length\n ) as string[]\n if (parts.length) return parts.join(' ')\n }\n return fallback ?? null\n}\n\nfunction resolveCustomerEmail(snapshot: CustomerSnapshot | null | undefined) {\n if (!snapshot) return null\n if (snapshot.customer?.primaryEmail) return snapshot.customer.primaryEmail\n return null\n}\n\nfunction toNumber(value: unknown): number | null {\n if (typeof value === 'number') return Number.isNaN(value) ? null : value\n if (typeof value === 'string' && value.trim().length) {\n const parsed = Number(value)\n return Number.isNaN(parsed) ? null : parsed\n }\n return null\n}\n\nfunction formatCurrency(amount: number | null | undefined, currency: string | null | undefined, fallback = '\u2014') {\n if (amount == null || Number.isNaN(amount)) return fallback\n try {\n if (currency && currency.trim().length) {\n const formatter = new Intl.NumberFormat(undefined, { style: 'currency', currency })\n return formatter.format(amount)\n }\n return new Intl.NumberFormat(undefined, { style: 'decimal', maximumFractionDigits: 2 }).format(amount)\n } catch {\n return String(amount)\n }\n}\n\nfunction mergeOptions(existing: FilterOption[], next: FilterOption[]): FilterOption[] {\n const map = new Map<string, FilterOption>()\n existing.forEach((opt) => map.set(opt.value, opt))\n next.forEach((opt) => map.set(opt.value, opt))\n return Array.from(map.values()).sort((a, b) => a.label.localeCompare(b.label))\n}\n\nfunction normalizeNumberInput(value: unknown): number | null {\n if (typeof value === 'number') return Number.isNaN(value) ? null : value\n if (typeof value === 'string' && value.trim().length) {\n const parsed = Number(value)\n return Number.isNaN(parsed) ? null : parsed\n }\n return null\n}\n\nexport function SalesDocumentsTable({ kind }: { kind: SalesDocumentKind }) {\n const t = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [rows, setRows] = React.useState<SalesDocumentRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'createdAt', desc: true }])\n const [search, setSearch] = React.useState('')\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [isLoading, setLoading] = React.useState(false)\n const [cacheStatus, setCacheStatus] = React.useState<'hit' | 'miss' | null>(null)\n const [reloadToken, setReloadToken] = React.useState(0)\n const [channelOptions, setChannelOptions] = React.useState<FilterOption[]>([])\n const [tagOptions, setTagOptions] = React.useState<FilterOption[]>([])\n const [customerOptions, setCustomerOptions] = React.useState<FilterOption[]>([])\n const [statusMap, setStatusMap] = React.useState<DictionaryMap>({})\n\n const resource = kind === 'order' ? 'orders' : 'quotes'\n const entityId = kind === 'order' ? E.sales.sales_order : E.sales.sales_quote\n const title = kind === 'order'\n ? t('sales.documents.list.ordersTitle', 'Sales orders')\n : t('sales.documents.list.quotesTitle', 'Sales quotes')\n const subtitle = t(\n 'sales.documents.list.subtitle',\n 'Review documents with customer context, totals, and channels.'\n )\n\n const fetchChannelOptions = React.useCallback(async (query?: string): Promise<FilterOption[]> => {\n const params = new URLSearchParams({ page: '1', pageSize: '50' })\n if (query && query.trim()) params.set('search', query.trim())\n try {\n const call = await apiCall<{ items?: unknown[] }>(`/api/sales/channels?${params.toString()}`)\n if (!call.ok) return []\n const items = Array.isArray(call.result?.items) ? call.result!.items : []\n return items\n .map((item: any): FilterOption | null => {\n const id = typeof item?.id === 'string' ? item.id : null\n const name = typeof item?.name === 'string' ? item.name : null\n if (!id || !name) return null\n return { value: id, label: name }\n })\n .filter((opt): opt is FilterOption => opt !== null)\n } catch {\n return []\n }\n }, [])\n\n const fetchTagOptions = React.useCallback(async (query?: string): Promise<FilterOption[]> => {\n const params = new URLSearchParams({ page: '1', pageSize: '50' })\n if (query && query.trim()) params.set('search', query.trim())\n try {\n const call = await apiCall<{ items?: unknown[] }>(`/api/sales/tags?${params.toString()}`)\n if (!call.ok) return []\n const items = Array.isArray(call.result?.items) ? call.result!.items : []\n return items\n .map((item: any): FilterOption | null => {\n const id = typeof item?.id === 'string' ? item.id : null\n const label = typeof item?.label === 'string' ? item.label : null\n if (!id || !label) return null\n return { value: id, label }\n })\n .filter((opt): opt is FilterOption => opt !== null)\n } catch {\n return []\n }\n }, [])\n\n const fetchCustomerOptions = React.useCallback(async (query?: string): Promise<FilterOption[]> => {\n const params = new URLSearchParams({ page: '1', pageSize: '20' })\n if (query && query.trim().length) params.set('search', query.trim())\n try {\n const [people, companies] = await Promise.all([\n apiCall<{ items?: unknown[] }>(`/api/customers/people?${params.toString()}`),\n apiCall<{ items?: unknown[] }>(`/api/customers/companies?${params.toString()}`),\n ])\n const peopleItems = Array.isArray(people.result?.items) ? people.result?.items ?? [] : []\n const companyItems = Array.isArray(companies.result?.items) ? companies.result?.items ?? [] : []\n const parseOption = (item: any, kind: 'person' | 'company'): FilterOption | null => {\n const id = typeof item?.id === 'string' ? item.id : null\n if (!id) return null\n const name =\n typeof item?.display_name === 'string' && item.display_name.trim().length\n ? item.display_name\n : typeof item?.name === 'string' && item.name.trim().length\n ? item.name\n : id\n const email =\n typeof item?.primary_email === 'string' && item.primary_email.trim().length\n ? item.primary_email.trim()\n : null\n const label = email ? `${name} (${email})` : name\n return { value: id, label: kind === 'company' ? label : label }\n }\n const options = [...peopleItems.map((i) => parseOption(i, 'person')), ...companyItems.map((i) => parseOption(i, 'company'))]\n .filter((opt): opt is FilterOption => !!opt)\n return options\n } catch {\n return []\n }\n }, [])\n\n const loadStatusMap = React.useCallback(async () => {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '100' })\n const response = await apiCall<{ items?: Array<Record<string, unknown>> }>(\n `/api/sales/order-statuses?${params.toString()}`,\n undefined,\n { fallback: { items: [] } }\n )\n const entries = normalizeDictionaryEntries(response.result?.items ?? [])\n setStatusMap(createDictionaryMap(entries))\n } catch (err) {\n console.error('sales.documents.statuses.load', err)\n setStatusMap({})\n }\n }, [])\n\n const loadChannelOptions = React.useCallback(\n async (query?: string) => {\n const opts = await fetchChannelOptions(query)\n if (opts.length) setChannelOptions((prev) => mergeOptions(prev, opts))\n return opts\n },\n [fetchChannelOptions]\n )\n\n const loadTagOptions = React.useCallback(\n async (query?: string) => {\n const opts = await fetchTagOptions(query)\n if (opts.length) setTagOptions((prev) => mergeOptions(prev, opts))\n return opts\n },\n [fetchTagOptions]\n )\n\n const loadCustomerOptions = React.useCallback(\n async (query?: string) => {\n const opts = await fetchCustomerOptions(query)\n if (opts.length) setCustomerOptions((prev) => mergeOptions(prev, opts))\n return opts\n },\n [fetchCustomerOptions]\n )\n\n React.useEffect(() => {\n loadChannelOptions().catch(() => {})\n loadTagOptions().catch(() => {})\n loadCustomerOptions().catch(() => {})\n loadStatusMap().catch(() => setStatusMap({}))\n }, [loadChannelOptions, loadCustomerOptions, loadStatusMap, loadTagOptions, scopeVersion])\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'channelId',\n label: t('sales.documents.list.filters.channel', 'Channel'),\n type: 'select',\n options: channelOptions,\n loadOptions: loadChannelOptions,\n },\n {\n id: 'date',\n label: t('sales.documents.list.filters.date', 'Date'),\n type: 'dateRange',\n },\n {\n id: 'lineItemCountMin',\n label: t('sales.documents.list.filters.itemsMin', 'Min items'),\n type: 'text',\n },\n {\n id: 'lineItemCountMax',\n label: t('sales.documents.list.filters.itemsMax', 'Max items'),\n type: 'text',\n },\n {\n id: 'totalNetMin',\n label: t('sales.documents.list.filters.totalNetMin', 'Min total (net)'),\n type: 'text',\n },\n {\n id: 'totalNetMax',\n label: t('sales.documents.list.filters.totalNetMax', 'Max total (net)'),\n type: 'text',\n },\n {\n id: 'totalGrossMin',\n label: t('sales.documents.list.filters.totalGrossMin', 'Min total (gross)'),\n type: 'text',\n },\n {\n id: 'totalGrossMax',\n label: t('sales.documents.list.filters.totalGrossMax', 'Max total (gross)'),\n type: 'text',\n },\n {\n id: 'customerId',\n label: t('sales.documents.list.filters.customer', 'Customer'),\n type: 'tags',\n options: customerOptions,\n loadOptions: loadCustomerOptions,\n placeholder: t('sales.documents.list.filters.customerPlaceholder', 'Search customers'),\n formatValue: (val: string) => {\n const match = customerOptions.find((opt) => opt.value === val)\n return match?.label ?? val\n },\n },\n {\n id: 'tagIds',\n label: t('sales.documents.list.filters.tags', 'Tags'),\n type: 'tags',\n options: tagOptions,\n loadOptions: loadTagOptions,\n },\n ], [channelOptions, loadChannelOptions, loadTagOptions, tagOptions, t])\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', String(PAGE_SIZE))\n if (search.trim()) params.set('search', search.trim())\n const sort = sorting[0]\n if (sort?.id) {\n params.set('sortField', sort.id)\n params.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n const channelId = typeof filterValues.channelId === 'string' ? filterValues.channelId : ''\n if (channelId) params.set('channelId', channelId)\n const customerIds = Array.isArray(filterValues.customerId)\n ? filterValues.customerId\n .map((value) => (typeof value === 'string' ? value.trim() : String(value || '').trim()))\n .filter((value) => value.length > 0)\n : []\n if (customerIds.length > 0) {\n params.set('customerId', customerIds[0])\n }\n const date = filterValues.date\n if (date && typeof date === 'object') {\n if (date.from) params.set('dateFrom', date.from)\n if (date.to) params.set('dateTo', date.to)\n }\n const numberFilters: Array<[keyof FilterValues, string]> = [\n ['lineItemCountMin', 'lineItemCountMin'],\n ['lineItemCountMax', 'lineItemCountMax'],\n ['totalNetMin', 'totalNetMin'],\n ['totalNetMax', 'totalNetMax'],\n ['totalGrossMin', 'totalGrossMin'],\n ['totalGrossMax', 'totalGrossMax'],\n ]\n numberFilters.forEach(([key, queryKey]) => {\n const value = normalizeNumberInput((filterValues as any)[key])\n if (value != null) params.set(queryKey, String(value))\n })\n const tagIds = Array.isArray(filterValues.tagIds)\n ? filterValues.tagIds.map((value) => (typeof value === 'string' ? value.trim() : String(value || '').trim())).filter((v) => v.length > 0)\n : []\n if (tagIds.length > 0) {\n params.set('tagIds', tagIds.join(','))\n }\n Object.entries(filterValues).forEach(([key, value]) => {\n if (!key.startsWith('cf_') || value == null) return\n if (Array.isArray(value)) {\n const normalized = value\n .map((item) => {\n if (item == null) return ''\n if (typeof item === 'string') return item.trim()\n return String(item).trim()\n })\n .filter((item) => item.length > 0)\n if (normalized.length) params.set(key, normalized.join(','))\n } else if (typeof value === 'object') {\n return\n } else if (value !== '') {\n const stringValue = typeof value === 'string' ? value.trim() : String(value)\n if (stringValue) params.set(key, stringValue)\n }\n })\n return params.toString()\n }, [filterValues, page, search, sorting])\n\n const currentParams = React.useMemo(() => Object.fromEntries(new URLSearchParams(queryParams)), [queryParams])\n\n const exportConfig = React.useMemo(() => ({\n view: {\n getUrl: (format: DataTableExportFormat) =>\n buildCrudExportUrl(`sales/${resource}`, { ...currentParams, exportScope: 'view' }, format),\n },\n full: {\n getUrl: (format: DataTableExportFormat) =>\n buildCrudExportUrl(`sales/${resource}`, { ...currentParams, exportScope: 'full', all: 'true' }, format),\n },\n }), [currentParams, resource])\n\n const mapApiDocument = React.useCallback(\n (item: Record<string, unknown>): SalesDocumentRow => {\n const doc = item as ApiDocument\n const id = typeof doc.id === 'string' ? doc.id : ''\n const number = kind === 'order'\n ? doc.orderNumber ?? (item as any)?.order_number ?? id\n : doc.quoteNumber ?? (item as any)?.quote_number ?? id\n const customerSnapshot = (doc.customerSnapshot ?? null) as CustomerSnapshot | null\n const customerName = resolveCustomerName(customerSnapshot, doc.customerEntityId ?? null)\n const customerEmail = resolveCustomerEmail(customerSnapshot)\n const totalNet = toNumber(doc.grandTotalNetAmount)\n const totalGross = toNumber(doc.grandTotalGrossAmount)\n const placedAt = doc.placedAt ?? null\n const validUntil = doc.validUntil ?? null\n const createdAt = doc.createdAt ?? null\n const date = placedAt ?? validUntil ?? createdAt ?? null\n return withDataTableNamespaces({\n id,\n number,\n status: doc.status ?? null,\n customerName,\n customerEmail,\n channelId: doc.channelId ?? null,\n lineItemCount: doc.lineItemCount ?? null,\n totalNet,\n totalGross,\n currency: doc.currencyCode ?? null,\n date,\n }, item)\n },\n [kind]\n )\n\n const loadDocuments = React.useCallback(async () => {\n setLoading(true)\n setCacheStatus(null)\n try {\n const call = await apiCall<DocumentsResponse>(`/api/sales/${resource}?${queryParams}`)\n if (!call.ok) {\n flash(t('sales.documents.list.errors.load', 'Failed to load documents.'), 'error')\n setRows([])\n setTotal(0)\n setTotalPages(1)\n return\n }\n const payload = call.result ?? {}\n const items = Array.isArray(payload.items) ? payload.items : []\n setRows(items.map((item) => mapApiDocument(item)))\n const count = typeof payload.total === 'number' ? payload.total : items.length\n setTotal(count)\n const pages = typeof payload.totalPages === 'number'\n ? payload.totalPages\n : Math.max(1, Math.ceil(count / PAGE_SIZE))\n setTotalPages(pages)\n setCacheStatus(call.cacheStatus ?? null)\n } catch (err) {\n console.error('sales.documents.list', err)\n flash(t('sales.documents.list.errors.load', 'Failed to load documents.'), 'error')\n } finally {\n setLoading(false)\n }\n }, [mapApiDocument, queryParams, resource, t])\n\n React.useEffect(() => {\n void loadDocuments()\n }, [loadDocuments, reloadToken, scopeVersion])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n setFilterValues(values)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n }, [])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [])\n\n const handleRefresh = React.useCallback(() => {\n setReloadToken((token) => token + 1)\n }, [])\n\n const handleDelete = React.useCallback(\n async (row: SalesDocumentRow) => {\n const confirmMessage =\n kind === 'order'\n ? t(\n 'sales.documents.list.table.deleteOrderConfirm',\n 'Delete this sales order? Related shipments, payments, addresses, and items will be removed.'\n )\n : t(\n 'sales.documents.list.table.deleteQuoteConfirm',\n 'Delete this sales quote? Related addresses, comments, and items will be removed.'\n )\n const confirmed = await confirm({\n title: confirmMessage,\n variant: 'destructive',\n })\n if (!confirmed) return\n try {\n const result = await deleteCrud(`sales/${resource}`, row.id, {\n errorMessage: t('sales.documents.list.table.deleteError', 'Failed to delete document.'),\n })\n if (result.ok) {\n flash(\n kind === 'order'\n ? t('sales.documents.list.table.orderDeleted', 'Sales order deleted.')\n : t('sales.documents.list.table.quoteDeleted', 'Sales quote deleted.'),\n 'success'\n )\n handleRefresh()\n }\n } catch (err) {\n console.error('sales.documents.delete', err)\n flash(t('sales.documents.list.table.deleteError', 'Failed to delete document.'), 'error')\n }\n },\n [confirm, handleRefresh, kind, resource, t]\n )\n\n const handleRowClick = React.useCallback((row: SalesDocumentRow) => {\n router.push(`/backend/sales/${resource}/${row.id}?kind=${kind}`)\n }, [kind, resource, router])\n\n const columns = React.useMemo<ColumnDef<SalesDocumentRow>[]>(() => [\n {\n id: 'number',\n accessorKey: 'number',\n header: kind === 'order'\n ? t('sales.documents.list.table.order', 'Order')\n : t('sales.documents.list.table.quote', 'Quote'),\n cell: ({ row }) => (\n <div className=\"flex flex-col\">\n <span className=\"font-semibold\">{row.original.number}</span>\n {row.original.status ? (\n <DictionaryValue\n value={row.original.status}\n map={statusMap}\n fallback={<span className=\"text-xs text-muted-foreground\">{row.original.status}</span>}\n className=\"text-xs text-muted-foreground font-medium\"\n iconWrapperClassName=\"inline-flex h-5 w-5 items-center justify-center rounded bg-muted text-muted-foreground\"\n iconClassName=\"h-3.5 w-3.5\"\n colorClassName=\"h-3 w-3 rounded-full border border-border/70\"\n />\n ) : null}\n </div>\n ),\n meta: { sticky: true },\n },\n {\n accessorKey: 'customerName',\n header: t('sales.documents.list.table.customer', 'Customer'),\n cell: ({ row }) => (\n <div className=\"flex flex-col\">\n <span className=\"text-sm font-medium\">\n {row.original.customerName ?? t('sales.documents.list.table.noCustomer', 'No customer')}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {row.original.customerEmail ?? t('sales.documents.list.table.noEmail', 'No email')}\n </span>\n </div>\n ),\n enableSorting: false,\n },\n {\n accessorKey: 'channelId',\n header: t('sales.documents.list.table.channel', 'Channel'),\n cell: ({ row }) => {\n const channelId = row.original.channelId\n if (!channelId) return <span className=\"text-xs text-muted-foreground\">{t('sales.documents.list.table.unassigned', 'Unassigned')}</span>\n const channel = channelOptions.find((opt) => opt.value === channelId)\n return (\n <span className=\"text-sm\">{channel?.label ?? channelId}</span>\n )\n },\n enableSorting: false,\n },\n {\n id: 'lineItemCount',\n accessorKey: 'lineItemCount',\n header: t('sales.documents.list.table.items', 'Items'),\n cell: ({ row }) => (\n <span className=\"text-sm font-semibold\">{typeof row.original.lineItemCount === 'number' ? row.original.lineItemCount : '\u2014'}</span>\n ),\n },\n {\n id: 'grandTotalNetAmount',\n accessorKey: 'totalNet',\n header: t('sales.documents.list.table.totalNet', 'Total (net)'),\n cell: ({ row }) => (\n <span className=\"text-sm\">{formatCurrency(row.original.totalNet ?? null, row.original.currency)}</span>\n ),\n },\n {\n id: 'grandTotalGrossAmount',\n accessorKey: 'totalGross',\n header: t('sales.documents.list.table.totalGross', 'Total (gross)'),\n cell: ({ row }) => (\n <span className=\"text-sm\">{formatCurrency(row.original.totalGross ?? null, row.original.currency)}</span>\n ),\n },\n {\n id: 'createdAt',\n accessorKey: 'date',\n header: t('sales.documents.list.table.date', 'Date'),\n cell: ({ row }) =>\n row.original.date\n ? <span className=\"text-xs text-muted-foreground\">{new Date(row.original.date).toLocaleString()}</span>\n : <span className=\"text-xs text-muted-foreground\">\u2014</span>,\n },\n ], [channelOptions, kind, statusMap, t])\n\n const emptyLabel = kind === 'order'\n ? t('sales.documents.list.table.emptyOrders', 'No orders yet.')\n : t('sales.documents.list.table.emptyQuotes', 'No quotes yet.')\n\n return (\n <Page>\n <PageBody>\n <DataTable<SalesDocumentRow>\n title={(\n <div className=\"flex flex-col\">\n <span>{title}</span>\n <span className=\"text-sm font-normal text-muted-foreground\">{subtitle}</span>\n </div>\n )}\n actions={(\n <Button asChild>\n <Link href={`/backend/sales/documents/create?kind=${kind}`}>\n {t('sales.documents.create.title', 'Create sales document')}\n </Link>\n </Button>\n )}\n columns={columns}\n data={rows}\n sorting={sorting}\n onSortingChange={setSorting}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={\n kind === 'order'\n ? t('sales.documents.list.search.orders', 'Search orders\u2026')\n : t('sales.documents.list.search.quotes', 'Search quotes\u2026')\n }\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n entityId={entityId}\n exporter={exportConfig}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n onPageChange: setPage,\n cacheStatus,\n }}\n refreshButton={{\n label: t('sales.documents.list.table.refresh', 'Refresh'),\n onRefresh: handleRefresh,\n isRefreshing: isLoading,\n }}\n rowActions={(row) => (\n <RowActions\n items={[\n {\n id: 'open',\n label: t('sales.documents.list.table.open', 'Open'),\n href: `/backend/sales/${resource}/${row.id}?kind=${kind}`,\n },\n {\n id: 'delete',\n label:\n kind === 'order'\n ? t('sales.documents.list.table.deleteOrder', 'Delete order')\n : t('sales.documents.list.table.deleteQuote', 'Delete quote'),\n onSelect: () => handleDelete(row),\n },\n ]}\n />\n )}\n onRowClick={handleRowClick}\n emptyState={\n <div className=\"py-10 text-center text-sm text-muted-foreground\">\n {emptyLabel}\n </div>\n }\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n\nexport default SalesDocumentsTable\n"],
5
+ "mappings": "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",
6
6
  "names": ["kind"]
7
7
  }
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  import Link from "next/link";
5
5
  import { useRouter } from "next/navigation";
6
6
  import { Page, PageBody } from "@open-mercato/ui/backend/Page";
7
- import { DataTable } from "@open-mercato/ui/backend/DataTable";
7
+ import { DataTable, withDataTableNamespaces } from "@open-mercato/ui/backend/DataTable";
8
8
  import { Badge } from "@open-mercato/ui/primitives/badge";
9
9
  import { Button } from "@open-mercato/ui/primitives/button";
10
10
  import { readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
@@ -152,7 +152,7 @@ function mapLeaveRequest(item) {
152
152
  const status = item.status === "approved" || item.status === "rejected" ? item.status : "pending";
153
153
  const reason = typeof item.unavailabilityReasonValue === "string" ? item.unavailabilityReasonValue : typeof item.unavailability_reason_value === "string" ? item.unavailability_reason_value : null;
154
154
  const updatedAt = typeof item.updatedAt === "string" ? item.updatedAt : typeof item.updated_at === "string" ? item.updated_at : null;
155
- return {
155
+ return withDataTableNamespaces({
156
156
  id,
157
157
  memberName,
158
158
  startDate,
@@ -160,7 +160,7 @@ function mapLeaveRequest(item) {
160
160
  status,
161
161
  reason,
162
162
  updatedAt
163
- };
163
+ }, item);
164
164
  }
165
165
  function formatDateRange(start, end) {
166
166
  const startLabel = formatDateLabel(start);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/staff/backend/staff/leave-requests/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nconst PAGE_SIZE = 50\n\ntype LeaveRequestRow = {\n id: string\n memberName: string | null\n startDate: string | null\n endDate: string | null\n status: 'pending' | 'approved' | 'rejected'\n reason: string | null\n updatedAt: string | null\n}\n\ntype LeaveRequestsResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\nexport default function StaffLeaveRequestsPage() {\n const t = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const [rows, setRows] = React.useState<LeaveRequestRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(true)\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'startDate', desc: true }])\n\n const labels = React.useMemo(() => ({\n title: t('staff.leaveRequests.page.title', 'Leave requests'),\n table: {\n member: t('staff.leaveRequests.table.member', 'Team member'),\n dates: t('staff.leaveRequests.table.dates', 'Dates'),\n status: t('staff.leaveRequests.table.status', 'Status'),\n reason: t('staff.leaveRequests.table.reason', 'Reason'),\n updatedAt: t('staff.leaveRequests.table.updatedAt', 'Updated'),\n empty: t('staff.leaveRequests.table.empty', 'No leave requests yet.'),\n search: t('staff.leaveRequests.table.search', 'Search leave requests...'),\n },\n actions: {\n add: t('staff.leaveRequests.actions.add', 'New request'),\n refresh: t('staff.leaveRequests.actions.refresh', 'Refresh'),\n },\n errors: {\n load: t('staff.leaveRequests.errors.load', 'Failed to load leave requests.'),\n },\n }), [t])\n\n const columns = React.useMemo<ColumnDef<LeaveRequestRow>[]>(() => [\n {\n accessorKey: 'memberName',\n header: labels.table.member,\n meta: { priority: 1, sticky: true },\n cell: ({ row }) => row.original.memberName ?? '-',\n },\n {\n accessorKey: 'startDate',\n header: labels.table.dates,\n meta: { priority: 2 },\n cell: ({ row }) => formatDateRange(row.original.startDate, row.original.endDate),\n },\n {\n accessorKey: 'status',\n header: labels.table.status,\n meta: { priority: 3 },\n cell: ({ row }) => (\n <Badge variant={resolveStatusVariant(row.original.status)}>\n {t(`staff.leaveRequests.status.${row.original.status}`, row.original.status)}\n </Badge>\n ),\n },\n {\n accessorKey: 'reason',\n header: labels.table.reason,\n meta: { priority: 4, truncate: true, maxWidth: '240px' },\n cell: ({ row }) => row.original.reason ?? '-',\n },\n {\n accessorKey: 'updatedAt',\n header: labels.table.updatedAt,\n meta: { priority: 5 },\n cell: ({ row }) => formatDateLabel(row.original.updatedAt),\n },\n ], [labels, t])\n\n const loadRows = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: String(PAGE_SIZE),\n })\n if (search.trim().length) params.set('search', search.trim())\n const activeSort = sorting[0]\n if (activeSort?.id) {\n params.set('sortField', activeSort.id)\n params.set('sortDir', activeSort.desc ? 'desc' : 'asc')\n }\n const payload = await readApiResultOrThrow<LeaveRequestsResponse>(\n `/api/staff/leave-requests?${params.toString()}`,\n undefined,\n { errorMessage: labels.errors.load },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setRows(items.map(mapLeaveRequest))\n setTotal(typeof payload.total === 'number' ? payload.total : items.length)\n setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)\n } catch {\n setRows([])\n setTotal(0)\n setTotalPages(1)\n } finally {\n setIsLoading(false)\n }\n }, [labels.errors.load, page, search, sorting])\n\n React.useEffect(() => {\n void loadRows()\n }, [loadRows, scopeVersion])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [])\n\n return (\n <Page>\n <PageBody>\n <DataTable<LeaveRequestRow>\n title={labels.title}\n data={rows}\n columns={columns}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={labels.table.search}\n emptyState={<p className=\"py-8 text-center text-sm text-muted-foreground\">{labels.table.empty}</p>}\n actions={(\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/leave-requests/create\">{labels.actions.add}</Link>\n </Button>\n )}\n refreshButton={{\n label: labels.actions.refresh,\n onRefresh: loadRows,\n isRefreshing: isLoading,\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n onPageChange: setPage,\n }}\n onRowClick={(row) => {\n router.push(`/backend/staff/leave-requests/${encodeURIComponent(row.id)}`)\n }}\n />\n </PageBody>\n </Page>\n )\n}\n\nfunction mapLeaveRequest(item: Record<string, unknown>): LeaveRequestRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const member = item.member && typeof item.member === 'object'\n ? item.member as { displayName?: unknown }\n : null\n const memberName = typeof member?.displayName === 'string'\n ? member.displayName\n : null\n const startDate = typeof item.startDate === 'string'\n ? item.startDate\n : typeof item.start_date === 'string'\n ? item.start_date\n : null\n const endDate = typeof item.endDate === 'string'\n ? item.endDate\n : typeof item.end_date === 'string'\n ? item.end_date\n : null\n const status = item.status === 'approved' || item.status === 'rejected' ? item.status : 'pending'\n const reason = typeof item.unavailabilityReasonValue === 'string'\n ? item.unavailabilityReasonValue\n : typeof item.unavailability_reason_value === 'string'\n ? item.unavailability_reason_value\n : null\n const updatedAt = typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null\n return {\n id,\n memberName,\n startDate,\n endDate,\n status,\n reason,\n updatedAt,\n }\n}\n\nfunction formatDateRange(start?: string | null, end?: string | null): string {\n const startLabel = formatDateLabel(start)\n const endLabel = formatDateLabel(end)\n if (startLabel && endLabel) return `${startLabel} -> ${endLabel}`\n return startLabel || endLabel || '-'\n}\n\nfunction formatDateLabel(value?: string | null): string {\n if (!value) return ''\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return value\n return date.toLocaleDateString()\n}\n\nfunction resolveStatusVariant(status: 'pending' | 'approved' | 'rejected') {\n if (status === 'approved') return 'default'\n if (status === 'rejected') return 'destructive'\n return 'secondary'\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nconst PAGE_SIZE = 50\n\ntype LeaveRequestRow = {\n id: string\n memberName: string | null\n startDate: string | null\n endDate: string | null\n status: 'pending' | 'approved' | 'rejected'\n reason: string | null\n updatedAt: string | null\n}\n\ntype LeaveRequestsResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\nexport default function StaffLeaveRequestsPage() {\n const t = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const [rows, setRows] = React.useState<LeaveRequestRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(true)\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'startDate', desc: true }])\n\n const labels = React.useMemo(() => ({\n title: t('staff.leaveRequests.page.title', 'Leave requests'),\n table: {\n member: t('staff.leaveRequests.table.member', 'Team member'),\n dates: t('staff.leaveRequests.table.dates', 'Dates'),\n status: t('staff.leaveRequests.table.status', 'Status'),\n reason: t('staff.leaveRequests.table.reason', 'Reason'),\n updatedAt: t('staff.leaveRequests.table.updatedAt', 'Updated'),\n empty: t('staff.leaveRequests.table.empty', 'No leave requests yet.'),\n search: t('staff.leaveRequests.table.search', 'Search leave requests...'),\n },\n actions: {\n add: t('staff.leaveRequests.actions.add', 'New request'),\n refresh: t('staff.leaveRequests.actions.refresh', 'Refresh'),\n },\n errors: {\n load: t('staff.leaveRequests.errors.load', 'Failed to load leave requests.'),\n },\n }), [t])\n\n const columns = React.useMemo<ColumnDef<LeaveRequestRow>[]>(() => [\n {\n accessorKey: 'memberName',\n header: labels.table.member,\n meta: { priority: 1, sticky: true },\n cell: ({ row }) => row.original.memberName ?? '-',\n },\n {\n accessorKey: 'startDate',\n header: labels.table.dates,\n meta: { priority: 2 },\n cell: ({ row }) => formatDateRange(row.original.startDate, row.original.endDate),\n },\n {\n accessorKey: 'status',\n header: labels.table.status,\n meta: { priority: 3 },\n cell: ({ row }) => (\n <Badge variant={resolveStatusVariant(row.original.status)}>\n {t(`staff.leaveRequests.status.${row.original.status}`, row.original.status)}\n </Badge>\n ),\n },\n {\n accessorKey: 'reason',\n header: labels.table.reason,\n meta: { priority: 4, truncate: true, maxWidth: '240px' },\n cell: ({ row }) => row.original.reason ?? '-',\n },\n {\n accessorKey: 'updatedAt',\n header: labels.table.updatedAt,\n meta: { priority: 5 },\n cell: ({ row }) => formatDateLabel(row.original.updatedAt),\n },\n ], [labels, t])\n\n const loadRows = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: String(PAGE_SIZE),\n })\n if (search.trim().length) params.set('search', search.trim())\n const activeSort = sorting[0]\n if (activeSort?.id) {\n params.set('sortField', activeSort.id)\n params.set('sortDir', activeSort.desc ? 'desc' : 'asc')\n }\n const payload = await readApiResultOrThrow<LeaveRequestsResponse>(\n `/api/staff/leave-requests?${params.toString()}`,\n undefined,\n { errorMessage: labels.errors.load },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setRows(items.map(mapLeaveRequest))\n setTotal(typeof payload.total === 'number' ? payload.total : items.length)\n setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)\n } catch {\n setRows([])\n setTotal(0)\n setTotalPages(1)\n } finally {\n setIsLoading(false)\n }\n }, [labels.errors.load, page, search, sorting])\n\n React.useEffect(() => {\n void loadRows()\n }, [loadRows, scopeVersion])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [])\n\n return (\n <Page>\n <PageBody>\n <DataTable<LeaveRequestRow>\n title={labels.title}\n data={rows}\n columns={columns}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={labels.table.search}\n emptyState={<p className=\"py-8 text-center text-sm text-muted-foreground\">{labels.table.empty}</p>}\n actions={(\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/leave-requests/create\">{labels.actions.add}</Link>\n </Button>\n )}\n refreshButton={{\n label: labels.actions.refresh,\n onRefresh: loadRows,\n isRefreshing: isLoading,\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n onPageChange: setPage,\n }}\n onRowClick={(row) => {\n router.push(`/backend/staff/leave-requests/${encodeURIComponent(row.id)}`)\n }}\n />\n </PageBody>\n </Page>\n )\n}\n\nfunction mapLeaveRequest(item: Record<string, unknown>): LeaveRequestRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const member = item.member && typeof item.member === 'object'\n ? item.member as { displayName?: unknown }\n : null\n const memberName = typeof member?.displayName === 'string'\n ? member.displayName\n : null\n const startDate = typeof item.startDate === 'string'\n ? item.startDate\n : typeof item.start_date === 'string'\n ? item.start_date\n : null\n const endDate = typeof item.endDate === 'string'\n ? item.endDate\n : typeof item.end_date === 'string'\n ? item.end_date\n : null\n const status = item.status === 'approved' || item.status === 'rejected' ? item.status : 'pending'\n const reason = typeof item.unavailabilityReasonValue === 'string'\n ? item.unavailabilityReasonValue\n : typeof item.unavailability_reason_value === 'string'\n ? item.unavailability_reason_value\n : null\n const updatedAt = typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null\n return withDataTableNamespaces({\n id,\n memberName,\n startDate,\n endDate,\n status,\n reason,\n updatedAt,\n }, item)\n}\n\nfunction formatDateRange(start?: string | null, end?: string | null): string {\n const startLabel = formatDateLabel(start)\n const endLabel = formatDateLabel(end)\n if (startLabel && endLabel) return `${startLabel} -> ${endLabel}`\n return startLabel || endLabel || '-'\n}\n\nfunction formatDateLabel(value?: string | null): string {\n if (!value) return ''\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return value\n return date.toLocaleDateString()\n}\n\nfunction resolveStatusVariant(status: 'pending' | 'approved' | 'rejected') {\n if (status === 'approved') return 'default'\n if (status === 'rejected') return 'destructive'\n return 'secondary'\n}\n"],
5
+ "mappings": ";AAkFQ;AAhFR,YAAY,WAAW;AACvB,OAAO,UAAU;AACjB,SAAS,iBAAiB;AAE1B,SAAS,MAAM,gBAAgB;AAC/B,SAAS,WAAW,+BAA+B;AACnD,SAAS,aAAa;AACtB,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC,SAAS,mCAAmC;AAC5C,SAAS,YAAY;AAErB,MAAM,YAAY;AAkBH,SAAR,yBAA0C;AAC/C,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,UAAU;AACzB,QAAM,eAAe,4BAA4B;AACjD,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAA4B,CAAC,CAAC;AAC5D,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAS,CAAC;AACxC,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAS,CAAC;AAC1C,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,CAAC;AACpD,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE;AAC7C,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,IAAI;AACrD,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAuB,CAAC,EAAE,IAAI,aAAa,MAAM,KAAK,CAAC,CAAC;AAE5F,QAAM,SAAS,MAAM,QAAQ,OAAO;AAAA,IAClC,OAAO,EAAE,kCAAkC,gBAAgB;AAAA,IAC3D,OAAO;AAAA,MACL,QAAQ,EAAE,oCAAoC,aAAa;AAAA,MAC3D,OAAO,EAAE,mCAAmC,OAAO;AAAA,MACnD,QAAQ,EAAE,oCAAoC,QAAQ;AAAA,MACtD,QAAQ,EAAE,oCAAoC,QAAQ;AAAA,MACtD,WAAW,EAAE,uCAAuC,SAAS;AAAA,MAC7D,OAAO,EAAE,mCAAmC,wBAAwB;AAAA,MACpE,QAAQ,EAAE,oCAAoC,0BAA0B;AAAA,IAC1E;AAAA,IACA,SAAS;AAAA,MACP,KAAK,EAAE,mCAAmC,aAAa;AAAA,MACvD,SAAS,EAAE,uCAAuC,SAAS;AAAA,IAC7D;AAAA,IACA,QAAQ;AAAA,MACN,MAAM,EAAE,mCAAmC,gCAAgC;AAAA,IAC7E;AAAA,EACF,IAAI,CAAC,CAAC,CAAC;AAEP,QAAM,UAAU,MAAM,QAAsC,MAAM;AAAA,IAChE;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,OAAO,MAAM;AAAA,MACrB,MAAM,EAAE,UAAU,GAAG,QAAQ,KAAK;AAAA,MAClC,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,cAAc;AAAA,IAChD;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,OAAO,MAAM;AAAA,MACrB,MAAM,EAAE,UAAU,EAAE;AAAA,MACpB,MAAM,CAAC,EAAE,IAAI,MAAM,gBAAgB,IAAI,SAAS,WAAW,IAAI,SAAS,OAAO;AAAA,IACjF;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,OAAO,MAAM;AAAA,MACrB,MAAM,EAAE,UAAU,EAAE;AAAA,MACpB,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,SAAM,SAAS,qBAAqB,IAAI,SAAS,MAAM,GACrD,YAAE,8BAA8B,IAAI,SAAS,MAAM,IAAI,IAAI,SAAS,MAAM,GAC7E;AAAA,IAEJ;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,OAAO,MAAM;AAAA,MACrB,MAAM,EAAE,UAAU,GAAG,UAAU,MAAM,UAAU,QAAQ;AAAA,MACvD,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,UAAU;AAAA,IAC5C;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,OAAO,MAAM;AAAA,MACrB,MAAM,EAAE,UAAU,EAAE;AAAA,MACpB,MAAM,CAAC,EAAE,IAAI,MAAM,gBAAgB,IAAI,SAAS,SAAS;AAAA,IAC3D;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC,CAAC;AAEd,QAAM,WAAW,MAAM,YAAY,YAAY;AAC7C,iBAAa,IAAI;AACjB,QAAI;AACF,YAAM,SAAS,IAAI,gBAAgB;AAAA,QACjC,MAAM,OAAO,IAAI;AAAA,QACjB,UAAU,OAAO,SAAS;AAAA,MAC5B,CAAC;AACD,UAAI,OAAO,KAAK,EAAE,OAAQ,QAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AAC5D,YAAM,aAAa,QAAQ,CAAC;AAC5B,UAAI,YAAY,IAAI;AAClB,eAAO,IAAI,aAAa,WAAW,EAAE;AACrC,eAAO,IAAI,WAAW,WAAW,OAAO,SAAS,KAAK;AAAA,MACxD;AACA,YAAM,UAAU,MAAM;AAAA,QACpB,6BAA6B,OAAO,SAAS,CAAC;AAAA,QAC9C;AAAA,QACA,EAAE,cAAc,OAAO,OAAO,KAAK;AAAA,MACrC;AACA,YAAM,QAAQ,MAAM,QAAQ,QAAQ,KAAK,IAAI,QAAQ,QAAQ,CAAC;AAC9D,cAAQ,MAAM,IAAI,eAAe,CAAC;AAClC,eAAS,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,MAAM,MAAM;AACzE,oBAAc,OAAO,QAAQ,eAAe,WAAW,QAAQ,aAAa,CAAC;AAAA,IAC/E,QAAQ;AACN,cAAQ,CAAC,CAAC;AACV,eAAS,CAAC;AACV,oBAAc,CAAC;AAAA,IACjB,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,OAAO,OAAO,MAAM,MAAM,QAAQ,OAAO,CAAC;AAE9C,QAAM,UAAU,MAAM;AACpB,SAAK,SAAS;AAAA,EAChB,GAAG,CAAC,UAAU,YAAY,CAAC;AAE3B,QAAM,qBAAqB,MAAM,YAAY,CAAC,UAAkB;AAC9D,cAAU,KAAK;AACf,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,CAAC;AAEL,SACE,oBAAC,QACC,8BAAC,YACC;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,OAAO;AAAA,MACd,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,mBAAmB,OAAO,MAAM;AAAA,MAChC,YAAY,oBAAC,OAAE,WAAU,kDAAkD,iBAAO,MAAM,OAAM;AAAA,MAC9F,SACE,oBAAC,UAAO,SAAO,MAAC,MAAK,MACnB,8BAAC,QAAK,MAAK,wCAAwC,iBAAO,QAAQ,KAAI,GACxE;AAAA,MAEF,eAAe;AAAA,QACb,OAAO,OAAO,QAAQ;AAAA,QACtB,WAAW;AAAA,QACX,cAAc;AAAA,MAChB;AAAA,MACA,UAAQ;AAAA,MACR;AAAA,MACA,iBAAiB;AAAA,MACjB,YAAY;AAAA,QACV;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA,cAAc;AAAA,MAChB;AAAA,MACA,YAAY,CAAC,QAAQ;AACnB,eAAO,KAAK,iCAAiC,mBAAmB,IAAI,EAAE,CAAC,EAAE;AAAA,MAC3E;AAAA;AAAA,EACF,GACF,GACF;AAEJ;AAEA,SAAS,gBAAgB,MAAgD;AACvE,QAAM,KAAK,OAAO,KAAK,OAAO,WAAW,KAAK,KAAK;AACnD,QAAM,SAAS,KAAK,UAAU,OAAO,KAAK,WAAW,WACjD,KAAK,SACL;AACJ,QAAM,aAAa,OAAO,QAAQ,gBAAgB,WAC9C,OAAO,cACP;AACJ,QAAM,YAAY,OAAO,KAAK,cAAc,WACxC,KAAK,YACL,OAAO,KAAK,eAAe,WACzB,KAAK,aACL;AACN,QAAM,UAAU,OAAO,KAAK,YAAY,WACpC,KAAK,UACL,OAAO,KAAK,aAAa,WACvB,KAAK,WACL;AACN,QAAM,SAAS,KAAK,WAAW,cAAc,KAAK,WAAW,aAAa,KAAK,SAAS;AACxF,QAAM,SAAS,OAAO,KAAK,8BAA8B,WACrD,KAAK,4BACL,OAAO,KAAK,gCAAgC,WAC1C,KAAK,8BACL;AACN,QAAM,YAAY,OAAO,KAAK,cAAc,WACxC,KAAK,YACL,OAAO,KAAK,eAAe,WACzB,KAAK,aACL;AACN,SAAO,wBAAwB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG,IAAI;AACT;AAEA,SAAS,gBAAgB,OAAuB,KAA6B;AAC3E,QAAM,aAAa,gBAAgB,KAAK;AACxC,QAAM,WAAW,gBAAgB,GAAG;AACpC,MAAI,cAAc,SAAU,QAAO,GAAG,UAAU,OAAO,QAAQ;AAC/D,SAAO,cAAc,YAAY;AACnC;AAEA,SAAS,gBAAgB,OAA+B;AACtD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO;AACzC,SAAO,KAAK,mBAAmB;AACjC;AAEA,SAAS,qBAAqB,QAA6C;AACzE,MAAI,WAAW,WAAY,QAAO;AAClC,MAAI,WAAW,WAAY,QAAO;AAClC,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  import Link from "next/link";
5
5
  import { useRouter } from "next/navigation";
6
6
  import { Page, PageBody } from "@open-mercato/ui/backend/Page";
7
- import { DataTable } from "@open-mercato/ui/backend/DataTable";
7
+ import { DataTable, withDataTableNamespaces } from "@open-mercato/ui/backend/DataTable";
8
8
  import { Badge } from "@open-mercato/ui/primitives/badge";
9
9
  import { Button } from "@open-mercato/ui/primitives/button";
10
10
  import { readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
@@ -155,14 +155,14 @@ function mapLeaveRequest(item) {
155
155
  const status = item.status === "approved" || item.status === "rejected" ? item.status : "pending";
156
156
  const reason = typeof item.unavailabilityReasonValue === "string" ? item.unavailabilityReasonValue : typeof item.unavailability_reason_value === "string" ? item.unavailability_reason_value : null;
157
157
  const updatedAt = typeof item.updatedAt === "string" ? item.updatedAt : typeof item.updated_at === "string" ? item.updated_at : null;
158
- return {
158
+ return withDataTableNamespaces({
159
159
  id,
160
160
  startDate,
161
161
  endDate,
162
162
  status,
163
163
  reason,
164
164
  updatedAt
165
- };
165
+ }, item);
166
166
  }
167
167
  function formatDateRange(start, end) {
168
168
  const startLabel = formatDateLabel(start);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/staff/backend/staff/my-leave-requests/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nconst PAGE_SIZE = 50\n\ntype LeaveRequestRow = {\n id: string\n startDate: string | null\n endDate: string | null\n status: 'pending' | 'approved' | 'rejected'\n reason: string | null\n updatedAt: string | null\n}\n\ntype LeaveRequestsResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n viewer?: { memberId?: string | null; canSend?: boolean }\n}\n\nexport default function StaffMyLeaveRequestsPage() {\n const t = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const [rows, setRows] = React.useState<LeaveRequestRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(true)\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'startDate', desc: true }])\n const [memberId, setMemberId] = React.useState<string | null>(null)\n const [canSend, setCanSend] = React.useState(false)\n\n const labels = React.useMemo(() => ({\n title: t('staff.leaveRequests.my.title', 'My leave requests'),\n table: {\n dates: t('staff.leaveRequests.table.dates', 'Dates'),\n status: t('staff.leaveRequests.table.status', 'Status'),\n reason: t('staff.leaveRequests.table.reason', 'Reason'),\n updatedAt: t('staff.leaveRequests.table.updatedAt', 'Updated'),\n empty: t('staff.leaveRequests.table.empty', 'No leave requests yet.'),\n search: t('staff.leaveRequests.table.search', 'Search leave requests...'),\n },\n actions: {\n add: t('staff.leaveRequests.actions.add', 'New request'),\n refresh: t('staff.leaveRequests.actions.refresh', 'Refresh'),\n createProfile: t('staff.leaveRequests.actions.createProfile', 'Create my profile'),\n },\n errors: {\n load: t('staff.leaveRequests.errors.load', 'Failed to load leave requests.'),\n },\n }), [t])\n\n const columns = React.useMemo<ColumnDef<LeaveRequestRow>[]>(() => [\n {\n accessorKey: 'startDate',\n header: labels.table.dates,\n meta: { priority: 1, sticky: true },\n cell: ({ row }) => formatDateRange(row.original.startDate, row.original.endDate),\n },\n {\n accessorKey: 'status',\n header: labels.table.status,\n meta: { priority: 2 },\n cell: ({ row }) => (\n <Badge variant={resolveStatusVariant(row.original.status)}>\n {t(`staff.leaveRequests.status.${row.original.status}`, row.original.status)}\n </Badge>\n ),\n },\n {\n accessorKey: 'reason',\n header: labels.table.reason,\n meta: { priority: 3, truncate: true, maxWidth: '240px' },\n cell: ({ row }) => row.original.reason ?? '-',\n },\n {\n accessorKey: 'updatedAt',\n header: labels.table.updatedAt,\n meta: { priority: 4 },\n cell: ({ row }) => formatDateLabel(row.original.updatedAt),\n },\n ], [labels.table, t])\n\n const loadRows = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: String(PAGE_SIZE),\n })\n if (search.trim().length) params.set('search', search.trim())\n const activeSort = sorting[0]\n if (activeSort?.id) {\n params.set('sortField', activeSort.id)\n params.set('sortDir', activeSort.desc ? 'desc' : 'asc')\n }\n const payload = await readApiResultOrThrow<LeaveRequestsResponse>(\n `/api/staff/leave-requests?${params.toString()}`,\n undefined,\n { errorMessage: labels.errors.load },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setRows(items.map(mapLeaveRequest))\n setTotal(typeof payload.total === 'number' ? payload.total : items.length)\n setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)\n const viewerMemberId = typeof payload.viewer?.memberId === 'string' ? payload.viewer.memberId : null\n setMemberId(viewerMemberId)\n setCanSend(payload.viewer?.canSend === true)\n } catch {\n setRows([])\n setTotal(0)\n setTotalPages(1)\n setMemberId(null)\n setCanSend(false)\n } finally {\n setIsLoading(false)\n }\n }, [labels.errors.load, page, search, sorting])\n\n React.useEffect(() => {\n void loadRows()\n }, [loadRows, scopeVersion])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [])\n\n const emptyState = memberId\n ? <p className=\"py-8 text-center text-sm text-muted-foreground\">{labels.table.empty}</p>\n : (\n <div className=\"py-8 text-center text-sm text-muted-foreground space-y-3\">\n <p>{t('staff.leaveRequests.empty.profileRequired', 'Create your team member profile to submit leave requests.')}</p>\n <Button asChild size=\"sm\" variant=\"outline\">\n <Link href=\"/backend/staff/profile/create\">{labels.actions.createProfile}</Link>\n </Button>\n </div>\n )\n\n return (\n <Page>\n <PageBody>\n <DataTable<LeaveRequestRow>\n title={labels.title}\n data={rows}\n columns={columns}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={labels.table.search}\n emptyState={emptyState}\n actions={memberId && canSend ? (\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/my-leave-requests/create\">{labels.actions.add}</Link>\n </Button>\n ) : null}\n refreshButton={{\n label: labels.actions.refresh,\n onRefresh: loadRows,\n isRefreshing: isLoading,\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n onPageChange: setPage,\n }}\n onRowClick={(row) => {\n router.push(`/backend/staff/my-leave-requests/${encodeURIComponent(row.id)}`)\n }}\n />\n </PageBody>\n </Page>\n )\n}\n\nfunction mapLeaveRequest(item: Record<string, unknown>): LeaveRequestRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const startDate = typeof item.startDate === 'string'\n ? item.startDate\n : typeof item.start_date === 'string'\n ? item.start_date\n : null\n const endDate = typeof item.endDate === 'string'\n ? item.endDate\n : typeof item.end_date === 'string'\n ? item.end_date\n : null\n const status = item.status === 'approved' || item.status === 'rejected' ? item.status : 'pending'\n const reason = typeof item.unavailabilityReasonValue === 'string'\n ? item.unavailabilityReasonValue\n : typeof item.unavailability_reason_value === 'string'\n ? item.unavailability_reason_value\n : null\n const updatedAt = typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null\n return {\n id,\n startDate,\n endDate,\n status,\n reason,\n updatedAt,\n }\n}\n\nfunction formatDateRange(start?: string | null, end?: string | null): string {\n const startLabel = formatDateLabel(start)\n const endLabel = formatDateLabel(end)\n if (startLabel && endLabel) return `${startLabel} -> ${endLabel}`\n return startLabel || endLabel || '-'\n}\n\nfunction formatDateLabel(value?: string | null): string {\n if (!value) return ''\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return value\n return date.toLocaleDateString()\n}\n\nfunction resolveStatusVariant(status: 'pending' | 'approved' | 'rejected') {\n if (status === 'approved') return 'default'\n if (status === 'rejected') return 'destructive'\n return 'secondary'\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nconst PAGE_SIZE = 50\n\ntype LeaveRequestRow = {\n id: string\n startDate: string | null\n endDate: string | null\n status: 'pending' | 'approved' | 'rejected'\n reason: string | null\n updatedAt: string | null\n}\n\ntype LeaveRequestsResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n viewer?: { memberId?: string | null; canSend?: boolean }\n}\n\nexport default function StaffMyLeaveRequestsPage() {\n const t = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const [rows, setRows] = React.useState<LeaveRequestRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(true)\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'startDate', desc: true }])\n const [memberId, setMemberId] = React.useState<string | null>(null)\n const [canSend, setCanSend] = React.useState(false)\n\n const labels = React.useMemo(() => ({\n title: t('staff.leaveRequests.my.title', 'My leave requests'),\n table: {\n dates: t('staff.leaveRequests.table.dates', 'Dates'),\n status: t('staff.leaveRequests.table.status', 'Status'),\n reason: t('staff.leaveRequests.table.reason', 'Reason'),\n updatedAt: t('staff.leaveRequests.table.updatedAt', 'Updated'),\n empty: t('staff.leaveRequests.table.empty', 'No leave requests yet.'),\n search: t('staff.leaveRequests.table.search', 'Search leave requests...'),\n },\n actions: {\n add: t('staff.leaveRequests.actions.add', 'New request'),\n refresh: t('staff.leaveRequests.actions.refresh', 'Refresh'),\n createProfile: t('staff.leaveRequests.actions.createProfile', 'Create my profile'),\n },\n errors: {\n load: t('staff.leaveRequests.errors.load', 'Failed to load leave requests.'),\n },\n }), [t])\n\n const columns = React.useMemo<ColumnDef<LeaveRequestRow>[]>(() => [\n {\n accessorKey: 'startDate',\n header: labels.table.dates,\n meta: { priority: 1, sticky: true },\n cell: ({ row }) => formatDateRange(row.original.startDate, row.original.endDate),\n },\n {\n accessorKey: 'status',\n header: labels.table.status,\n meta: { priority: 2 },\n cell: ({ row }) => (\n <Badge variant={resolveStatusVariant(row.original.status)}>\n {t(`staff.leaveRequests.status.${row.original.status}`, row.original.status)}\n </Badge>\n ),\n },\n {\n accessorKey: 'reason',\n header: labels.table.reason,\n meta: { priority: 3, truncate: true, maxWidth: '240px' },\n cell: ({ row }) => row.original.reason ?? '-',\n },\n {\n accessorKey: 'updatedAt',\n header: labels.table.updatedAt,\n meta: { priority: 4 },\n cell: ({ row }) => formatDateLabel(row.original.updatedAt),\n },\n ], [labels.table, t])\n\n const loadRows = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: String(PAGE_SIZE),\n })\n if (search.trim().length) params.set('search', search.trim())\n const activeSort = sorting[0]\n if (activeSort?.id) {\n params.set('sortField', activeSort.id)\n params.set('sortDir', activeSort.desc ? 'desc' : 'asc')\n }\n const payload = await readApiResultOrThrow<LeaveRequestsResponse>(\n `/api/staff/leave-requests?${params.toString()}`,\n undefined,\n { errorMessage: labels.errors.load },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setRows(items.map(mapLeaveRequest))\n setTotal(typeof payload.total === 'number' ? payload.total : items.length)\n setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)\n const viewerMemberId = typeof payload.viewer?.memberId === 'string' ? payload.viewer.memberId : null\n setMemberId(viewerMemberId)\n setCanSend(payload.viewer?.canSend === true)\n } catch {\n setRows([])\n setTotal(0)\n setTotalPages(1)\n setMemberId(null)\n setCanSend(false)\n } finally {\n setIsLoading(false)\n }\n }, [labels.errors.load, page, search, sorting])\n\n React.useEffect(() => {\n void loadRows()\n }, [loadRows, scopeVersion])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [])\n\n const emptyState = memberId\n ? <p className=\"py-8 text-center text-sm text-muted-foreground\">{labels.table.empty}</p>\n : (\n <div className=\"py-8 text-center text-sm text-muted-foreground space-y-3\">\n <p>{t('staff.leaveRequests.empty.profileRequired', 'Create your team member profile to submit leave requests.')}</p>\n <Button asChild size=\"sm\" variant=\"outline\">\n <Link href=\"/backend/staff/profile/create\">{labels.actions.createProfile}</Link>\n </Button>\n </div>\n )\n\n return (\n <Page>\n <PageBody>\n <DataTable<LeaveRequestRow>\n title={labels.title}\n data={rows}\n columns={columns}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={labels.table.search}\n emptyState={emptyState}\n actions={memberId && canSend ? (\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/my-leave-requests/create\">{labels.actions.add}</Link>\n </Button>\n ) : null}\n refreshButton={{\n label: labels.actions.refresh,\n onRefresh: loadRows,\n isRefreshing: isLoading,\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n onPageChange: setPage,\n }}\n onRowClick={(row) => {\n router.push(`/backend/staff/my-leave-requests/${encodeURIComponent(row.id)}`)\n }}\n />\n </PageBody>\n </Page>\n )\n}\n\nfunction mapLeaveRequest(item: Record<string, unknown>): LeaveRequestRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const startDate = typeof item.startDate === 'string'\n ? item.startDate\n : typeof item.start_date === 'string'\n ? item.start_date\n : null\n const endDate = typeof item.endDate === 'string'\n ? item.endDate\n : typeof item.end_date === 'string'\n ? item.end_date\n : null\n const status = item.status === 'approved' || item.status === 'rejected' ? item.status : 'pending'\n const reason = typeof item.unavailabilityReasonValue === 'string'\n ? item.unavailabilityReasonValue\n : typeof item.unavailability_reason_value === 'string'\n ? item.unavailability_reason_value\n : null\n const updatedAt = typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null\n return withDataTableNamespaces({\n id,\n startDate,\n endDate,\n status,\n reason,\n updatedAt,\n }, item)\n}\n\nfunction formatDateRange(start?: string | null, end?: string | null): string {\n const startLabel = formatDateLabel(start)\n const endLabel = formatDateLabel(end)\n if (startLabel && endLabel) return `${startLabel} -> ${endLabel}`\n return startLabel || endLabel || '-'\n}\n\nfunction formatDateLabel(value?: string | null): string {\n if (!value) return ''\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return value\n return date.toLocaleDateString()\n}\n\nfunction resolveStatusVariant(status: 'pending' | 'approved' | 'rejected') {\n if (status === 'approved') return 'default'\n if (status === 'rejected') return 'destructive'\n return 'secondary'\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  import Link from "next/link";
5
5
  import { usePathname, useRouter, useSearchParams } from "next/navigation";
6
6
  import { Page, PageBody } from "@open-mercato/ui/backend/Page";
7
- import { DataTable } from "@open-mercato/ui/backend/DataTable";
7
+ import { DataTable, withDataTableNamespaces } from "@open-mercato/ui/backend/DataTable";
8
8
  import { RowActions } from "@open-mercato/ui/backend/RowActions";
9
9
  import { Button } from "@open-mercato/ui/primitives/button";
10
10
  import { BooleanIcon } from "@open-mercato/ui/backend/ValueIcons";
@@ -375,7 +375,7 @@ function mapApiTeamMember(item) {
375
375
  const teamId = typeof item.teamId === "string" ? item.teamId : typeof item.team_id === "string" ? item.team_id : null;
376
376
  const team = item.team && typeof item.team === "object" ? item.team : null;
377
377
  const teamName = typeof team?.name === "string" ? team.name : null;
378
- return {
378
+ return withDataTableNamespaces({
379
379
  id,
380
380
  displayName,
381
381
  description,
@@ -387,7 +387,7 @@ function mapApiTeamMember(item) {
387
387
  updatedAt,
388
388
  teamId,
389
389
  teamName
390
- };
390
+ }, item);
391
391
  }
392
392
  function compareGroupedRows(field, labels, left, right) {
393
393
  const leftTeam = (left.teamName ?? labels.unassignedTeam).toLocaleLowerCase();