@open-mercato/core 0.6.8-develop.7082.1.f2a845b020 → 0.6.8-develop.7090.1.4dbca7b350

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 (62) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/customers/components/DealsKpiStrip.js +7 -6
  3. package/dist/modules/customers/components/DealsKpiStrip.js.map +2 -2
  4. package/dist/modules/customers/components/detail/CompanyKpiBar.js +5 -4
  5. package/dist/modules/customers/components/detail/CompanyKpiBar.js.map +2 -2
  6. package/dist/modules/customers/components/detail/DealsSection.js +6 -5
  7. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  8. package/dist/modules/customers/components/detail/utils.js +5 -5
  9. package/dist/modules/customers/components/detail/utils.js.map +2 -2
  10. package/dist/modules/sales/backend/sales/documents/[id]/page.js +10 -8
  11. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  12. package/dist/modules/sales/components/PriceWithCurrency.js +7 -5
  13. package/dist/modules/sales/components/PriceWithCurrency.js.map +2 -2
  14. package/dist/modules/sales/components/documents/AdjustmentsSection.js +8 -6
  15. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  16. package/dist/modules/sales/components/documents/ItemsSection.js +14 -7
  17. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  18. package/dist/modules/sales/components/documents/LineItemDialog.js +8 -7
  19. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  20. package/dist/modules/sales/components/documents/PaymentsSection.js +9 -8
  21. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  22. package/dist/modules/sales/components/documents/ReturnsSection.js +8 -6
  23. package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
  24. package/dist/modules/sales/components/documents/SalesOrderDraftLines.js +5 -4
  25. package/dist/modules/sales/components/documents/SalesOrderDraftLines.js.map +2 -2
  26. package/dist/modules/sales/components/documents/ShipmentDialog.js +5 -4
  27. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  28. package/dist/modules/sales/components/documents/ShipmentsSection.js +8 -6
  29. package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
  30. package/dist/modules/sales/components/documents/lineItemUtils.js +2 -2
  31. package/dist/modules/sales/components/documents/lineItemUtils.js.map +2 -2
  32. package/dist/modules/sales/data/entities.js +8 -2
  33. package/dist/modules/sales/data/entities.js.map +2 -2
  34. package/dist/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.js +32 -0
  35. package/dist/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.js.map +7 -0
  36. package/dist/modules/staff/backend/staff/timesheets/page.js +29 -18
  37. package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
  38. package/package.json +7 -7
  39. package/src/modules/auth/i18n/de.json +3 -0
  40. package/src/modules/auth/i18n/en.json +3 -0
  41. package/src/modules/auth/i18n/es.json +3 -0
  42. package/src/modules/auth/i18n/ko.json +3 -0
  43. package/src/modules/auth/i18n/pl.json +3 -0
  44. package/src/modules/customers/components/DealsKpiStrip.tsx +7 -7
  45. package/src/modules/customers/components/detail/CompanyKpiBar.tsx +5 -4
  46. package/src/modules/customers/components/detail/DealsSection.tsx +11 -5
  47. package/src/modules/customers/components/detail/utils.ts +15 -5
  48. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +14 -8
  49. package/src/modules/sales/components/PriceWithCurrency.tsx +17 -5
  50. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +6 -5
  51. package/src/modules/sales/components/documents/ItemsSection.tsx +8 -1
  52. package/src/modules/sales/components/documents/LineItemDialog.tsx +9 -8
  53. package/src/modules/sales/components/documents/PaymentsSection.tsx +9 -8
  54. package/src/modules/sales/components/documents/ReturnsSection.tsx +6 -5
  55. package/src/modules/sales/components/documents/SalesOrderDraftLines.tsx +5 -4
  56. package/src/modules/sales/components/documents/ShipmentDialog.tsx +5 -4
  57. package/src/modules/sales/components/documents/ShipmentsSection.tsx +6 -5
  58. package/src/modules/sales/components/documents/lineItemUtils.ts +7 -2
  59. package/src/modules/sales/data/entities.ts +6 -0
  60. package/src/modules/sales/migrations/.snapshot-open-mercato.json +60 -0
  61. package/src/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.ts +87 -0
  62. package/src/modules/staff/backend/staff/timesheets/page.tsx +12 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/components/detail/DealsSection.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Link2, Pencil, Plus } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { LinkEntityDialog } from '../linking/LinkEntityDialog'\nimport { createDealLinkAdapter } from '../linking/adapters/dealAdapter'\nimport { LoadingMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { hasMoreFromPage } from '@open-mercato/shared/lib/pagination/load-more'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { E } from '#generated/entities.ids.generated'\nimport type { DealCustomFieldEntry, DealSummary, SectionAction, TabEmptyStateConfig, Translator } from './types'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { formatDate } from './utils'\nimport { DealDialog } from './DealDialog'\nimport type { DealFormBaseValues, DealFormSubmitPayload } from './DealForm'\nimport { generateTempId } from '@open-mercato/core/modules/customers/lib/detailHelpers'\nimport { useCurrencyDictionary } from './hooks/useCurrencyDictionary'\nimport { useCustomerDictionary } from './hooks/useCustomerDictionary'\nimport { CustomFieldValuesList } from './CustomFieldValuesList'\nimport { useCustomFieldDisplay } from './hooks/useCustomFieldDisplay'\nimport { normalizeCustomFieldKey } from './customFieldUtils'\n\nconst DEALS_PAGE_SIZE = 10\n\ntype DealsScope =\n | { kind: 'person'; entityId: string }\n | { kind: 'company'; entityId: string }\n\ntype GuardedMutationRunner = <T,>(\n operation: () => Promise<T>,\n mutationPayload?: Record<string, unknown>,\n) => Promise<T>\n\ntype PendingAction =\n | { kind: 'create' }\n | { kind: 'update'; id: string }\n | { kind: 'remove'; id: string }\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction sanitizeCustomValues(input: unknown): Record<string, unknown> | null {\n if (!isPlainObject(input)) return null\n const result: Record<string, unknown> = {}\n Object.entries(input).forEach(([key, value]) => {\n const trimmedKey = key.trim()\n if (!trimmedKey.length) return\n result[trimmedKey] = value\n })\n return Object.keys(result).length ? result : null\n}\n\nfunction sanitizeCustomFieldEntries(\n entries: unknown,\n values: Record<string, unknown> | null,\n): DealCustomFieldEntry[] {\n const map = new Map<string, DealCustomFieldEntry>()\n if (Array.isArray(entries)) {\n entries.forEach((entry) => {\n if (!entry || typeof entry !== 'object') return\n const record = entry as Record<string, unknown>\n const keyRaw =\n typeof record.key === 'string'\n ? record.key\n : typeof record.id === 'string'\n ? record.id\n : null\n if (!keyRaw) return\n const key = keyRaw.trim()\n if (!key.length) return\n const normalizedKey = normalizeCustomFieldKey(key)\n if (!normalizedKey) return\n const label =\n typeof record.label === 'string' && record.label.trim().length\n ? record.label.trim()\n : null\n const kind =\n typeof record.kind === 'string' && record.kind.trim().length\n ? record.kind.trim()\n : null\n const multi =\n typeof record.multi === 'boolean' ? record.multi : Array.isArray(record.value) ? true : undefined\n map.set(normalizedKey, {\n key,\n label,\n value: record.value,\n kind,\n multi,\n })\n })\n }\n\n if (values) {\n Object.entries(values).forEach(([rawKey, value]) => {\n const key = rawKey.trim()\n if (!key.length) return\n const normalizedKey = normalizeCustomFieldKey(key)\n if (!normalizedKey) return\n const existing = map.get(normalizedKey)\n if (existing) {\n existing.value = value\n if (existing.multi === undefined) existing.multi = Array.isArray(value)\n } else {\n map.set(normalizedKey, {\n key,\n label: null,\n value,\n kind: null,\n multi: Array.isArray(value) ? true : undefined,\n })\n }\n })\n }\n\n return Array.from(map.values())\n}\n\ntype NormalizedDeal = Omit<\n DealSummary,\n 'valueAmount' | 'probability' | 'expectedCloseAt' | 'customValues' | 'customFields' | 'personIds' | 'companyIds'\n> & {\n valueAmount: number | null\n probability: number | null\n expectedCloseAt: string | null\n personIds: string[]\n companyIds: string[]\n customValues: Record<string, unknown> | null\n customFields: DealCustomFieldEntry[]\n}\n\nfunction toNumber(value: unknown): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed.length) return null\n const parsed = Number(trimmed)\n return Number.isNaN(parsed) ? null : parsed\n }\n return null\n}\n\nfunction toIso(value: unknown): string | null {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed.length) return null\n const parsed = new Date(trimmed)\n return Number.isNaN(parsed.getTime()) ? null : parsed.toISOString()\n }\n if (value instanceof Date) {\n return Number.isNaN(value.getTime()) ? null : value.toISOString()\n }\n return null\n}\n\nfunction mergeIds(...sources: Array<unknown>): string[] {\n const set = new Set<string>()\n sources.forEach((source) => {\n if (Array.isArray(source)) {\n source.forEach((value) => {\n if (typeof value !== 'string') return\n const trimmed = value.trim()\n if (!trimmed.length) return\n set.add(trimmed)\n })\n }\n })\n return Array.from(set)\n}\n\nfunction normalizeDeal(deal: Partial<DealSummary> & { id: string; title?: string }): NormalizedDeal {\n const title = typeof deal.title === 'string' && deal.title.trim().length ? deal.title.trim() : ''\n const normalizeIdList = (list: unknown): string[] => {\n if (!Array.isArray(list)) return []\n const seen = new Set<string>()\n const result: string[] = []\n list.forEach((candidate) => {\n if (typeof candidate !== 'string') return\n const trimmed = candidate.trim()\n if (!trimmed.length || seen.has(trimmed)) return\n seen.add(trimmed)\n result.push(trimmed)\n })\n return result\n }\n\n const normalizeAssignees = (entries: unknown, fallbackIds: string[]): { id: string; label: string }[] => {\n if (!Array.isArray(entries)) {\n return fallbackIds.map((id) => ({ id, label: '' }))\n }\n const seen = new Set<string>()\n const resolved: { id: string; label: string }[] = []\n entries.forEach((entry) => {\n if (!entry || typeof entry !== 'object') return\n const data = entry as Record<string, unknown>\n const id = typeof data.id === 'string' ? data.id.trim() : ''\n if (!id || seen.has(id)) return\n const label = typeof data.label === 'string' ? data.label : ''\n seen.add(id)\n resolved.push({ id, label })\n })\n if (!resolved.length && fallbackIds.length) {\n return fallbackIds.map((id) => ({ id, label: '' }))\n }\n return resolved\n }\n\n const personIds = normalizeIdList(deal.personIds ?? null)\n const companyIds = normalizeIdList(deal.companyIds ?? null)\n const people = normalizeAssignees(deal.people ?? null, personIds)\n const companies = normalizeAssignees(deal.companies ?? null, companyIds)\n\n const customValues = sanitizeCustomValues(deal.customValues ?? null)\n const customFields = sanitizeCustomFieldEntries(deal.customFields ?? null, customValues)\n\n return {\n id: deal.id,\n title,\n status: typeof deal.status === 'string' ? deal.status : deal.status ?? null,\n pipelineStage:\n typeof deal.pipelineStage === 'string' ? deal.pipelineStage : deal.pipelineStage ?? null,\n pipelineId:\n typeof deal.pipelineId === 'string' && deal.pipelineId.trim().length\n ? deal.pipelineId.trim()\n : deal.pipelineId ?? null,\n pipelineStageId:\n typeof deal.pipelineStageId === 'string' && deal.pipelineStageId.trim().length\n ? deal.pipelineStageId.trim()\n : deal.pipelineStageId ?? null,\n valueAmount: toNumber(deal.valueAmount ?? null),\n valueCurrency:\n typeof deal.valueCurrency === 'string' && deal.valueCurrency.trim().length\n ? deal.valueCurrency.trim().toUpperCase()\n : null,\n probability: toNumber(deal.probability ?? null),\n expectedCloseAt: toIso(deal.expectedCloseAt ?? null),\n description:\n typeof deal.description === 'string' && deal.description.trim().length\n ? deal.description\n : deal.description ?? null,\n ownerUserId:\n typeof deal.ownerUserId === 'string' && deal.ownerUserId.trim().length\n ? deal.ownerUserId\n : deal.ownerUserId ?? null,\n source:\n typeof deal.source === 'string' && deal.source.trim().length ? deal.source : deal.source ?? null,\n closureOutcome:\n typeof deal.closureOutcome === 'string' && deal.closureOutcome.trim().length\n ? deal.closureOutcome\n : deal.closureOutcome ?? null,\n lossReasonId:\n typeof deal.lossReasonId === 'string' && deal.lossReasonId.trim().length\n ? deal.lossReasonId\n : deal.lossReasonId ?? null,\n lossNotes:\n typeof deal.lossNotes === 'string' && deal.lossNotes.trim().length\n ? deal.lossNotes\n : deal.lossNotes ?? null,\n createdAt: toIso(deal.createdAt ?? null),\n updatedAt: toIso(deal.updatedAt ?? null),\n personIds,\n companyIds,\n people,\n companies,\n customValues,\n customFields,\n }\n}\n\nfunction formatValueLabel(amount: number | null, currency: string | null, emptyLabel: string): string {\n if (typeof amount === 'number') {\n const formatter = new Intl.NumberFormat(undefined, {\n style: currency ? 'currency' : 'decimal',\n currency: currency ?? undefined,\n maximumFractionDigits: 2,\n })\n try {\n return formatter.format(amount)\n } catch {\n return currency ? `${amount} ${currency}` : `${amount}`\n }\n }\n return emptyLabel\n}\n\nexport type DealsSectionProps = {\n scope: DealsScope | null\n addActionLabel: string\n emptyLabel: string\n emptyState: TabEmptyStateConfig\n onCountDelta?: (delta: number) => void\n onActionChange?: (action: SectionAction | null) => void\n onLoadingChange?: (isLoading: boolean) => void\n onDataRefresh?: () => Promise<void> | void\n translator?: Translator\n runGuardedMutation?: GuardedMutationRunner\n}\n\nexport function DealsSection({\n scope,\n addActionLabel,\n emptyLabel,\n emptyState,\n onCountDelta,\n onActionChange,\n onLoadingChange,\n onDataRefresh,\n translator,\n runGuardedMutation,\n}: DealsSectionProps) {\n const tHook = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const fallbackTranslator = React.useMemo<Translator>(() => createTranslatorWithFallback(tHook), [tHook])\n const t: Translator = React.useMemo(() => translator ?? fallbackTranslator, [translator, fallbackTranslator])\n useCurrencyDictionary()\n const scopeVersion = useOrganizationScopeVersion()\n const statusDictionaryQuery = useCustomerDictionary('deal-statuses', scopeVersion)\n const statusDictionaryMap = statusDictionaryQuery.data?.map ?? null\n const customFieldResources = useCustomFieldDisplay(E.customers.customer_deal)\n\n const [deals, setDeals] = React.useState<NormalizedDeal[]>([])\n const [isLoading, setIsLoading] = React.useState<boolean>(() => Boolean(scope))\n const [loadError, setLoadError] = React.useState<string | null>(null)\n const [pendingAction, setPendingAction] = React.useState<PendingAction | null>(null)\n const [hasMore, setHasMore] = React.useState(false)\n const pageRef = React.useRef(0)\n const hasMoreRef = React.useRef(true)\n const [dialogOpen, setDialogOpen] = React.useState(false)\n const [initialValues, setInitialValues] = React.useState<\n Partial<DealFormBaseValues & Record<string, unknown>> | undefined\n >(undefined)\n const pendingCounterRef = React.useRef(0)\n\n const pushLoading = React.useCallback(() => {\n pendingCounterRef.current += 1\n if (pendingCounterRef.current === 1) onLoadingChange?.(true)\n }, [onLoadingChange])\n\n const popLoading = React.useCallback(() => {\n pendingCounterRef.current = Math.max(0, pendingCounterRef.current - 1)\n if (pendingCounterRef.current === 0) onLoadingChange?.(false)\n }, [onLoadingChange])\n\n const translate = React.useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>) => {\n const value = t(key, fallback, params)\n return value === key && fallback ? fallback : value\n },\n [t],\n )\n const runWriteMutation = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n if (!runGuardedMutation) {\n return operation()\n }\n return runGuardedMutation(operation, mutationPayload)\n },\n [runGuardedMutation],\n )\n const refreshParentData = React.useCallback(async () => {\n await Promise.resolve(onDataRefresh?.())\n }, [onDataRefresh])\n\n const loadDeals = React.useCallback(async ({ append }: { append: boolean }) => {\n if (!scope) {\n setDeals([])\n setLoadError(null)\n setHasMore(false)\n setIsLoading(false)\n pendingCounterRef.current = 0\n onLoadingChange?.(false)\n pageRef.current = 0\n hasMoreRef.current = false\n return\n }\n if (append && !hasMoreRef.current) return\n const nextPage = append ? pageRef.current + 1 : 1\n if (!append) {\n pageRef.current = 0\n hasMoreRef.current = true\n setHasMore(true)\n setDeals([])\n }\n pushLoading()\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(nextPage),\n pageSize: String(DEALS_PAGE_SIZE),\n sortField: 'updatedAt',\n sortDir: 'desc',\n })\n if (scope.kind === 'person') params.set('personEntityId', scope.entityId)\n if (scope.kind === 'company') params.set('companyEntityId', scope.entityId)\n const payload = await readApiResultOrThrow<Record<string, unknown>>(\n `/api/customers/deals?${params.toString()}`,\n undefined,\n { errorMessage: translate('customers.people.detail.deals.loadError', 'Failed to load deals.') },\n )\n const rawItems = Array.isArray(payload?.items) ? payload.items : []\n const mapped: NormalizedDeal[] = rawItems.map((item: unknown) => {\n const record = (item && typeof item === 'object') ? (item as Record<string, unknown>) : {}\n const id =\n typeof record.id === 'string' && record.id.trim().length ? record.id : generateTempId()\n const title =\n typeof record.title === 'string' && record.title.trim().length ? record.title.trim() : ''\n const status =\n typeof record.status === 'string' && record.status.trim().length\n ? record.status.trim()\n : null\n const pipelineStage =\n typeof record.pipelineStage === 'string' && record.pipelineStage.trim().length\n ? record.pipelineStage.trim()\n : typeof record.pipeline_stage === 'string' && record.pipeline_stage.trim().length\n ? record.pipeline_stage.trim()\n : null\n const pipelineId =\n typeof record.pipelineId === 'string' && record.pipelineId.trim().length\n ? record.pipelineId.trim()\n : typeof record.pipeline_id === 'string' && record.pipeline_id.trim().length\n ? record.pipeline_id.trim()\n : null\n const pipelineStageId =\n typeof record.pipelineStageId === 'string' && record.pipelineStageId.trim().length\n ? record.pipelineStageId.trim()\n : typeof record.pipeline_stage_id === 'string' && record.pipeline_stage_id.trim().length\n ? record.pipeline_stage_id.trim()\n : null\n const valueAmount = toNumber(record.valueAmount ?? record.value_amount)\n const valueCurrencyRaw = record.valueCurrency ?? record.value_currency ?? null\n const valueCurrency =\n typeof valueCurrencyRaw === 'string' && valueCurrencyRaw.trim().length\n ? valueCurrencyRaw.trim().toUpperCase()\n : null\n const probability = toNumber(record.probability)\n const expectedCloseAt =\n typeof record.expectedCloseAt === 'string' && record.expectedCloseAt.trim().length\n ? record.expectedCloseAt\n : typeof record.expected_close_at === 'string' && record.expected_close_at.trim().length\n ? record.expected_close_at\n : null\n const description =\n typeof record.description === 'string' && record.description.trim().length\n ? record.description\n : null\n const ownerUserId =\n typeof record.ownerUserId === 'string' && record.ownerUserId.trim().length\n ? record.ownerUserId\n : typeof record.owner_user_id === 'string' && record.owner_user_id.trim().length\n ? record.owner_user_id\n : null\n const source =\n typeof record.source === 'string' && record.source.trim().length\n ? record.source\n : null\n const closureOutcome =\n typeof record.closureOutcome === 'string' && record.closureOutcome.trim().length\n ? record.closureOutcome\n : typeof record.closure_outcome === 'string' && record.closure_outcome.trim().length\n ? record.closure_outcome\n : null\n const lossReasonId =\n typeof record.lossReasonId === 'string' && record.lossReasonId.trim().length\n ? record.lossReasonId\n : typeof record.loss_reason_id === 'string' && record.loss_reason_id.trim().length\n ? record.loss_reason_id\n : null\n const lossNotes =\n typeof record.lossNotes === 'string' && record.lossNotes.trim().length\n ? record.lossNotes\n : typeof record.loss_notes === 'string' && record.loss_notes.trim().length\n ? record.loss_notes\n : null\n const createdAt =\n typeof record.createdAt === 'string' && record.createdAt.trim().length\n ? record.createdAt\n : typeof record.created_at === 'string' && record.created_at.trim().length\n ? record.created_at\n : null\n const updatedAt =\n typeof record.updatedAt === 'string' && record.updatedAt.trim().length\n ? record.updatedAt\n : typeof record.updated_at === 'string' && record.updated_at.trim().length\n ? record.updated_at\n : null\n const personIds = Array.isArray(record.personIds)\n ? record.personIds\n : Array.isArray(record.person_ids)\n ? record.person_ids\n : []\n const people = Array.isArray(record.people) ? record.people : []\n const companyIds = Array.isArray(record.companyIds)\n ? record.companyIds\n : Array.isArray(record.company_ids)\n ? record.company_ids\n : []\n const companies = Array.isArray(record.companies) ? record.companies : []\n const customValues = sanitizeCustomValues(\n record.customValues ?? record.custom_values ?? null,\n )\n const customFieldEntries = sanitizeCustomFieldEntries(\n record.customFields ?? record.custom_fields ?? null,\n customValues,\n )\n return normalizeDeal({\n id,\n title,\n status,\n pipelineStage,\n pipelineId,\n pipelineStageId,\n valueAmount,\n valueCurrency,\n probability,\n expectedCloseAt,\n description,\n ownerUserId,\n source,\n closureOutcome,\n lossReasonId,\n lossNotes,\n createdAt,\n updatedAt,\n personIds: personIds as string[] | undefined,\n people: people as { id: string; label: string }[] | undefined,\n companyIds: companyIds as string[] | undefined,\n companies: companies as { id: string; label: string }[] | undefined,\n customValues,\n customFields: customFieldEntries,\n })\n })\n setDeals((prev) => {\n if (!append) return mapped\n const mappedById = new Map(mapped.map((deal) => [deal.id, deal]))\n const prevIds = new Set(prev.map((deal) => deal.id))\n const updatedPrev = prev.map((deal) => mappedById.get(deal.id) ?? deal)\n const appended = mapped.filter((deal) => !prevIds.has(deal.id))\n return [...updatedPrev, ...appended]\n })\n pageRef.current = nextPage\n // Short-page termination, unconditionally \u2014 see `hasMoreFromPage`.\n // Preferring `totalPages` here hid deals that do exist. Measured on\n // `rawItems`, which is what the server served, rather than on the\n // deduped rows appended above.\n const nextHasMore = hasMoreFromPage(rawItems.length, DEALS_PAGE_SIZE)\n hasMoreRef.current = nextHasMore\n setHasMore(nextHasMore)\n setLoadError(null)\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : translate('customers.people.detail.deals.loadError', 'Failed to load deals.')\n setLoadError(message)\n if (!append) {\n setHasMore(false)\n hasMoreRef.current = false\n }\n } finally {\n setIsLoading(false)\n popLoading()\n }\n }, [popLoading, pushLoading, scope, translate])\n\n React.useEffect(() => {\n loadDeals({ append: false }).catch(() => {})\n }, [loadDeals, scope])\n\n const openCreateDialog = React.useCallback(() => {\n if (!scope) return\n setInitialValues({\n personIds: scope.kind === 'person' ? [scope.entityId] : [],\n companyIds: scope.kind === 'company' ? [scope.entityId] : [],\n })\n setDialogOpen(true)\n }, [scope])\n\n const [linkDialogOpen, setLinkDialogOpen] = React.useState(false)\n const openLinkDialog = React.useCallback(() => {\n if (!scope) return\n setLinkDialogOpen(true)\n }, [scope])\n\n const existingDealIds = React.useMemo(() => deals.map((deal) => deal.id), [deals])\n\n const dealLinkAdapter = React.useMemo(\n () =>\n createDealLinkAdapter({\n dialogTitle: t('customers.linking.deal.dialogTitle', 'Link deal'),\n dialogSubtitle: t(\n 'customers.linking.deal.dialogSubtitle',\n 'Link an existing deal to this record',\n ),\n sectionLabel: t('customers.linking.deal.sectionLabel', 'MATCHING DEALS'),\n searchPlaceholder: t('customers.linking.deal.searchPlaceholder', 'Search all deals\u2026'),\n searchEmptyHint: t('customers.linking.deal.searchEmpty', 'No matching deals found.'),\n selectedEmptyHint: t('customers.linking.deal.selectedEmpty', 'No deals selected.'),\n confirmButtonLabel: t('customers.linking.deal.confirmButton', 'Link deal'),\n orphanWarningTitle: t('customers.linking.deal.orphanWarningTitle', 'Deal without company'),\n orphanWarningMessage: t(\n 'customers.linking.deal.orphanWarning',\n 'This deal has no other linked entities. If you unlink it later, it will become unreachable.',\n ),\n contextEntityId: scope?.entityId,\n }),\n [scope?.entityId, t],\n )\n\n const handleLinkConfirm = React.useCallback(\n async ({\n addedIds,\n removedIds,\n }: {\n addedIds: string[]\n removedIds: string[]\n }) => {\n if (!scope) return\n if (!addedIds.length && !removedIds.length) return\n pushLoading()\n try {\n for (const dealId of addedIds) {\n const payload = await readApiResultOrThrow<Record<string, unknown>>(\n `/api/customers/deals/${encodeURIComponent(dealId)}`,\n )\n const currentPersonIds = Array.isArray(payload.personIds)\n ? (payload.personIds as string[]).filter((id) => typeof id === 'string')\n : []\n const currentCompanyIds = Array.isArray(payload.companyIds)\n ? (payload.companyIds as string[]).filter((id) => typeof id === 'string')\n : []\n const nextPersonIds =\n scope.kind === 'person' && !currentPersonIds.includes(scope.entityId)\n ? [...currentPersonIds, scope.entityId]\n : currentPersonIds\n const nextCompanyIds =\n scope.kind === 'company' && !currentCompanyIds.includes(scope.entityId)\n ? [...currentCompanyIds, scope.entityId]\n : currentCompanyIds\n await runWriteMutation(\n () =>\n // optimistic-lock-exempt: deal association list (link)\n updateCrud(\n 'customers/deals',\n { id: dealId, personIds: nextPersonIds, companyIds: nextCompanyIds },\n {\n errorMessage: t(\n 'customers.people.detail.deals.linkError',\n 'Failed to link deal.',\n ),\n },\n ),\n { dealId, scopeKind: scope.kind, scopeEntityId: scope.entityId, operation: 'linkDeal' },\n )\n }\n for (const dealId of removedIds) {\n const payload = await readApiResultOrThrow<Record<string, unknown>>(\n `/api/customers/deals/${encodeURIComponent(dealId)}`,\n )\n const currentPersonIds = Array.isArray(payload.personIds)\n ? (payload.personIds as string[]).filter((id) => typeof id === 'string')\n : []\n const currentCompanyIds = Array.isArray(payload.companyIds)\n ? (payload.companyIds as string[]).filter((id) => typeof id === 'string')\n : []\n const nextPersonIds =\n scope.kind === 'person'\n ? currentPersonIds.filter((id) => id !== scope.entityId)\n : currentPersonIds\n const nextCompanyIds =\n scope.kind === 'company'\n ? currentCompanyIds.filter((id) => id !== scope.entityId)\n : currentCompanyIds\n await runWriteMutation(\n () =>\n // optimistic-lock-exempt: deal association list (unlink)\n updateCrud(\n 'customers/deals',\n { id: dealId, personIds: nextPersonIds, companyIds: nextCompanyIds },\n {\n errorMessage: t(\n 'customers.people.detail.deals.unlinkError',\n 'Failed to unlink deal.',\n ),\n },\n ),\n { dealId, scopeKind: scope.kind, scopeEntityId: scope.entityId, operation: 'unlinkDeal' },\n )\n }\n await loadDeals({ append: false })\n await refreshParentData()\n if (addedIds.length + removedIds.length > 0) {\n onCountDelta?.(addedIds.length - removedIds.length)\n }\n flash(\n addedIds.length > 0\n ? t('customers.people.detail.deals.linkSuccess', 'Deal linked.')\n : t('customers.people.detail.deals.unlinkSuccess', 'Deal unlinked.'),\n 'success',\n )\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : t('customers.people.detail.deals.linkError', 'Failed to link deal.')\n flash(message, 'error')\n } finally {\n popLoading()\n }\n },\n [loadDeals, onCountDelta, popLoading, pushLoading, refreshParentData, runWriteMutation, scope, t],\n )\n\n const closeDialog = React.useCallback(() => {\n setDialogOpen(false)\n setInitialValues(undefined)\n }, [])\n\n const handleDialogOpenChange = React.useCallback(\n (next: boolean) => {\n if (!next) closeDialog()\n else setDialogOpen(true)\n },\n [closeDialog],\n )\n\n const handleCreate = React.useCallback(\n async ({ base, custom }: DealFormSubmitPayload) => {\n if (!scope) {\n throw new Error(translate('customers.people.detail.deals.error', 'Failed to save deal.'))\n }\n setPendingAction({ kind: 'create' })\n pushLoading()\n try {\n const personIds = mergeIds(base.personIds)\n const companyIds = mergeIds(base.companyIds)\n\n const payload: Record<string, unknown> = {\n title: base.title,\n status: base.status ?? undefined,\n pipelineStage: base.pipelineStage ?? undefined,\n pipelineId: base.pipelineId ?? undefined,\n pipelineStageId: base.pipelineStageId ?? undefined,\n valueAmount: typeof base.valueAmount === 'number' ? base.valueAmount : undefined,\n valueCurrency: base.valueCurrency ?? undefined,\n probability: typeof base.probability === 'number' ? base.probability : undefined,\n expectedCloseAt: base.expectedCloseAt ?? undefined,\n description: base.description ?? undefined,\n personIds,\n companyIds,\n }\n if (Object.keys(custom).length) payload.customFields = custom\n const { result } = await runWriteMutation(\n () =>\n // optimistic-lock-exempt: deal create-only, no prior version\n createCrud<{ id?: string }>('customers/deals', payload, {\n errorMessage: translate('customers.people.detail.deals.error', 'Failed to save deal.'),\n }),\n {\n ...payload,\n operation: 'createDeal',\n },\n )\n const dealId =\n typeof result?.id === 'string' && result.id.trim().length ? result.id : generateTempId()\n const belongsToScope =\n (scope.kind !== 'person' || personIds.includes(scope.entityId)) &&\n (scope.kind !== 'company' || companyIds.includes(scope.entityId))\n if (belongsToScope) {\n const customValuesForState = sanitizeCustomValues(\n Object.keys(custom).length ? custom : null,\n )\n const timestamp = new Date().toISOString()\n const normalized = normalizeDeal({\n id: dealId,\n title: base.title,\n status: base.status ?? null,\n pipelineStage: base.pipelineStage ?? null,\n pipelineId: base.pipelineId ?? null,\n pipelineStageId: base.pipelineStageId ?? null,\n valueAmount: base.valueAmount ?? null,\n valueCurrency: base.valueCurrency ?? null,\n probability: base.probability ?? null,\n expectedCloseAt: base.expectedCloseAt ?? null,\n description: base.description ?? null,\n personIds,\n companyIds,\n customValues: customValuesForState,\n createdAt: timestamp,\n updatedAt: timestamp,\n })\n setDeals((prev) => [normalized, ...prev])\n onCountDelta?.(1)\n }\n await refreshParentData()\n flash(translate('customers.people.detail.deals.success', 'Deal created.'), 'success')\n } finally {\n setPendingAction(null)\n popLoading()\n }\n },\n [onCountDelta, popLoading, pushLoading, refreshParentData, runWriteMutation, scope, translate],\n )\n\n const handleUnlink = React.useCallback(\n async (deal: NormalizedDeal) => {\n if (!scope) return\n\n const nextPersonIds =\n scope.kind === 'person'\n ? deal.personIds.filter((id) => id !== scope.entityId)\n : deal.personIds\n const nextCompanyIds =\n scope.kind === 'company'\n ? deal.companyIds.filter((id) => id !== scope.entityId)\n : deal.companyIds\n\n const confirmed = await confirm({\n title:\n scope.kind === 'person'\n ? translate('customers.people.detail.deals.unlinkConfirmPerson', 'Unlink this deal from this person?')\n : translate('customers.people.detail.deals.unlinkConfirmCompany', 'Unlink this deal from this company?'),\n description: translate(\n 'customers.people.detail.deals.unlinkDescription',\n 'The deal will remain available from its own detail page.',\n ),\n confirmText: translate('customers.people.card.unlink', 'Unlink'),\n cancelText: translate('customers.people.detail.deals.cancel', 'Cancel'),\n })\n if (!confirmed) return\n\n setPendingAction({ kind: 'remove', id: deal.id })\n pushLoading()\n try {\n const payload: Record<string, unknown> = {\n id: deal.id,\n personIds: nextPersonIds,\n companyIds: nextCompanyIds,\n }\n await runWriteMutation(\n () =>\n // optimistic-lock-exempt: deal association list (unlink)\n updateCrud('customers/deals', payload, {\n errorMessage: translate('customers.people.detail.deals.unlinkError', 'Failed to unlink deal.'),\n }),\n {\n ...payload,\n operation: 'unlinkDeal',\n },\n )\n setDeals((prev) => prev.filter((item) => item.id !== deal.id))\n onCountDelta?.(-1)\n await refreshParentData()\n flash(translate('customers.people.detail.deals.unlinkSuccess', 'Deal unlinked.'), 'success')\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : translate('customers.people.detail.deals.unlinkError', 'Failed to unlink deal.')\n flash(message, 'error')\n } finally {\n setPendingAction(null)\n popLoading()\n }\n },\n [confirm, onCountDelta, popLoading, pushLoading, refreshParentData, runWriteMutation, scope, translate],\n )\n\n const handleDialogSubmit = React.useCallback(\n async (payload: DealFormSubmitPayload) => {\n try {\n await handleCreate(payload)\n closeDialog()\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : translate('customers.people.detail.deals.error', 'Failed to save deal.')\n flash(message, 'error')\n }\n },\n [closeDialog, handleCreate, translate],\n )\n\n React.useEffect(() => {\n if (!onActionChange) return\n const disabled = !scope || isLoading || pendingAction !== null\n const action: SectionAction = {\n label: addActionLabel,\n onClick: () => {\n if (!disabled) openCreateDialog()\n },\n disabled,\n }\n onActionChange(action)\n return () => {\n onActionChange(null)\n }\n }, [addActionLabel, isLoading, onActionChange, openCreateDialog, pendingAction, scope])\n\n const isFormPending = pendingAction?.kind === 'create'\n\n const sortedDeals = React.useMemo(() => {\n return [...deals].sort((a, b) => {\n const timeA = a.updatedAt ?? a.createdAt ?? ''\n const timeB = b.updatedAt ?? b.createdAt ?? ''\n return timeB.localeCompare(timeA)\n })\n }, [deals])\n\n return (\n <div className=\"mt-4 space-y-4\">\n {loadError ? (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-sm text-destructive\">\n {loadError}\n </div>\n ) : null}\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={openLinkDialog}\n disabled={!scope || pendingAction !== null}\n >\n <Link2 className=\"mr-1.5 size-3.5\" />\n {t('customers.people.detail.deals.linkExisting', 'Link existing deal')}\n </Button>\n <Button\n type=\"button\"\n variant=\"default\"\n size=\"sm\"\n onClick={openCreateDialog}\n disabled={!scope || pendingAction !== null}\n >\n <Plus className=\"mr-1.5 size-3.5\" />\n {addActionLabel}\n </Button>\n </div>\n {isLoading && sortedDeals.length === 0 ? (\n <LoadingMessage\n label={t('customers.people.detail.deals.loading', 'Loading deals\u2026')}\n className=\"border-0 bg-transparent p-0 py-8 justify-center\"\n />\n ) : (\n <>\n {!isLoading && sortedDeals.length === 0 ? (\n <TabEmptyState\n title={emptyState.title}\n action={{\n label: emptyState.actionLabel,\n onClick: openCreateDialog,\n disabled: !scope || pendingAction !== null,\n }}\n />\n ) : null}\n <div className=\"space-y-4\">\n {sortedDeals.map((deal) => {\n const valueLabel = formatValueLabel(deal.valueAmount, deal.valueCurrency ?? null, emptyLabel)\n const expectedLabel = deal.expectedCloseAt ? formatDate(deal.expectedCloseAt) ?? emptyLabel : emptyLabel\n const probabilityLabel =\n typeof deal.probability === 'number' ? `${deal.probability}%` : emptyLabel\n const isUnlinkPending = pendingAction?.kind === 'remove' && pendingAction.id === deal.id\n const statusLabel =\n deal.status && statusDictionaryMap\n ? statusDictionaryMap[deal.status]?.label ?? deal.status\n : deal.status ?? emptyLabel\n return (\n <article key={deal.id} className=\"group rounded-lg border bg-card p-4 shadow-xs transition hover:border-border/70\">\n <header className=\"flex flex-wrap items-center justify-between gap-2\">\n <div>\n <Link\n href={`/backend/customers/deals/${encodeURIComponent(deal.id)}`}\n className=\"text-base font-semibold text-foreground transition hover:text-primary hover:underline\"\n >\n {deal.title || emptyLabel}\n </Link>\n {deal.description ? (\n <p className=\"mt-1 line-clamp-3 text-sm text-muted-foreground whitespace-pre-wrap\">{deal.description}</p>\n ) : null}\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs font-medium uppercase text-muted-foreground\">\n {statusLabel}\n </span>\n <div className=\"flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100\">\n <IconButton asChild variant=\"ghost\" size=\"sm\" className=\"h-8 w-8\">\n <Link\n href={`/backend/customers/deals/${encodeURIComponent(deal.id)}`}\n aria-label={t('customers.people.detail.deals.edit', 'Open deal details')}\n >\n <Pencil className=\"size-4\" />\n </Link>\n </IconButton>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-8 rounded-lg px-3 text-xs\"\n onClick={(event) => {\n event.preventDefault()\n void handleUnlink(deal)\n }}\n disabled={pendingAction !== null}\n >\n {isUnlinkPending\n ? t('customers.people.detail.deals.unlinking', 'Unlinking\u2026')\n : t('customers.people.card.unlink', 'Unlink')}\n </Button>\n </div>\n </div>\n </header>\n <dl className=\"mt-3 grid gap-2 text-xs text-muted-foreground sm:grid-cols-2\">\n <div className=\"flex flex-col gap-0.5\">\n <dt className=\"font-medium\">\n {t('customers.people.detail.deals.fields.pipelineStage', 'Pipeline stage')}\n </dt>\n <dd>{deal.pipelineStage ?? emptyLabel}</dd>\n </div>\n <div className=\"flex flex-col gap-0.5\">\n <dt className=\"font-medium\">\n {t('customers.people.detail.deals.fields.probability', 'Probability')}\n </dt>\n <dd>{probabilityLabel}</dd>\n </div>\n <div className=\"flex flex-col gap-0.5\">\n <dt className=\"font-medium\">\n {t('customers.people.detail.deals.fields.valueAmount', 'Value')}\n </dt>\n <dd>{valueLabel}</dd>\n </div>\n <div className=\"flex flex-col gap-0.5\">\n <dt className=\"font-medium\">\n {t('customers.people.detail.deals.fields.expectedCloseAt', 'Expected close')}\n </dt>\n <dd>{expectedLabel}</dd>\n </div>\n </dl>\n <CustomFieldValuesList\n entries={deal.customFields?.map((entry) => ({\n key: entry.key,\n value: entry.value,\n label: entry.label ?? undefined,\n }))}\n values={deal.customValues ?? undefined}\n resources={customFieldResources}\n emptyLabel={emptyLabel}\n itemKeyPrefix={`deal-${deal.id}-field`}\n className=\"mt-3\"\n />\n </article>\n )\n })}\n {isLoading && deals.length > 0 ? (\n <div className=\"flex justify-center\">\n <LoadingMessage\n label={t('customers.people.detail.deals.loading', 'Loading deals\u2026')}\n className=\"border-0 bg-transparent p-0 justify-center [&_span[role='status']]:h-5 [&_span[role='status']]:w-5\"\n />\n </div>\n ) : null}\n {!isLoading && hasMore ? (\n <div className=\"flex justify-center\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n loadDeals({ append: true }).catch(() => {})\n }}\n disabled={pendingAction !== null || isLoading}\n >\n {t('customers.people.detail.deals.loadMore', 'Load more deals')}\n </Button>\n </div>\n ) : null}\n </div>\n </>\n )}\n\n <DealDialog\n open={dialogOpen}\n mode=\"create\"\n onOpenChange={handleDialogOpenChange}\n initialValues={initialValues}\n onSubmit={async (payload) => {\n await handleDialogSubmit(payload)\n }}\n isSubmitting={Boolean(isFormPending)}\n />\n <LinkEntityDialog\n open={linkDialogOpen}\n onOpenChange={setLinkDialogOpen}\n adapter={dealLinkAdapter}\n initialSelectedIds={existingDealIds}\n onConfirm={handleLinkConfirm}\n />\n {ConfirmDialogElement}\n </div>\n )\n}\n\nexport default DealsSection\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Link2, Pencil, Plus } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { LinkEntityDialog } from '../linking/LinkEntityDialog'\nimport { createDealLinkAdapter } from '../linking/adapters/dealAdapter'\nimport { LoadingMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT, useLocale } from '@open-mercato/shared/lib/i18n/context'\nimport { hasMoreFromPage } from '@open-mercato/shared/lib/pagination/load-more'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { E } from '#generated/entities.ids.generated'\nimport type { DealCustomFieldEntry, DealSummary, SectionAction, TabEmptyStateConfig, Translator } from './types'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { formatDate } from './utils'\nimport { DealDialog } from './DealDialog'\nimport type { DealFormBaseValues, DealFormSubmitPayload } from './DealForm'\nimport { generateTempId } from '@open-mercato/core/modules/customers/lib/detailHelpers'\nimport { useCurrencyDictionary } from './hooks/useCurrencyDictionary'\nimport { useCustomerDictionary } from './hooks/useCustomerDictionary'\nimport { CustomFieldValuesList } from './CustomFieldValuesList'\nimport { useCustomFieldDisplay } from './hooks/useCustomFieldDisplay'\nimport { normalizeCustomFieldKey } from './customFieldUtils'\n\nconst DEALS_PAGE_SIZE = 10\n\ntype DealsScope =\n | { kind: 'person'; entityId: string }\n | { kind: 'company'; entityId: string }\n\ntype GuardedMutationRunner = <T,>(\n operation: () => Promise<T>,\n mutationPayload?: Record<string, unknown>,\n) => Promise<T>\n\ntype PendingAction =\n | { kind: 'create' }\n | { kind: 'update'; id: string }\n | { kind: 'remove'; id: string }\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction sanitizeCustomValues(input: unknown): Record<string, unknown> | null {\n if (!isPlainObject(input)) return null\n const result: Record<string, unknown> = {}\n Object.entries(input).forEach(([key, value]) => {\n const trimmedKey = key.trim()\n if (!trimmedKey.length) return\n result[trimmedKey] = value\n })\n return Object.keys(result).length ? result : null\n}\n\nfunction sanitizeCustomFieldEntries(\n entries: unknown,\n values: Record<string, unknown> | null,\n): DealCustomFieldEntry[] {\n const map = new Map<string, DealCustomFieldEntry>()\n if (Array.isArray(entries)) {\n entries.forEach((entry) => {\n if (!entry || typeof entry !== 'object') return\n const record = entry as Record<string, unknown>\n const keyRaw =\n typeof record.key === 'string'\n ? record.key\n : typeof record.id === 'string'\n ? record.id\n : null\n if (!keyRaw) return\n const key = keyRaw.trim()\n if (!key.length) return\n const normalizedKey = normalizeCustomFieldKey(key)\n if (!normalizedKey) return\n const label =\n typeof record.label === 'string' && record.label.trim().length\n ? record.label.trim()\n : null\n const kind =\n typeof record.kind === 'string' && record.kind.trim().length\n ? record.kind.trim()\n : null\n const multi =\n typeof record.multi === 'boolean' ? record.multi : Array.isArray(record.value) ? true : undefined\n map.set(normalizedKey, {\n key,\n label,\n value: record.value,\n kind,\n multi,\n })\n })\n }\n\n if (values) {\n Object.entries(values).forEach(([rawKey, value]) => {\n const key = rawKey.trim()\n if (!key.length) return\n const normalizedKey = normalizeCustomFieldKey(key)\n if (!normalizedKey) return\n const existing = map.get(normalizedKey)\n if (existing) {\n existing.value = value\n if (existing.multi === undefined) existing.multi = Array.isArray(value)\n } else {\n map.set(normalizedKey, {\n key,\n label: null,\n value,\n kind: null,\n multi: Array.isArray(value) ? true : undefined,\n })\n }\n })\n }\n\n return Array.from(map.values())\n}\n\ntype NormalizedDeal = Omit<\n DealSummary,\n 'valueAmount' | 'probability' | 'expectedCloseAt' | 'customValues' | 'customFields' | 'personIds' | 'companyIds'\n> & {\n valueAmount: number | null\n probability: number | null\n expectedCloseAt: string | null\n personIds: string[]\n companyIds: string[]\n customValues: Record<string, unknown> | null\n customFields: DealCustomFieldEntry[]\n}\n\nfunction toNumber(value: unknown): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed.length) return null\n const parsed = Number(trimmed)\n return Number.isNaN(parsed) ? null : parsed\n }\n return null\n}\n\nfunction toIso(value: unknown): string | null {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed.length) return null\n const parsed = new Date(trimmed)\n return Number.isNaN(parsed.getTime()) ? null : parsed.toISOString()\n }\n if (value instanceof Date) {\n return Number.isNaN(value.getTime()) ? null : value.toISOString()\n }\n return null\n}\n\nfunction mergeIds(...sources: Array<unknown>): string[] {\n const set = new Set<string>()\n sources.forEach((source) => {\n if (Array.isArray(source)) {\n source.forEach((value) => {\n if (typeof value !== 'string') return\n const trimmed = value.trim()\n if (!trimmed.length) return\n set.add(trimmed)\n })\n }\n })\n return Array.from(set)\n}\n\nfunction normalizeDeal(deal: Partial<DealSummary> & { id: string; title?: string }): NormalizedDeal {\n const title = typeof deal.title === 'string' && deal.title.trim().length ? deal.title.trim() : ''\n const normalizeIdList = (list: unknown): string[] => {\n if (!Array.isArray(list)) return []\n const seen = new Set<string>()\n const result: string[] = []\n list.forEach((candidate) => {\n if (typeof candidate !== 'string') return\n const trimmed = candidate.trim()\n if (!trimmed.length || seen.has(trimmed)) return\n seen.add(trimmed)\n result.push(trimmed)\n })\n return result\n }\n\n const normalizeAssignees = (entries: unknown, fallbackIds: string[]): { id: string; label: string }[] => {\n if (!Array.isArray(entries)) {\n return fallbackIds.map((id) => ({ id, label: '' }))\n }\n const seen = new Set<string>()\n const resolved: { id: string; label: string }[] = []\n entries.forEach((entry) => {\n if (!entry || typeof entry !== 'object') return\n const data = entry as Record<string, unknown>\n const id = typeof data.id === 'string' ? data.id.trim() : ''\n if (!id || seen.has(id)) return\n const label = typeof data.label === 'string' ? data.label : ''\n seen.add(id)\n resolved.push({ id, label })\n })\n if (!resolved.length && fallbackIds.length) {\n return fallbackIds.map((id) => ({ id, label: '' }))\n }\n return resolved\n }\n\n const personIds = normalizeIdList(deal.personIds ?? null)\n const companyIds = normalizeIdList(deal.companyIds ?? null)\n const people = normalizeAssignees(deal.people ?? null, personIds)\n const companies = normalizeAssignees(deal.companies ?? null, companyIds)\n\n const customValues = sanitizeCustomValues(deal.customValues ?? null)\n const customFields = sanitizeCustomFieldEntries(deal.customFields ?? null, customValues)\n\n return {\n id: deal.id,\n title,\n status: typeof deal.status === 'string' ? deal.status : deal.status ?? null,\n pipelineStage:\n typeof deal.pipelineStage === 'string' ? deal.pipelineStage : deal.pipelineStage ?? null,\n pipelineId:\n typeof deal.pipelineId === 'string' && deal.pipelineId.trim().length\n ? deal.pipelineId.trim()\n : deal.pipelineId ?? null,\n pipelineStageId:\n typeof deal.pipelineStageId === 'string' && deal.pipelineStageId.trim().length\n ? deal.pipelineStageId.trim()\n : deal.pipelineStageId ?? null,\n valueAmount: toNumber(deal.valueAmount ?? null),\n valueCurrency:\n typeof deal.valueCurrency === 'string' && deal.valueCurrency.trim().length\n ? deal.valueCurrency.trim().toUpperCase()\n : null,\n probability: toNumber(deal.probability ?? null),\n expectedCloseAt: toIso(deal.expectedCloseAt ?? null),\n description:\n typeof deal.description === 'string' && deal.description.trim().length\n ? deal.description\n : deal.description ?? null,\n ownerUserId:\n typeof deal.ownerUserId === 'string' && deal.ownerUserId.trim().length\n ? deal.ownerUserId\n : deal.ownerUserId ?? null,\n source:\n typeof deal.source === 'string' && deal.source.trim().length ? deal.source : deal.source ?? null,\n closureOutcome:\n typeof deal.closureOutcome === 'string' && deal.closureOutcome.trim().length\n ? deal.closureOutcome\n : deal.closureOutcome ?? null,\n lossReasonId:\n typeof deal.lossReasonId === 'string' && deal.lossReasonId.trim().length\n ? deal.lossReasonId\n : deal.lossReasonId ?? null,\n lossNotes:\n typeof deal.lossNotes === 'string' && deal.lossNotes.trim().length\n ? deal.lossNotes\n : deal.lossNotes ?? null,\n createdAt: toIso(deal.createdAt ?? null),\n updatedAt: toIso(deal.updatedAt ?? null),\n personIds,\n companyIds,\n people,\n companies,\n customValues,\n customFields,\n }\n}\n\nfunction formatValueLabel(\n amount: number | null,\n currency: string | null,\n emptyLabel: string,\n locale?: string,\n): string {\n if (typeof amount === 'number') {\n const formatter = new Intl.NumberFormat(locale, {\n style: currency ? 'currency' : 'decimal',\n currency: currency ?? undefined,\n maximumFractionDigits: 2,\n })\n try {\n return formatter.format(amount)\n } catch {\n return currency ? `${amount} ${currency}` : `${amount}`\n }\n }\n return emptyLabel\n}\n\nexport type DealsSectionProps = {\n scope: DealsScope | null\n addActionLabel: string\n emptyLabel: string\n emptyState: TabEmptyStateConfig\n onCountDelta?: (delta: number) => void\n onActionChange?: (action: SectionAction | null) => void\n onLoadingChange?: (isLoading: boolean) => void\n onDataRefresh?: () => Promise<void> | void\n translator?: Translator\n runGuardedMutation?: GuardedMutationRunner\n}\n\nexport function DealsSection({\n scope,\n addActionLabel,\n emptyLabel,\n emptyState,\n onCountDelta,\n onActionChange,\n onLoadingChange,\n onDataRefresh,\n translator,\n runGuardedMutation,\n}: DealsSectionProps) {\n const tHook = useT()\n const locale = useLocale()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const fallbackTranslator = React.useMemo<Translator>(() => createTranslatorWithFallback(tHook), [tHook])\n const t: Translator = React.useMemo(() => translator ?? fallbackTranslator, [translator, fallbackTranslator])\n useCurrencyDictionary()\n const scopeVersion = useOrganizationScopeVersion()\n const statusDictionaryQuery = useCustomerDictionary('deal-statuses', scopeVersion)\n const statusDictionaryMap = statusDictionaryQuery.data?.map ?? null\n const customFieldResources = useCustomFieldDisplay(E.customers.customer_deal)\n\n const [deals, setDeals] = React.useState<NormalizedDeal[]>([])\n const [isLoading, setIsLoading] = React.useState<boolean>(() => Boolean(scope))\n const [loadError, setLoadError] = React.useState<string | null>(null)\n const [pendingAction, setPendingAction] = React.useState<PendingAction | null>(null)\n const [hasMore, setHasMore] = React.useState(false)\n const pageRef = React.useRef(0)\n const hasMoreRef = React.useRef(true)\n const [dialogOpen, setDialogOpen] = React.useState(false)\n const [initialValues, setInitialValues] = React.useState<\n Partial<DealFormBaseValues & Record<string, unknown>> | undefined\n >(undefined)\n const pendingCounterRef = React.useRef(0)\n\n const pushLoading = React.useCallback(() => {\n pendingCounterRef.current += 1\n if (pendingCounterRef.current === 1) onLoadingChange?.(true)\n }, [onLoadingChange])\n\n const popLoading = React.useCallback(() => {\n pendingCounterRef.current = Math.max(0, pendingCounterRef.current - 1)\n if (pendingCounterRef.current === 0) onLoadingChange?.(false)\n }, [onLoadingChange])\n\n const translate = React.useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>) => {\n const value = t(key, fallback, params)\n return value === key && fallback ? fallback : value\n },\n [t],\n )\n const runWriteMutation = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n if (!runGuardedMutation) {\n return operation()\n }\n return runGuardedMutation(operation, mutationPayload)\n },\n [runGuardedMutation],\n )\n const refreshParentData = React.useCallback(async () => {\n await Promise.resolve(onDataRefresh?.())\n }, [onDataRefresh])\n\n const loadDeals = React.useCallback(async ({ append }: { append: boolean }) => {\n if (!scope) {\n setDeals([])\n setLoadError(null)\n setHasMore(false)\n setIsLoading(false)\n pendingCounterRef.current = 0\n onLoadingChange?.(false)\n pageRef.current = 0\n hasMoreRef.current = false\n return\n }\n if (append && !hasMoreRef.current) return\n const nextPage = append ? pageRef.current + 1 : 1\n if (!append) {\n pageRef.current = 0\n hasMoreRef.current = true\n setHasMore(true)\n setDeals([])\n }\n pushLoading()\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(nextPage),\n pageSize: String(DEALS_PAGE_SIZE),\n sortField: 'updatedAt',\n sortDir: 'desc',\n })\n if (scope.kind === 'person') params.set('personEntityId', scope.entityId)\n if (scope.kind === 'company') params.set('companyEntityId', scope.entityId)\n const payload = await readApiResultOrThrow<Record<string, unknown>>(\n `/api/customers/deals?${params.toString()}`,\n undefined,\n { errorMessage: translate('customers.people.detail.deals.loadError', 'Failed to load deals.') },\n )\n const rawItems = Array.isArray(payload?.items) ? payload.items : []\n const mapped: NormalizedDeal[] = rawItems.map((item: unknown) => {\n const record = (item && typeof item === 'object') ? (item as Record<string, unknown>) : {}\n const id =\n typeof record.id === 'string' && record.id.trim().length ? record.id : generateTempId()\n const title =\n typeof record.title === 'string' && record.title.trim().length ? record.title.trim() : ''\n const status =\n typeof record.status === 'string' && record.status.trim().length\n ? record.status.trim()\n : null\n const pipelineStage =\n typeof record.pipelineStage === 'string' && record.pipelineStage.trim().length\n ? record.pipelineStage.trim()\n : typeof record.pipeline_stage === 'string' && record.pipeline_stage.trim().length\n ? record.pipeline_stage.trim()\n : null\n const pipelineId =\n typeof record.pipelineId === 'string' && record.pipelineId.trim().length\n ? record.pipelineId.trim()\n : typeof record.pipeline_id === 'string' && record.pipeline_id.trim().length\n ? record.pipeline_id.trim()\n : null\n const pipelineStageId =\n typeof record.pipelineStageId === 'string' && record.pipelineStageId.trim().length\n ? record.pipelineStageId.trim()\n : typeof record.pipeline_stage_id === 'string' && record.pipeline_stage_id.trim().length\n ? record.pipeline_stage_id.trim()\n : null\n const valueAmount = toNumber(record.valueAmount ?? record.value_amount)\n const valueCurrencyRaw = record.valueCurrency ?? record.value_currency ?? null\n const valueCurrency =\n typeof valueCurrencyRaw === 'string' && valueCurrencyRaw.trim().length\n ? valueCurrencyRaw.trim().toUpperCase()\n : null\n const probability = toNumber(record.probability)\n const expectedCloseAt =\n typeof record.expectedCloseAt === 'string' && record.expectedCloseAt.trim().length\n ? record.expectedCloseAt\n : typeof record.expected_close_at === 'string' && record.expected_close_at.trim().length\n ? record.expected_close_at\n : null\n const description =\n typeof record.description === 'string' && record.description.trim().length\n ? record.description\n : null\n const ownerUserId =\n typeof record.ownerUserId === 'string' && record.ownerUserId.trim().length\n ? record.ownerUserId\n : typeof record.owner_user_id === 'string' && record.owner_user_id.trim().length\n ? record.owner_user_id\n : null\n const source =\n typeof record.source === 'string' && record.source.trim().length\n ? record.source\n : null\n const closureOutcome =\n typeof record.closureOutcome === 'string' && record.closureOutcome.trim().length\n ? record.closureOutcome\n : typeof record.closure_outcome === 'string' && record.closure_outcome.trim().length\n ? record.closure_outcome\n : null\n const lossReasonId =\n typeof record.lossReasonId === 'string' && record.lossReasonId.trim().length\n ? record.lossReasonId\n : typeof record.loss_reason_id === 'string' && record.loss_reason_id.trim().length\n ? record.loss_reason_id\n : null\n const lossNotes =\n typeof record.lossNotes === 'string' && record.lossNotes.trim().length\n ? record.lossNotes\n : typeof record.loss_notes === 'string' && record.loss_notes.trim().length\n ? record.loss_notes\n : null\n const createdAt =\n typeof record.createdAt === 'string' && record.createdAt.trim().length\n ? record.createdAt\n : typeof record.created_at === 'string' && record.created_at.trim().length\n ? record.created_at\n : null\n const updatedAt =\n typeof record.updatedAt === 'string' && record.updatedAt.trim().length\n ? record.updatedAt\n : typeof record.updated_at === 'string' && record.updated_at.trim().length\n ? record.updated_at\n : null\n const personIds = Array.isArray(record.personIds)\n ? record.personIds\n : Array.isArray(record.person_ids)\n ? record.person_ids\n : []\n const people = Array.isArray(record.people) ? record.people : []\n const companyIds = Array.isArray(record.companyIds)\n ? record.companyIds\n : Array.isArray(record.company_ids)\n ? record.company_ids\n : []\n const companies = Array.isArray(record.companies) ? record.companies : []\n const customValues = sanitizeCustomValues(\n record.customValues ?? record.custom_values ?? null,\n )\n const customFieldEntries = sanitizeCustomFieldEntries(\n record.customFields ?? record.custom_fields ?? null,\n customValues,\n )\n return normalizeDeal({\n id,\n title,\n status,\n pipelineStage,\n pipelineId,\n pipelineStageId,\n valueAmount,\n valueCurrency,\n probability,\n expectedCloseAt,\n description,\n ownerUserId,\n source,\n closureOutcome,\n lossReasonId,\n lossNotes,\n createdAt,\n updatedAt,\n personIds: personIds as string[] | undefined,\n people: people as { id: string; label: string }[] | undefined,\n companyIds: companyIds as string[] | undefined,\n companies: companies as { id: string; label: string }[] | undefined,\n customValues,\n customFields: customFieldEntries,\n })\n })\n setDeals((prev) => {\n if (!append) return mapped\n const mappedById = new Map(mapped.map((deal) => [deal.id, deal]))\n const prevIds = new Set(prev.map((deal) => deal.id))\n const updatedPrev = prev.map((deal) => mappedById.get(deal.id) ?? deal)\n const appended = mapped.filter((deal) => !prevIds.has(deal.id))\n return [...updatedPrev, ...appended]\n })\n pageRef.current = nextPage\n // Short-page termination, unconditionally \u2014 see `hasMoreFromPage`.\n // Preferring `totalPages` here hid deals that do exist. Measured on\n // `rawItems`, which is what the server served, rather than on the\n // deduped rows appended above.\n const nextHasMore = hasMoreFromPage(rawItems.length, DEALS_PAGE_SIZE)\n hasMoreRef.current = nextHasMore\n setHasMore(nextHasMore)\n setLoadError(null)\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : translate('customers.people.detail.deals.loadError', 'Failed to load deals.')\n setLoadError(message)\n if (!append) {\n setHasMore(false)\n hasMoreRef.current = false\n }\n } finally {\n setIsLoading(false)\n popLoading()\n }\n }, [popLoading, pushLoading, scope, translate])\n\n React.useEffect(() => {\n loadDeals({ append: false }).catch(() => {})\n }, [loadDeals, scope])\n\n const openCreateDialog = React.useCallback(() => {\n if (!scope) return\n setInitialValues({\n personIds: scope.kind === 'person' ? [scope.entityId] : [],\n companyIds: scope.kind === 'company' ? [scope.entityId] : [],\n })\n setDialogOpen(true)\n }, [scope])\n\n const [linkDialogOpen, setLinkDialogOpen] = React.useState(false)\n const openLinkDialog = React.useCallback(() => {\n if (!scope) return\n setLinkDialogOpen(true)\n }, [scope])\n\n const existingDealIds = React.useMemo(() => deals.map((deal) => deal.id), [deals])\n\n const dealLinkAdapter = React.useMemo(\n () =>\n createDealLinkAdapter({\n dialogTitle: t('customers.linking.deal.dialogTitle', 'Link deal'),\n dialogSubtitle: t(\n 'customers.linking.deal.dialogSubtitle',\n 'Link an existing deal to this record',\n ),\n sectionLabel: t('customers.linking.deal.sectionLabel', 'MATCHING DEALS'),\n searchPlaceholder: t('customers.linking.deal.searchPlaceholder', 'Search all deals\u2026'),\n searchEmptyHint: t('customers.linking.deal.searchEmpty', 'No matching deals found.'),\n selectedEmptyHint: t('customers.linking.deal.selectedEmpty', 'No deals selected.'),\n confirmButtonLabel: t('customers.linking.deal.confirmButton', 'Link deal'),\n orphanWarningTitle: t('customers.linking.deal.orphanWarningTitle', 'Deal without company'),\n orphanWarningMessage: t(\n 'customers.linking.deal.orphanWarning',\n 'This deal has no other linked entities. If you unlink it later, it will become unreachable.',\n ),\n contextEntityId: scope?.entityId,\n }),\n [scope?.entityId, t],\n )\n\n const handleLinkConfirm = React.useCallback(\n async ({\n addedIds,\n removedIds,\n }: {\n addedIds: string[]\n removedIds: string[]\n }) => {\n if (!scope) return\n if (!addedIds.length && !removedIds.length) return\n pushLoading()\n try {\n for (const dealId of addedIds) {\n const payload = await readApiResultOrThrow<Record<string, unknown>>(\n `/api/customers/deals/${encodeURIComponent(dealId)}`,\n )\n const currentPersonIds = Array.isArray(payload.personIds)\n ? (payload.personIds as string[]).filter((id) => typeof id === 'string')\n : []\n const currentCompanyIds = Array.isArray(payload.companyIds)\n ? (payload.companyIds as string[]).filter((id) => typeof id === 'string')\n : []\n const nextPersonIds =\n scope.kind === 'person' && !currentPersonIds.includes(scope.entityId)\n ? [...currentPersonIds, scope.entityId]\n : currentPersonIds\n const nextCompanyIds =\n scope.kind === 'company' && !currentCompanyIds.includes(scope.entityId)\n ? [...currentCompanyIds, scope.entityId]\n : currentCompanyIds\n await runWriteMutation(\n () =>\n // optimistic-lock-exempt: deal association list (link)\n updateCrud(\n 'customers/deals',\n { id: dealId, personIds: nextPersonIds, companyIds: nextCompanyIds },\n {\n errorMessage: t(\n 'customers.people.detail.deals.linkError',\n 'Failed to link deal.',\n ),\n },\n ),\n { dealId, scopeKind: scope.kind, scopeEntityId: scope.entityId, operation: 'linkDeal' },\n )\n }\n for (const dealId of removedIds) {\n const payload = await readApiResultOrThrow<Record<string, unknown>>(\n `/api/customers/deals/${encodeURIComponent(dealId)}`,\n )\n const currentPersonIds = Array.isArray(payload.personIds)\n ? (payload.personIds as string[]).filter((id) => typeof id === 'string')\n : []\n const currentCompanyIds = Array.isArray(payload.companyIds)\n ? (payload.companyIds as string[]).filter((id) => typeof id === 'string')\n : []\n const nextPersonIds =\n scope.kind === 'person'\n ? currentPersonIds.filter((id) => id !== scope.entityId)\n : currentPersonIds\n const nextCompanyIds =\n scope.kind === 'company'\n ? currentCompanyIds.filter((id) => id !== scope.entityId)\n : currentCompanyIds\n await runWriteMutation(\n () =>\n // optimistic-lock-exempt: deal association list (unlink)\n updateCrud(\n 'customers/deals',\n { id: dealId, personIds: nextPersonIds, companyIds: nextCompanyIds },\n {\n errorMessage: t(\n 'customers.people.detail.deals.unlinkError',\n 'Failed to unlink deal.',\n ),\n },\n ),\n { dealId, scopeKind: scope.kind, scopeEntityId: scope.entityId, operation: 'unlinkDeal' },\n )\n }\n await loadDeals({ append: false })\n await refreshParentData()\n if (addedIds.length + removedIds.length > 0) {\n onCountDelta?.(addedIds.length - removedIds.length)\n }\n flash(\n addedIds.length > 0\n ? t('customers.people.detail.deals.linkSuccess', 'Deal linked.')\n : t('customers.people.detail.deals.unlinkSuccess', 'Deal unlinked.'),\n 'success',\n )\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : t('customers.people.detail.deals.linkError', 'Failed to link deal.')\n flash(message, 'error')\n } finally {\n popLoading()\n }\n },\n [loadDeals, onCountDelta, popLoading, pushLoading, refreshParentData, runWriteMutation, scope, t],\n )\n\n const closeDialog = React.useCallback(() => {\n setDialogOpen(false)\n setInitialValues(undefined)\n }, [])\n\n const handleDialogOpenChange = React.useCallback(\n (next: boolean) => {\n if (!next) closeDialog()\n else setDialogOpen(true)\n },\n [closeDialog],\n )\n\n const handleCreate = React.useCallback(\n async ({ base, custom }: DealFormSubmitPayload) => {\n if (!scope) {\n throw new Error(translate('customers.people.detail.deals.error', 'Failed to save deal.'))\n }\n setPendingAction({ kind: 'create' })\n pushLoading()\n try {\n const personIds = mergeIds(base.personIds)\n const companyIds = mergeIds(base.companyIds)\n\n const payload: Record<string, unknown> = {\n title: base.title,\n status: base.status ?? undefined,\n pipelineStage: base.pipelineStage ?? undefined,\n pipelineId: base.pipelineId ?? undefined,\n pipelineStageId: base.pipelineStageId ?? undefined,\n valueAmount: typeof base.valueAmount === 'number' ? base.valueAmount : undefined,\n valueCurrency: base.valueCurrency ?? undefined,\n probability: typeof base.probability === 'number' ? base.probability : undefined,\n expectedCloseAt: base.expectedCloseAt ?? undefined,\n description: base.description ?? undefined,\n personIds,\n companyIds,\n }\n if (Object.keys(custom).length) payload.customFields = custom\n const { result } = await runWriteMutation(\n () =>\n // optimistic-lock-exempt: deal create-only, no prior version\n createCrud<{ id?: string }>('customers/deals', payload, {\n errorMessage: translate('customers.people.detail.deals.error', 'Failed to save deal.'),\n }),\n {\n ...payload,\n operation: 'createDeal',\n },\n )\n const dealId =\n typeof result?.id === 'string' && result.id.trim().length ? result.id : generateTempId()\n const belongsToScope =\n (scope.kind !== 'person' || personIds.includes(scope.entityId)) &&\n (scope.kind !== 'company' || companyIds.includes(scope.entityId))\n if (belongsToScope) {\n const customValuesForState = sanitizeCustomValues(\n Object.keys(custom).length ? custom : null,\n )\n const timestamp = new Date().toISOString()\n const normalized = normalizeDeal({\n id: dealId,\n title: base.title,\n status: base.status ?? null,\n pipelineStage: base.pipelineStage ?? null,\n pipelineId: base.pipelineId ?? null,\n pipelineStageId: base.pipelineStageId ?? null,\n valueAmount: base.valueAmount ?? null,\n valueCurrency: base.valueCurrency ?? null,\n probability: base.probability ?? null,\n expectedCloseAt: base.expectedCloseAt ?? null,\n description: base.description ?? null,\n personIds,\n companyIds,\n customValues: customValuesForState,\n createdAt: timestamp,\n updatedAt: timestamp,\n })\n setDeals((prev) => [normalized, ...prev])\n onCountDelta?.(1)\n }\n await refreshParentData()\n flash(translate('customers.people.detail.deals.success', 'Deal created.'), 'success')\n } finally {\n setPendingAction(null)\n popLoading()\n }\n },\n [onCountDelta, popLoading, pushLoading, refreshParentData, runWriteMutation, scope, translate],\n )\n\n const handleUnlink = React.useCallback(\n async (deal: NormalizedDeal) => {\n if (!scope) return\n\n const nextPersonIds =\n scope.kind === 'person'\n ? deal.personIds.filter((id) => id !== scope.entityId)\n : deal.personIds\n const nextCompanyIds =\n scope.kind === 'company'\n ? deal.companyIds.filter((id) => id !== scope.entityId)\n : deal.companyIds\n\n const confirmed = await confirm({\n title:\n scope.kind === 'person'\n ? translate('customers.people.detail.deals.unlinkConfirmPerson', 'Unlink this deal from this person?')\n : translate('customers.people.detail.deals.unlinkConfirmCompany', 'Unlink this deal from this company?'),\n description: translate(\n 'customers.people.detail.deals.unlinkDescription',\n 'The deal will remain available from its own detail page.',\n ),\n confirmText: translate('customers.people.card.unlink', 'Unlink'),\n cancelText: translate('customers.people.detail.deals.cancel', 'Cancel'),\n })\n if (!confirmed) return\n\n setPendingAction({ kind: 'remove', id: deal.id })\n pushLoading()\n try {\n const payload: Record<string, unknown> = {\n id: deal.id,\n personIds: nextPersonIds,\n companyIds: nextCompanyIds,\n }\n await runWriteMutation(\n () =>\n // optimistic-lock-exempt: deal association list (unlink)\n updateCrud('customers/deals', payload, {\n errorMessage: translate('customers.people.detail.deals.unlinkError', 'Failed to unlink deal.'),\n }),\n {\n ...payload,\n operation: 'unlinkDeal',\n },\n )\n setDeals((prev) => prev.filter((item) => item.id !== deal.id))\n onCountDelta?.(-1)\n await refreshParentData()\n flash(translate('customers.people.detail.deals.unlinkSuccess', 'Deal unlinked.'), 'success')\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : translate('customers.people.detail.deals.unlinkError', 'Failed to unlink deal.')\n flash(message, 'error')\n } finally {\n setPendingAction(null)\n popLoading()\n }\n },\n [confirm, onCountDelta, popLoading, pushLoading, refreshParentData, runWriteMutation, scope, translate],\n )\n\n const handleDialogSubmit = React.useCallback(\n async (payload: DealFormSubmitPayload) => {\n try {\n await handleCreate(payload)\n closeDialog()\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : translate('customers.people.detail.deals.error', 'Failed to save deal.')\n flash(message, 'error')\n }\n },\n [closeDialog, handleCreate, translate],\n )\n\n React.useEffect(() => {\n if (!onActionChange) return\n const disabled = !scope || isLoading || pendingAction !== null\n const action: SectionAction = {\n label: addActionLabel,\n onClick: () => {\n if (!disabled) openCreateDialog()\n },\n disabled,\n }\n onActionChange(action)\n return () => {\n onActionChange(null)\n }\n }, [addActionLabel, isLoading, onActionChange, openCreateDialog, pendingAction, scope])\n\n const isFormPending = pendingAction?.kind === 'create'\n\n const sortedDeals = React.useMemo(() => {\n return [...deals].sort((a, b) => {\n const timeA = a.updatedAt ?? a.createdAt ?? ''\n const timeB = b.updatedAt ?? b.createdAt ?? ''\n return timeB.localeCompare(timeA)\n })\n }, [deals])\n\n return (\n <div className=\"mt-4 space-y-4\">\n {loadError ? (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-sm text-destructive\">\n {loadError}\n </div>\n ) : null}\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={openLinkDialog}\n disabled={!scope || pendingAction !== null}\n >\n <Link2 className=\"mr-1.5 size-3.5\" />\n {t('customers.people.detail.deals.linkExisting', 'Link existing deal')}\n </Button>\n <Button\n type=\"button\"\n variant=\"default\"\n size=\"sm\"\n onClick={openCreateDialog}\n disabled={!scope || pendingAction !== null}\n >\n <Plus className=\"mr-1.5 size-3.5\" />\n {addActionLabel}\n </Button>\n </div>\n {isLoading && sortedDeals.length === 0 ? (\n <LoadingMessage\n label={t('customers.people.detail.deals.loading', 'Loading deals\u2026')}\n className=\"border-0 bg-transparent p-0 py-8 justify-center\"\n />\n ) : (\n <>\n {!isLoading && sortedDeals.length === 0 ? (\n <TabEmptyState\n title={emptyState.title}\n action={{\n label: emptyState.actionLabel,\n onClick: openCreateDialog,\n disabled: !scope || pendingAction !== null,\n }}\n />\n ) : null}\n <div className=\"space-y-4\">\n {sortedDeals.map((deal) => {\n const valueLabel = formatValueLabel(deal.valueAmount, deal.valueCurrency ?? null, emptyLabel, locale)\n const expectedLabel = deal.expectedCloseAt ? formatDate(deal.expectedCloseAt, locale) ?? emptyLabel : emptyLabel\n const probabilityLabel =\n typeof deal.probability === 'number' ? `${deal.probability}%` : emptyLabel\n const isUnlinkPending = pendingAction?.kind === 'remove' && pendingAction.id === deal.id\n const statusLabel =\n deal.status && statusDictionaryMap\n ? statusDictionaryMap[deal.status]?.label ?? deal.status\n : deal.status ?? emptyLabel\n return (\n <article key={deal.id} className=\"group rounded-lg border bg-card p-4 shadow-xs transition hover:border-border/70\">\n <header className=\"flex flex-wrap items-center justify-between gap-2\">\n <div>\n <Link\n href={`/backend/customers/deals/${encodeURIComponent(deal.id)}`}\n className=\"text-base font-semibold text-foreground transition hover:text-primary hover:underline\"\n >\n {deal.title || emptyLabel}\n </Link>\n {deal.description ? (\n <p className=\"mt-1 line-clamp-3 text-sm text-muted-foreground whitespace-pre-wrap\">{deal.description}</p>\n ) : null}\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs font-medium uppercase text-muted-foreground\">\n {statusLabel}\n </span>\n <div className=\"flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100\">\n <IconButton asChild variant=\"ghost\" size=\"sm\" className=\"h-8 w-8\">\n <Link\n href={`/backend/customers/deals/${encodeURIComponent(deal.id)}`}\n aria-label={t('customers.people.detail.deals.edit', 'Open deal details')}\n >\n <Pencil className=\"size-4\" />\n </Link>\n </IconButton>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-8 rounded-lg px-3 text-xs\"\n onClick={(event) => {\n event.preventDefault()\n void handleUnlink(deal)\n }}\n disabled={pendingAction !== null}\n >\n {isUnlinkPending\n ? t('customers.people.detail.deals.unlinking', 'Unlinking\u2026')\n : t('customers.people.card.unlink', 'Unlink')}\n </Button>\n </div>\n </div>\n </header>\n <dl className=\"mt-3 grid gap-2 text-xs text-muted-foreground sm:grid-cols-2\">\n <div className=\"flex flex-col gap-0.5\">\n <dt className=\"font-medium\">\n {t('customers.people.detail.deals.fields.pipelineStage', 'Pipeline stage')}\n </dt>\n <dd>{deal.pipelineStage ?? emptyLabel}</dd>\n </div>\n <div className=\"flex flex-col gap-0.5\">\n <dt className=\"font-medium\">\n {t('customers.people.detail.deals.fields.probability', 'Probability')}\n </dt>\n <dd>{probabilityLabel}</dd>\n </div>\n <div className=\"flex flex-col gap-0.5\">\n <dt className=\"font-medium\">\n {t('customers.people.detail.deals.fields.valueAmount', 'Value')}\n </dt>\n <dd>{valueLabel}</dd>\n </div>\n <div className=\"flex flex-col gap-0.5\">\n <dt className=\"font-medium\">\n {t('customers.people.detail.deals.fields.expectedCloseAt', 'Expected close')}\n </dt>\n <dd>{expectedLabel}</dd>\n </div>\n </dl>\n <CustomFieldValuesList\n entries={deal.customFields?.map((entry) => ({\n key: entry.key,\n value: entry.value,\n label: entry.label ?? undefined,\n }))}\n values={deal.customValues ?? undefined}\n resources={customFieldResources}\n emptyLabel={emptyLabel}\n itemKeyPrefix={`deal-${deal.id}-field`}\n className=\"mt-3\"\n />\n </article>\n )\n })}\n {isLoading && deals.length > 0 ? (\n <div className=\"flex justify-center\">\n <LoadingMessage\n label={t('customers.people.detail.deals.loading', 'Loading deals\u2026')}\n className=\"border-0 bg-transparent p-0 justify-center [&_span[role='status']]:h-5 [&_span[role='status']]:w-5\"\n />\n </div>\n ) : null}\n {!isLoading && hasMore ? (\n <div className=\"flex justify-center\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n loadDeals({ append: true }).catch(() => {})\n }}\n disabled={pendingAction !== null || isLoading}\n >\n {t('customers.people.detail.deals.loadMore', 'Load more deals')}\n </Button>\n </div>\n ) : null}\n </div>\n </>\n )}\n\n <DealDialog\n open={dialogOpen}\n mode=\"create\"\n onOpenChange={handleDialogOpenChange}\n initialValues={initialValues}\n onSubmit={async (payload) => {\n await handleDialogSubmit(payload)\n }}\n isSubmitting={Boolean(isFormPending)}\n />\n <LinkEntityDialog\n open={linkDialogOpen}\n onOpenChange={setLinkDialogOpen}\n adapter={dealLinkAdapter}\n initialSelectedIds={existingDealIds}\n onConfirm={handleLinkConfirm}\n />\n {ConfirmDialogElement}\n </div>\n )\n}\n\nexport default DealsSection\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import { CUSTOMER_INTERACTION_TASK_SOURCE, CUSTOMER_INTERACTION_TASK_TYPE } from "../../lib/interactionCompatibility.js";
3
- function formatDate(value) {
3
+ function formatDate(value, locale) {
4
4
  if (!value) return null;
5
5
  const date = new Date(value);
6
6
  if (Number.isNaN(date.getTime())) return null;
7
- return date.toLocaleDateString();
7
+ return date.toLocaleDateString(locale);
8
8
  }
9
9
  function formatTemplate(template, params) {
10
10
  if (!template) return template;
@@ -133,15 +133,15 @@ function createDictionarySelectLabels(kind, translate) {
133
133
  return base;
134
134
  }
135
135
  }
136
- function formatCurrency(amount, currency) {
136
+ function formatCurrency(amount, currency, locale) {
137
137
  try {
138
- return new Intl.NumberFormat(void 0, {
138
+ return new Intl.NumberFormat(locale, {
139
139
  style: "currency",
140
140
  currency: currency || "PLN",
141
141
  maximumFractionDigits: 0
142
142
  }).format(amount);
143
143
  } catch {
144
- return `${amount.toLocaleString()} ${currency || "PLN"}`;
144
+ return `${amount.toLocaleString(locale)} ${currency || "PLN"}`;
145
145
  }
146
146
  }
147
147
  function formatFallbackLabel(value) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/components/detail/utils.ts"],
4
- "sourcesContent": ["\"use client\"\n\nimport type { DictionarySelectLabels } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport type { CustomerDictionaryKind } from '../../lib/dictionaries'\nimport { CUSTOMER_INTERACTION_TASK_SOURCE, CUSTOMER_INTERACTION_TASK_TYPE } from '../../lib/interactionCompatibility'\n\n\nexport function formatDate(value?: string | null): string | null {\n if (!value) return null\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return null\n return date.toLocaleDateString()\n}\n\nexport function formatTemplate(template: string, params?: Record<string, string | number>): string {\n if (!template) return template\n if (!params) return template\n return template.replace(/\\{\\{(\\w+)\\}\\}|\\{(\\w+)\\}/g, (match, doubleKey, singleKey) => {\n const key = doubleKey ?? singleKey\n if (!key) return match\n const value = params[key]\n return value === undefined ? match : String(value)\n })\n}\n\nexport function toLocalDateTimeInput(value?: string | null): string {\n if (!value) return ''\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return ''\n const pad = (input: number) => `${input}`.padStart(2, '0')\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(\n date.getMinutes(),\n )}`\n}\n\nexport function resolveTodoHref(source: string, todoId: string | null | undefined): string | null {\n if (!todoId) return null\n if (!source) return null\n if (source === CUSTOMER_INTERACTION_TASK_SOURCE || source === CUSTOMER_INTERACTION_TASK_TYPE) return null\n const [module] = source.split(':')\n if (!module) return null\n if (module === 'example') {\n return `/backend/todos/${encodeURIComponent(todoId)}/edit`\n }\n return `/backend/${module}/todos/${encodeURIComponent(todoId)}/edit`\n}\n\nexport function resolveTodoApiPath(source: string): string | null {\n if (!source) return null\n if (source === CUSTOMER_INTERACTION_TASK_SOURCE || source === CUSTOMER_INTERACTION_TASK_TYPE) {\n return '/api/customers/todos'\n }\n const [module] = source.split(':')\n if (!module) return null\n return `/api/${module}/todos`\n}\n\nexport function createDictionarySelectLabels(\n kind: CustomerDictionaryKind,\n translate: (key: string, fallback: string) => string,\n): DictionarySelectLabels {\n const base = {\n valueLabel: translate('customers.people.form.dictionary.valueLabel', 'Name'),\n valuePlaceholder: translate('customers.people.form.dictionary.valuePlaceholder', 'Name'),\n labelLabel: translate('customers.people.form.dictionary.labelLabel', 'Label'),\n labelPlaceholder: translate('customers.people.form.dictionary.labelPlaceholder', 'Display name shown in UI'),\n emptyError: translate('customers.people.form.dictionary.errorRequired', 'Please enter a name'),\n cancelLabel: translate('customers.people.form.dictionary.cancel', 'Cancel'),\n saveLabel: translate('customers.people.form.dictionary.save', 'Save'),\n saveShortcutHint: translate('customers.people.form.dictionary.saveShortcut', '\u2318/Ctrl + Enter'),\n errorLoad: translate('customers.people.form.dictionary.errorLoad', 'Failed to load options'),\n errorSave: translate('customers.people.form.dictionary.error', 'Failed to save option'),\n loadingLabel: translate('customers.people.form.dictionary.loading', 'Loading\u2026'),\n manageTitle: translate('customers.people.form.dictionary.manage', 'Manage dictionary'),\n placeholder: translate('customers.people.form.dictionary.placeholder', 'Select an option'),\n addLabel: translate('customers.people.form.dictionary.add', 'Add option'),\n addPrompt: translate('customers.people.form.dictionary.prompt', 'Name your option'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitle', 'Add option'),\n } satisfies DictionarySelectLabels\n\n switch (kind) {\n case 'statuses':\n return {\n ...base,\n placeholder: translate('customers.people.form.status.placeholder', 'Select a status'),\n addLabel: translate('customers.people.form.dictionary.addStatus', 'Add status'),\n addPrompt: translate('customers.people.form.dictionary.promptStatus', 'Name the status'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitleStatus', 'Add status'),\n }\n case 'lifecycle-stages':\n return {\n ...base,\n placeholder: translate('customers.people.form.lifecycleStage.placeholder', 'Select a lifecycle stage'),\n addLabel: translate('customers.people.form.dictionary.addLifecycleStage', 'Add lifecycle stage'),\n addPrompt: translate('customers.people.form.dictionary.promptLifecycleStage', 'Name the lifecycle stage'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitleLifecycleStage', 'Add lifecycle stage'),\n }\n case 'sources':\n return {\n ...base,\n placeholder: translate('customers.people.form.source.placeholder', 'Select a source'),\n addLabel: translate('customers.people.form.dictionary.addSource', 'Add source'),\n addPrompt: translate('customers.people.form.dictionary.promptSource', 'Name the source'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitleSource', 'Add source'),\n }\n case 'activity-types':\n return {\n ...base,\n placeholder: translate('customers.people.form.activityType.placeholder', 'Select an activity type'),\n addLabel: translate('customers.people.form.dictionary.addActivityType', 'Add activity type'),\n addPrompt: translate('customers.people.form.dictionary.promptActivityType', 'Name the activity type'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitleActivityType', 'Add activity type'),\n }\n case 'deal-statuses':\n return {\n ...base,\n placeholder: translate('customers.deals.form.status.placeholder', 'Select a deal status'),\n addLabel: translate('customers.deals.form.dictionary.addStatus', 'Add deal status'),\n addPrompt: translate('customers.deals.form.dictionary.promptStatus', 'Name the deal status'),\n dialogTitle: translate('customers.deals.form.dictionary.dialogTitleStatus', 'Add deal status'),\n }\n case 'pipeline-stages':\n return {\n ...base,\n placeholder: translate('customers.deals.form.pipeline.placeholder', 'Select a pipeline stage'),\n addLabel: translate('customers.deals.form.dictionary.addPipelineStage', 'Add pipeline stage'),\n addPrompt: translate('customers.deals.form.dictionary.promptPipelineStage', 'Name the pipeline stage'),\n dialogTitle: translate('customers.deals.form.dictionary.dialogTitlePipelineStage', 'Add pipeline stage'),\n }\n case 'job-titles':\n return {\n ...base,\n placeholder: translate('customers.people.form.jobTitle.placeholder', 'Select a job title'),\n addLabel: translate('customers.people.form.dictionary.addJobTitle', 'Add job title'),\n addPrompt: translate('customers.people.form.dictionary.promptJobTitle', 'Name the job title'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitleJobTitle', 'Add job title'),\n }\n case 'address-types':\n return {\n ...base,\n placeholder: translate('customers.people.form.addressType.placeholder', 'Select an address type'),\n addLabel: translate('customers.people.form.dictionary.addAddressType', 'Add address type'),\n addPrompt: translate('customers.people.form.dictionary.promptAddressType', 'Name the address type'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitleAddressType', 'Add address type'),\n }\n default:\n return base\n }\n}\n\nexport function formatCurrency(amount: number, currency?: string | null): string {\n try {\n return new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency: currency || 'PLN',\n maximumFractionDigits: 0,\n }).format(amount)\n } catch {\n return `${amount.toLocaleString()} ${currency || 'PLN'}`\n }\n}\n\nexport function formatFallbackLabel(value: string): string {\n return value\n .replace(/[_-]+/g, ' ')\n .replace(/^\\w/, (c) => c.toUpperCase())\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport type { DictionarySelectLabels } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport type { CustomerDictionaryKind } from '../../lib/dictionaries'\nimport { CUSTOMER_INTERACTION_TASK_SOURCE, CUSTOMER_INTERACTION_TASK_TYPE } from '../../lib/interactionCompatibility'\n\n\n/**\n * Pass `locale` to format in the application locale (`useLocale()` in client components).\n * Omitting it keeps the runtime default, which varies per machine and is therefore not\n * assertable in tests.\n */\nexport function formatDate(value?: string | null, locale?: string): string | null {\n if (!value) return null\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return null\n return date.toLocaleDateString(locale)\n}\n\nexport function formatTemplate(template: string, params?: Record<string, string | number>): string {\n if (!template) return template\n if (!params) return template\n return template.replace(/\\{\\{(\\w+)\\}\\}|\\{(\\w+)\\}/g, (match, doubleKey, singleKey) => {\n const key = doubleKey ?? singleKey\n if (!key) return match\n const value = params[key]\n return value === undefined ? match : String(value)\n })\n}\n\nexport function toLocalDateTimeInput(value?: string | null): string {\n if (!value) return ''\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return ''\n const pad = (input: number) => `${input}`.padStart(2, '0')\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(\n date.getMinutes(),\n )}`\n}\n\nexport function resolveTodoHref(source: string, todoId: string | null | undefined): string | null {\n if (!todoId) return null\n if (!source) return null\n if (source === CUSTOMER_INTERACTION_TASK_SOURCE || source === CUSTOMER_INTERACTION_TASK_TYPE) return null\n const [module] = source.split(':')\n if (!module) return null\n if (module === 'example') {\n return `/backend/todos/${encodeURIComponent(todoId)}/edit`\n }\n return `/backend/${module}/todos/${encodeURIComponent(todoId)}/edit`\n}\n\nexport function resolveTodoApiPath(source: string): string | null {\n if (!source) return null\n if (source === CUSTOMER_INTERACTION_TASK_SOURCE || source === CUSTOMER_INTERACTION_TASK_TYPE) {\n return '/api/customers/todos'\n }\n const [module] = source.split(':')\n if (!module) return null\n return `/api/${module}/todos`\n}\n\nexport function createDictionarySelectLabels(\n kind: CustomerDictionaryKind,\n translate: (key: string, fallback: string) => string,\n): DictionarySelectLabels {\n const base = {\n valueLabel: translate('customers.people.form.dictionary.valueLabel', 'Name'),\n valuePlaceholder: translate('customers.people.form.dictionary.valuePlaceholder', 'Name'),\n labelLabel: translate('customers.people.form.dictionary.labelLabel', 'Label'),\n labelPlaceholder: translate('customers.people.form.dictionary.labelPlaceholder', 'Display name shown in UI'),\n emptyError: translate('customers.people.form.dictionary.errorRequired', 'Please enter a name'),\n cancelLabel: translate('customers.people.form.dictionary.cancel', 'Cancel'),\n saveLabel: translate('customers.people.form.dictionary.save', 'Save'),\n saveShortcutHint: translate('customers.people.form.dictionary.saveShortcut', '\u2318/Ctrl + Enter'),\n errorLoad: translate('customers.people.form.dictionary.errorLoad', 'Failed to load options'),\n errorSave: translate('customers.people.form.dictionary.error', 'Failed to save option'),\n loadingLabel: translate('customers.people.form.dictionary.loading', 'Loading\u2026'),\n manageTitle: translate('customers.people.form.dictionary.manage', 'Manage dictionary'),\n placeholder: translate('customers.people.form.dictionary.placeholder', 'Select an option'),\n addLabel: translate('customers.people.form.dictionary.add', 'Add option'),\n addPrompt: translate('customers.people.form.dictionary.prompt', 'Name your option'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitle', 'Add option'),\n } satisfies DictionarySelectLabels\n\n switch (kind) {\n case 'statuses':\n return {\n ...base,\n placeholder: translate('customers.people.form.status.placeholder', 'Select a status'),\n addLabel: translate('customers.people.form.dictionary.addStatus', 'Add status'),\n addPrompt: translate('customers.people.form.dictionary.promptStatus', 'Name the status'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitleStatus', 'Add status'),\n }\n case 'lifecycle-stages':\n return {\n ...base,\n placeholder: translate('customers.people.form.lifecycleStage.placeholder', 'Select a lifecycle stage'),\n addLabel: translate('customers.people.form.dictionary.addLifecycleStage', 'Add lifecycle stage'),\n addPrompt: translate('customers.people.form.dictionary.promptLifecycleStage', 'Name the lifecycle stage'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitleLifecycleStage', 'Add lifecycle stage'),\n }\n case 'sources':\n return {\n ...base,\n placeholder: translate('customers.people.form.source.placeholder', 'Select a source'),\n addLabel: translate('customers.people.form.dictionary.addSource', 'Add source'),\n addPrompt: translate('customers.people.form.dictionary.promptSource', 'Name the source'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitleSource', 'Add source'),\n }\n case 'activity-types':\n return {\n ...base,\n placeholder: translate('customers.people.form.activityType.placeholder', 'Select an activity type'),\n addLabel: translate('customers.people.form.dictionary.addActivityType', 'Add activity type'),\n addPrompt: translate('customers.people.form.dictionary.promptActivityType', 'Name the activity type'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitleActivityType', 'Add activity type'),\n }\n case 'deal-statuses':\n return {\n ...base,\n placeholder: translate('customers.deals.form.status.placeholder', 'Select a deal status'),\n addLabel: translate('customers.deals.form.dictionary.addStatus', 'Add deal status'),\n addPrompt: translate('customers.deals.form.dictionary.promptStatus', 'Name the deal status'),\n dialogTitle: translate('customers.deals.form.dictionary.dialogTitleStatus', 'Add deal status'),\n }\n case 'pipeline-stages':\n return {\n ...base,\n placeholder: translate('customers.deals.form.pipeline.placeholder', 'Select a pipeline stage'),\n addLabel: translate('customers.deals.form.dictionary.addPipelineStage', 'Add pipeline stage'),\n addPrompt: translate('customers.deals.form.dictionary.promptPipelineStage', 'Name the pipeline stage'),\n dialogTitle: translate('customers.deals.form.dictionary.dialogTitlePipelineStage', 'Add pipeline stage'),\n }\n case 'job-titles':\n return {\n ...base,\n placeholder: translate('customers.people.form.jobTitle.placeholder', 'Select a job title'),\n addLabel: translate('customers.people.form.dictionary.addJobTitle', 'Add job title'),\n addPrompt: translate('customers.people.form.dictionary.promptJobTitle', 'Name the job title'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitleJobTitle', 'Add job title'),\n }\n case 'address-types':\n return {\n ...base,\n placeholder: translate('customers.people.form.addressType.placeholder', 'Select an address type'),\n addLabel: translate('customers.people.form.dictionary.addAddressType', 'Add address type'),\n addPrompt: translate('customers.people.form.dictionary.promptAddressType', 'Name the address type'),\n dialogTitle: translate('customers.people.form.dictionary.dialogTitleAddressType', 'Add address type'),\n }\n default:\n return base\n }\n}\n\n/**\n * Pass `locale` to format in the application locale (`useLocale()` in client components).\n * Omitting it keeps the runtime default, which varies per machine and is therefore not\n * assertable in tests.\n */\nexport function formatCurrency(amount: number, currency?: string | null, locale?: string): string {\n try {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: currency || 'PLN',\n maximumFractionDigits: 0,\n }).format(amount)\n } catch {\n return `${amount.toLocaleString(locale)} ${currency || 'PLN'}`\n }\n}\n\nexport function formatFallbackLabel(value: string): string {\n return value\n .replace(/[_-]+/g, ' ')\n .replace(/^\\w/, (c) => c.toUpperCase())\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -35,7 +35,7 @@ import { buildOptimisticLockHeader } from "@open-mercato/ui/backend/utils/optimi
35
35
  import { surfaceRecordConflict } from "@open-mercato/ui/backend/conflicts";
36
36
  import { collectCustomFieldValues } from "@open-mercato/ui/backend/utils/customFieldValues";
37
37
  import { mapCrudServerErrorToFormErrors } from "@open-mercato/ui/backend/utils/serverErrors";
38
- import { useT } from "@open-mercato/shared/lib/i18n/context";
38
+ import { useT, useLocale } from "@open-mercato/shared/lib/i18n/context";
39
39
  import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
40
40
  import { cn } from "@open-mercato/shared/lib/utils";
41
41
  import { ContactEmailDisplay } from "@open-mercato/core/modules/sales/components/ContactEmailDisplay";
@@ -70,13 +70,13 @@ import { buildRecordInjectionContext, useSetCurrentRecordInjectionContext } from
70
70
  import { useSalesChannelsEnabled } from "@open-mercato/core/modules/sales/components/useSalesChannelsEnabled";
71
71
  import { createLogger } from "@open-mercato/shared/lib/logger";
72
72
  const logger = createLogger("sales");
73
- function formatMessageAmount(amount, currency) {
73
+ function formatMessageAmount(amount, currency, locale) {
74
74
  if (typeof amount !== "number" || !Number.isFinite(amount)) return null;
75
- if (!currency) return amount.toLocaleString();
75
+ if (!currency) return amount.toLocaleString(locale);
76
76
  try {
77
- return new Intl.NumberFormat(void 0, { style: "currency", currency }).format(amount);
77
+ return new Intl.NumberFormat(locale, { style: "currency", currency }).format(amount);
78
78
  } catch {
79
- return `${amount.toLocaleString()} ${currency}`;
79
+ return `${amount.toLocaleString(locale)} ${currency}`;
80
80
  }
81
81
  }
82
82
  function CurrencyInlineEditor({
@@ -1502,6 +1502,7 @@ function SalesDocumentDetailPage({
1502
1502
  includeAmountInMessageMetadata
1503
1503
  }) {
1504
1504
  const t = useT();
1505
+ const locale = useLocale();
1505
1506
  const { enabled: channelsEnabled } = useSalesChannelsEnabled();
1506
1507
  const router = useRouter();
1507
1508
  const searchParams = useSearchParams();
@@ -2264,7 +2265,7 @@ function SalesDocumentDetailPage({
2264
2265
  const metadataEmail = record?.metadata && typeof record.metadata.customerEmail === "string" ? record.metadata.customerEmail : null;
2265
2266
  const contactEmail = resolveCustomerEmail(customerSnapshot) ?? metadataEmail ?? record?.contactEmail ?? null;
2266
2267
  const statusDisplay = record?.status ? statusDictionaryMap[record.status] ?? null : null;
2267
- const previewAmount = formatMessageAmount(record?.grandTotalGrossAmount ?? null, record?.currencyCode ?? null);
2268
+ const previewAmount = formatMessageAmount(record?.grandTotalGrossAmount ?? null, record?.currencyCode ?? null, locale);
2268
2269
  const messagePreviewMetadata = {};
2269
2270
  if (includeAmountInMessageMetadata && previewAmount) {
2270
2271
  messagePreviewMetadata[t("sales.documents.detail.totals.grandTotalGross")] = previewAmount;
@@ -3151,7 +3152,7 @@ function SalesDocumentDetailPage({
3151
3152
  renderDisplay: (params2) => {
3152
3153
  const { value, emptyLabel } = params2;
3153
3154
  if (value && value.length) {
3154
- return /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: new Date(value).toLocaleDateString() });
3155
+ return /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: new Date(value).toLocaleDateString(locale) });
3155
3156
  }
3156
3157
  return /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: emptyLabel });
3157
3158
  }
@@ -3230,6 +3231,7 @@ function SalesDocumentDetailPage({
3230
3231
  shippingMethodLoading,
3231
3232
  shippingMethodOptions,
3232
3233
  t,
3234
+ locale,
3233
3235
  kind,
3234
3236
  saveShortcutLabel
3235
3237
  ]);
@@ -3907,7 +3909,7 @@ function SalesDocumentDetailPage({
3907
3909
  activateOnClick: true,
3908
3910
  containerClassName: "h-full",
3909
3911
  saveLabel: t("customers.people.detail.inline.saveShortcut"),
3910
- renderDisplay: ({ value, emptyLabel }) => value && value.length ? /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: new Date(value).toLocaleDateString() }) : /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: emptyLabel })
3912
+ renderDisplay: ({ value, emptyLabel }) => value && value.length ? /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: new Date(value).toLocaleDateString(locale) }) : /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: emptyLabel })
3911
3913
  },
3912
3914
  "date"
3913
3915
  )