@open-mercato/core 0.10.1-develop.7761.1.9dfaf470ed → 0.10.1-develop.7762.1.657bb7236b

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 (80) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +1 -0
  3. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
  4. package/dist/modules/customers/api/companies/[id]/route.js +3 -2
  5. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  6. package/dist/modules/customers/api/deals/[id]/route.js +11 -12
  7. package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
  8. package/dist/modules/customers/api/people/[id]/route.js +3 -2
  9. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  10. package/dist/modules/customers/backend/customers/companies/create/page.js +6 -0
  11. package/dist/modules/customers/backend/customers/companies/create/page.js.map +2 -2
  12. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +25 -25
  13. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  14. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js +8 -27
  15. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js.map +2 -2
  16. package/dist/modules/customers/backend/customers/deals/[id]/page.js +175 -171
  17. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  18. package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js +25 -24
  19. package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js.map +2 -2
  20. package/dist/modules/customers/backend/customers/people/create/page.js +9 -0
  21. package/dist/modules/customers/backend/customers/people/create/page.js.map +2 -2
  22. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +140 -144
  23. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  24. package/dist/modules/customers/components/detail/CompanyDetailHeader.js +2 -0
  25. package/dist/modules/customers/components/detail/CompanyDetailHeader.js.map +2 -2
  26. package/dist/modules/customers/components/detail/CompanyDetailTabs.js +13 -4
  27. package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
  28. package/dist/modules/customers/components/detail/CreatePersonDialog.js +13 -3
  29. package/dist/modules/customers/components/detail/CreatePersonDialog.js.map +2 -2
  30. package/dist/modules/customers/components/detail/CustomerDetailSidebar.js +29 -0
  31. package/dist/modules/customers/components/detail/CustomerDetailSidebar.js.map +7 -0
  32. package/dist/modules/customers/components/detail/DealDetailHeader.js +4 -2
  33. package/dist/modules/customers/components/detail/DealDetailHeader.js.map +2 -2
  34. package/dist/modules/customers/components/detail/DealDetailTabs.js +9 -1
  35. package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
  36. package/dist/modules/customers/components/detail/DealForm.js +5 -0
  37. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  38. package/dist/modules/customers/components/detail/PersonDetailHeader.js +2 -0
  39. package/dist/modules/customers/components/detail/PersonDetailHeader.js.map +2 -2
  40. package/dist/modules/customers/components/detail/PersonDetailTabs.js +9 -1
  41. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  42. package/dist/modules/customers/components/detail/create/CreateDealForm.js +160 -176
  43. package/dist/modules/customers/components/detail/create/CreateDealForm.js.map +2 -2
  44. package/dist/modules/customers/components/detail/useCustomerInjectedTabs.js +47 -0
  45. package/dist/modules/customers/components/detail/useCustomerInjectedTabs.js.map +7 -0
  46. package/dist/modules/customers/components/formConfig.js +3 -0
  47. package/dist/modules/customers/components/formConfig.js.map +2 -2
  48. package/dist/modules/customers/extension-points.js +14 -4
  49. package/dist/modules/customers/extension-points.js.map +2 -2
  50. package/dist/modules/customers/lib/detailResponseEnrichment.js +38 -0
  51. package/dist/modules/customers/lib/detailResponseEnrichment.js.map +7 -0
  52. package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js +4 -4
  53. package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js.map +2 -2
  54. package/package.json +7 -7
  55. package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +2 -0
  56. package/src/modules/customers/api/companies/[id]/route.ts +3 -2
  57. package/src/modules/customers/api/deals/[id]/route.ts +12 -12
  58. package/src/modules/customers/api/people/[id]/route.ts +3 -2
  59. package/src/modules/customers/backend/customers/companies/create/page.tsx +6 -0
  60. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +27 -30
  61. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.tsx +9 -44
  62. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +7 -3
  63. package/src/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.tsx +25 -27
  64. package/src/modules/customers/backend/customers/people/create/page.tsx +9 -0
  65. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +21 -33
  66. package/src/modules/customers/components/detail/CompanyDetailHeader.tsx +3 -0
  67. package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +15 -4
  68. package/src/modules/customers/components/detail/CreatePersonDialog.tsx +15 -4
  69. package/src/modules/customers/components/detail/CustomerDetailSidebar.tsx +41 -0
  70. package/src/modules/customers/components/detail/DealDetailHeader.tsx +4 -1
  71. package/src/modules/customers/components/detail/DealDetailTabs.tsx +11 -1
  72. package/src/modules/customers/components/detail/DealForm.tsx +5 -0
  73. package/src/modules/customers/components/detail/PersonDetailHeader.tsx +3 -0
  74. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +11 -1
  75. package/src/modules/customers/components/detail/create/CreateDealForm.tsx +126 -209
  76. package/src/modules/customers/components/detail/useCustomerInjectedTabs.tsx +64 -0
  77. package/src/modules/customers/components/formConfig.tsx +3 -0
  78. package/src/modules/customers/extension-points.ts +14 -4
  79. package/src/modules/customers/lib/detailResponseEnrichment.ts +53 -0
  80. package/src/modules/integrations/widgets/injection/external-ids/widget.client.tsx +4 -4
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/customers/backend/customers/deals/%5Bid%5D/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/customers/extension-points'\nimport Link from 'next/link'\nimport { Building2, FileText, Hash, UserSearch } from 'lucide-react'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { useRouter, useSearchParams, usePathname } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, NotesSection, RecordNotFoundState } from '@open-mercato/ui/backend/detail'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { buildRecordInjectionContext, useSetCurrentRecordInjectionContext } from '@open-mercato/ui/backend/injection/recordContext'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { CollapsibleZoneLayout, type ZoneSectionDescriptor } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { E } from '#generated/entities.ids.generated'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { DealClosureActionBar } from '../../../../components/detail/DealClosureActionBar'\nimport { DealDetailHeader } from '../../../../components/detail/DealDetailHeader'\nimport { DealDetailTabs, resolveLegacyTab, type DealTabId } from '../../../../components/detail/DealDetailTabs'\nimport { DealForm, useDealAssociationLookups } from '../../../../components/detail/DealForm'\nimport { DealLinkedEntitiesTab } from '../../../../components/detail/DealLinkedEntitiesTab'\nimport { DealPeopleSection } from '../../../../components/detail/DealPeopleSection'\nimport { ConfirmDealLostDialog } from '../../../../components/detail/ConfirmDealLostDialog'\nimport { DealLostSummaryDialog } from '../../../../components/detail/DealLostSummaryDialog'\nimport { DealWonPopup } from '../../../../components/detail/DealWonPopup'\nimport { InlineActivityComposer } from '../../../../components/detail/InlineActivityComposer'\nimport { PipelineStepper } from '../../../../components/detail/PipelineStepper'\nimport { PlannedActivitiesSection } from '../../../../components/detail/PlannedActivitiesSection'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { createCustomerNotesAdapter } from '../../../../components/detail/notesAdapter'\nimport type { InteractionSummary } from '../../../../components/detail/types'\nimport { readMarkdownPreferenceCookie, writeMarkdownPreferenceCookie } from '../../../../lib/markdownPreference'\nimport { ICON_SUGGESTIONS } from '../../../../lib/dictionaries'\nimport { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\n\nimport { formatCurrency, startOfNextQuarter } from './hooks/formatters'\nimport type { DealDetailPayload } from './hooks/types'\nimport { useDealActivities } from './hooks/useDealActivities'\nimport { useDealAssociations } from './hooks/useDealAssociations'\nimport { useDealClosure } from './hooks/useDealClosure'\nimport { useDealData } from './hooks/useDealData'\nimport { useDealFormHandlers } from './hooks/useDealFormHandlers'\nimport { useDealInjectedTabs } from './hooks/useDealInjectedTabs'\nimport { useDealMutationContext } from './hooks/useDealMutationContext'\nimport { useDealPipeline } from './hooks/useDealPipeline'\nimport { useScheduleDialog } from './hooks/useScheduleDialog'\n\nexport default function DealDetailPage({ params }: { params?: { id?: string } }) {\n const id = params?.id ?? ''\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const pathname = usePathname()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n const zoneSections = React.useMemo<ZoneSectionDescriptor[]>(() => [\n { id: 'details', icon: FileText, label: t('customers.people.detail.deals.form.details', 'Deal details') },\n { id: 'custom', icon: Hash, label: t('customers.people.detail.deals.form.customFields', 'Custom fields') },\n ], [t])\n\n const { data, setData, isLoading, error, isNotFound, loadData } = useDealData(id)\n const [isDirty, setIsDirty] = React.useState(false)\n const {\n scheduleDialogOpen,\n scheduleEditData,\n openSchedule,\n openEdit: openScheduleEdit,\n closeSchedule,\n } = useScheduleDialog()\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n\n const currentDealId = data?.deal.id ?? id\n const { injectionContext, runMutationWithContext } = useDealMutationContext({\n currentDealId,\n fallbackId: id,\n data,\n })\n\n // Publish page-load record context with explicit `updatedAt`/`data` to the\n // AppShell-owned `backend:record:current` mount. The deal path is already in the\n // widget's allowlist (presence works) but supplied no version/record payload \u2014\n // this gives the merge dialog its action-log base and field-diff source.\n useSetCurrentRecordInjectionContext(\n buildRecordInjectionContext({\n resourceKind: 'customers.deal',\n resourceId: data?.deal.id ?? null,\n updatedAt: data?.deal.updatedAt ?? null,\n data: data as Record<string, unknown> | null,\n path: pathname,\n }),\n )\n\n const notesAdapter = React.useMemo(\n () => createCustomerNotesAdapter(detailTranslator, { runMutation: runMutationWithContext }),\n [detailTranslator, runMutationWithContext],\n )\n\n const { injectedTabs, injectedTabMap } = useDealInjectedTabs({\n injectionContext,\n data,\n setData,\n })\n\n const injectedTabIds = React.useMemo(() => injectedTabs.map((tab) => tab.id), [injectedTabs])\n const initialTab = React.useMemo(\n () => resolveLegacyTab(searchParams?.get('tab'), injectedTabIds),\n [injectedTabIds, searchParams],\n )\n const [activeTab, setActiveTab] = React.useState<DealTabId>(initialTab)\n\n React.useEffect(() => {\n setActiveTab(initialTab)\n }, [initialTab])\n\n const { searchCompaniesPage, fetchCompaniesByIds } = useDealAssociationLookups({\n excludeLinkedDealId: data?.deal.id ?? null,\n })\n\n const {\n plannedActivities,\n activityRefreshKey,\n loadPlannedActivities,\n handleActivityCreated,\n handleMarkDone,\n handleCancelActivity,\n } = useDealActivities({ dealId: id, runMutationWithContext })\n\n React.useEffect(() => {\n void Promise.all([loadData({ cache: true }), loadPlannedActivities({ cache: true })])\n }, [loadData, loadPlannedActivities])\n\n const activityEntities = React.useMemo(\n () => (data\n ? [...data.people, ...data.companies].map((entry) => ({\n id: entry.id,\n label: entry.subtitle ? `${entry.label} \u00B7 ${entry.subtitle}` : entry.label,\n kind: entry.kind,\n isPrimary: entry.isPrimary === true,\n }))\n : []),\n [data],\n )\n const [selectedActivityEntityId, setSelectedActivityEntityId] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n setSelectedActivityEntityId((current) => {\n if (activityEntities.length === 1) return activityEntities[0].id\n if (current && activityEntities.some((entry) => entry.id === current)) return current\n const primary = activityEntities.find((entry) => entry.isPrimary)\n return (primary ?? activityEntities[0])?.id ?? null\n })\n }, [activityEntities])\n\n const selectedActivityEntity = React.useMemo(\n () => activityEntities.find((entry) => entry.id === selectedActivityEntityId) ?? null,\n [activityEntities, selectedActivityEntityId],\n )\n\n const dealOptions = React.useMemo(\n () => data ? [{ id: data.deal.id, label: data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal') }] : [],\n [data, t],\n )\n\n const entityOptions = React.useMemo(\n () => activityEntities.map(({ id, label }) => ({ id, label })),\n [activityEntities],\n )\n\n const confirmDiscardIfDirty = React.useCallback(async () => {\n if (!isDirty) return true\n return confirm({\n title: t('customers.deals.detail.unsavedTitle', 'Discard unsaved changes?'),\n description: t(\n 'customers.deals.detail.unsavedDescription',\n 'You have unsaved edits in this deal. Save them first or continue to discard them.',\n ),\n confirmText: t('customers.deals.detail.unsavedConfirm', 'Discard changes'),\n cancelText: t('customers.deals.detail.unsavedCancel', 'Keep editing'),\n variant: 'destructive',\n })\n }, [confirm, isDirty, t])\n\n const {\n peopleEditorIds,\n companiesEditorIds,\n peopleSaving,\n companiesSaving,\n handlePeopleAssociationsChange,\n handleCompaniesAssociationsChange,\n loadLinkedCompaniesPage,\n } = useDealAssociations({\n currentDealId,\n data,\n setData,\n runMutationWithContext,\n onRefresh: () => loadData(),\n })\n\n const { isStageSaving, handleStageChange } = useDealPipeline({\n currentDealId,\n data,\n runMutationWithContext,\n confirmDiscardIfDirty,\n onStageChanged: loadData,\n })\n\n const {\n lostDialogOpen,\n wonPopupOpen,\n lostPopupOpen,\n wonStats,\n lostStats,\n openLostDialog,\n closeLostDialog,\n closeWonPopup,\n closeLostPopup,\n handleWon,\n handleLostConfirm,\n } = useDealClosure({\n currentDealId,\n dealUpdatedAt: data?.deal.updatedAt ?? null,\n runMutationWithContext,\n confirmDiscardIfDirty,\n onClosed: loadData,\n })\n\n const handleTabChange = React.useCallback(async (tab: DealTabId) => {\n if (!(await confirmDiscardIfDirty())) return\n setActiveTab(tab)\n const nextParams = new URLSearchParams(searchParams?.toString() ?? '')\n nextParams.set('tab', tab)\n router.replace(`/backend/customers/deals/${encodeURIComponent(id)}?${nextParams.toString()}`, { scroll: false })\n }, [confirmDiscardIfDirty, id, router, searchParams])\n\n const { isSaving, handleFormSubmit, handleDelete, handleHeaderSave } = useDealFormHandlers({\n data,\n currentDealId,\n loadData,\n runMutationWithContext,\n formWrapperRef,\n confirm,\n })\n\n const handleEditActivity = React.useCallback((activity: InteractionSummary) => {\n if (activity.entityId && activityEntities.some((entry) => entry.id === activity.entityId)) {\n setSelectedActivityEntityId(activity.entityId)\n }\n // Forward `customValues` so per-type chip state (callPhoneNumber,\n // callDirection, taskPriority) round-trips on edit (#1808 phone persistence).\n // Forward `occurredAt` so historical activity edits prefill from the\n // original moment instead of \"today\" (#1807 prefill).\n const rawActivity = activity as unknown as Record<string, unknown>\n openScheduleEdit({\n id: activity.id,\n updatedAt: typeof rawActivity.updatedAt === 'string' ? rawActivity.updatedAt as string : typeof rawActivity.updated_at === 'string' ? rawActivity.updated_at as string : null,\n // Pin the edit payload to the activity's own entity \u2014 the deal page can\n // show activities from more than one linked entity, and the dialog has\n // no entity picker, so it must never silently re-link on save (#6050).\n entityId: activity.entityId ?? selectedActivityEntityId ?? null,\n interactionType: activity.interactionType,\n title: activity.title ?? null,\n body: activity.body ?? null,\n scheduledAt: activity.scheduledAt ?? null,\n occurredAt: activity.occurredAt ?? null,\n durationMinutes: activity.duration ?? null,\n priority: activity.priority ?? null,\n location: activity.location ?? null,\n allDay: activity.allDay ?? null,\n recurrenceRule: activity.recurrenceRule ?? null,\n recurrenceEnd: activity.recurrenceEnd ?? null,\n participants: activity.participants ?? null,\n reminderMinutes: activity.reminderMinutes ?? null,\n visibility: activity.visibility ?? null,\n linkedEntities: activity.linkedEntities ?? null,\n guestPermissions: activity.guestPermissions ?? null,\n ...(rawActivity.customValues && typeof rawActivity.customValues === 'object'\n ? { customValues: rawActivity.customValues as Record<string, unknown> }\n : {}),\n ...(typeof rawActivity.phoneNumber === 'string'\n ? { phoneNumber: rawActivity.phoneNumber as string }\n : {}),\n } as ScheduleActivityEditData & { customValues?: Record<string, unknown> | null; phoneNumber?: string | null })\n }, [activityEntities, openScheduleEdit, selectedActivityEntityId])\n\n const handleViewDashboard = React.useCallback(() => {\n closeWonPopup()\n router.push('/backend')\n }, [closeWonPopup, router])\n\n const handleBackToPipeline = React.useCallback(() => {\n closeWonPopup()\n closeLostPopup()\n router.push('/backend/customers/deals/pipeline')\n }, [closeLostPopup, closeWonPopup, router])\n\n const handleScheduleLostFollowUp = React.useCallback(() => {\n if (!data || !selectedActivityEntity) return\n const nextQuarterDate = startOfNextQuarter(new Date())\n closeLostPopup()\n openScheduleEdit({\n id: '',\n interactionType: 'task',\n title: data.deal.title\n ? t('customers.deals.detail.lost.followUpTitle', 'Revisit {{title}}', { title: data.deal.title })\n : t('customers.deals.detail.lost.followUpFallbackTitle', 'Revisit closed deal'),\n body: data.deal.lossNotes ?? null,\n scheduledAt: nextQuarterDate.toISOString(),\n durationMinutes: 30,\n location: null,\n allDay: false,\n recurrenceRule: null,\n recurrenceEnd: null,\n participants: null,\n reminderMinutes: 1440,\n visibility: 'team',\n linkedEntities: [\n {\n id: data.deal.id,\n type: 'deal',\n label: data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal'),\n },\n ],\n })\n }, [closeLostPopup, data, openScheduleEdit, selectedActivityEntity, t])\n\n const currentPipelineName = data\n ? data.pipelineName ?? wonStats?.pipelineName ?? lostStats?.pipelineName ?? null\n : wonStats?.pipelineName ?? lostStats?.pipelineName ?? null\n const formPipelineOptions = React.useMemo(\n () => data?.deal.pipelineId\n ? [{\n id: data.deal.pipelineId,\n name: currentPipelineName ?? t('customers.deals.detail.pipeline.defaultName', 'Current pipeline'),\n isDefault: false,\n }]\n : [],\n [currentPipelineName, data?.deal.pipelineId, t],\n )\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.deals.detail.loading', 'Loading deal\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.deals.detail.error.notFound', 'Deal not found.')}\n backHref=\"/backend/customers/deals\"\n backLabel={t('customers.deals.detail.actions.backToList', 'Back to deals')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.deals.detail.error.load', 'Failed to load deal.')}\n action={\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/backend/customers/deals\">\n {t('customers.deals.detail.actions.backToList', 'Back to deals')}\n </Link>\n </Button>\n }\n />\n </PageBody>\n </Page>\n )\n }\n\n const amountLabel = formatCurrency(data.deal.valueAmount, data.deal.valueCurrency)\n const dealName = data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')\n\n const zone1Content = (\n <div ref={formWrapperRef}>\n <DealForm\n mode=\"edit\"\n embedded\n trackDirtyWhenEmbedded\n hideFooterActions\n singleColumnGroups\n showAssociationsGroup={false}\n showVersionHistory={false}\n showCancelAction={false}\n injectionSpotId={extensionPoints.hosts.dealForm.spotId}\n optimisticLockUpdatedAt={data.deal.updatedAt}\n onDirtyChange={setIsDirty}\n initialPipelineOptions={formPipelineOptions}\n initialPipelineStageOptions={data.pipelineStages}\n initialOwnerOption={data.owner ? { id: data.owner.id, name: data.owner.name, email: data.owner.email } : null}\n collapsibleGroups={{ pageType: 'deal-detail-v3', chevronPosition: 'right' }}\n sortableGroups={{ pageType: 'deal-detail-v3' }}\n initialValues={{\n ...data.deal,\n valueAmount:\n typeof data.deal.valueAmount === 'string' && data.deal.valueAmount.trim().length\n ? Number(data.deal.valueAmount)\n : null,\n personIds: data.linkedPersonIds,\n companyIds: data.linkedCompanyIds,\n customFields: data.customFields,\n ...Object.fromEntries(Object.entries(data.customFields ?? {}).map(([key, value]) => [`cf_${key}`, value])),\n }}\n onSubmit={handleFormSubmit}\n onCancel={() => { void loadData() }}\n onDelete={handleDelete}\n />\n </div>\n )\n\n const zone2Content = (\n <div className=\"rounded-[10px] border border-border bg-card px-5 py-5\">\n {(() => {\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n\n if (activeTab === 'activities') {\n const activityEntitySelection = activityEntities.length > 1 ? (\n <div className=\"rounded-[10px] border border-border bg-muted/20 px-5 py-5\">\n <label htmlFor=\"deal-activity-entity\" className=\"text-sm font-semibold text-foreground\">\n {t('customers.deals.detail.activities.selectEntityLabel', 'Choose customer record')}\n </label>\n <div className=\"mt-1 text-sm text-muted-foreground\">\n {t(\n 'customers.deals.detail.activities.selectEntityDescription',\n 'Pick the person or company that should own new deal activities and follow-ups.',\n )}\n </div>\n <select\n id=\"deal-activity-entity\"\n aria-label={t('customers.deals.detail.activities.selectEntityLabel', 'Choose customer record')}\n className=\"mt-4 h-9 w-full rounded border border-muted-foreground/40 bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n value={selectedActivityEntityId ?? ''}\n onChange={(event) => setSelectedActivityEntityId(event.target.value || null)}\n >\n <option value=\"\">\n {t('customers.deals.detail.activities.selectEntityPlaceholder', 'Select a person or company')}\n </option>\n {activityEntities.map((entry) => (\n <option key={entry.id} value={entry.id}>\n {entry.label}\n </option>\n ))}\n </select>\n </div>\n ) : null\n\n return (\n <div className=\"space-y-4\">\n {activityEntities.length > 1 ? activityEntitySelection : null}\n {activityEntities.length === 0 ? (\n <div className=\"rounded-[10px] border border-border bg-muted/20 px-5 py-5\">\n <div className=\"text-sm font-semibold text-foreground\">\n {t('customers.deals.detail.activities.linkEntityTitle', 'Link a person or company first')}\n </div>\n <div className=\"mt-1 text-sm text-muted-foreground\">\n {t('customers.deals.detail.activities.linkEntityDescription', 'Activities on a deal still need a customer record for timeline ownership.')}\n </div>\n <div className=\"mt-4 flex gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => handleTabChange('people')}>\n {t('customers.deals.detail.tabs.people', 'People')}\n </Button>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => handleTabChange('companies')}>\n {t('customers.deals.detail.tabs.companies', 'Companies')}\n </Button>\n </div>\n </div>\n ) : selectedActivityEntity ? (\n <InlineActivityComposer\n entityType={selectedActivityEntity.kind}\n entityId={selectedActivityEntity.id}\n dealId={data.deal.id}\n onActivityCreated={() => { void handleActivityCreated() }}\n runGuardedMutation={runMutationWithContext}\n onScheduleRequested={openSchedule}\n />\n ) : (\n <EmptyState\n size=\"sm\"\n icon={<UserSearch className=\"h-8 w-8\" aria-hidden=\"true\" />}\n title={t('customers.deals.detail.activities.selectEntityRequiredTitle', 'Choose a person or company to continue')}\n description={t(\n 'customers.deals.detail.activities.selectEntityRequiredDescription',\n 'Select the customer record that should receive new deal activities before logging or scheduling anything.',\n )}\n />\n )}\n <PlannedActivitiesSection\n activities={plannedActivities}\n onComplete={(interactionId) => { void handleMarkDone(interactionId) }}\n onSchedule={selectedActivityEntity ? openSchedule : undefined}\n onEdit={handleEditActivity}\n onCancel={(interactionId) => { void handleCancelActivity(interactionId) }}\n />\n {selectedActivityEntity ? (\n <ActivitiesSection\n entityId={selectedActivityEntity.id}\n entityName={selectedActivityEntity.label}\n dealId={data.deal.id}\n dealOptions={dealOptions}\n entityOptions={entityOptions}\n defaultEntityId={selectedActivityEntity.id}\n addActionLabel={t('customers.deals.detail.activitiesAdd', 'Log activity')}\n emptyState={{\n title: t('customers.deals.detail.activitiesEmptyTitle', 'No activities yet'),\n actionLabel: t('customers.deals.detail.activitiesEmptyAction', 'Log activity'),\n }}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={() => { void handleActivityCreated() }}\n refreshKey={activityRefreshKey}\n onEditActivity={handleEditActivity}\n />\n ) : null}\n </div>\n )\n }\n\n if (activeTab === 'people') {\n return (\n <DealPeopleSection\n dealId={data.deal.id}\n dealName={dealName}\n selectedIds={peopleEditorIds}\n onSaveSelection={(next) => handlePeopleAssociationsChange(next)}\n addActionLabel={t('customers.deals.detail.peopleAdd', 'Add person')}\n disabled={peopleSaving || isSaving}\n emptyLabel={t('customers.deals.detail.peopleEmpty', 'No people linked to this deal yet.')}\n emptyState={{\n title: t('customers.deals.detail.peopleEmptyTitle', 'Link the people involved'),\n actionLabel: t('customers.deals.detail.peopleEmptyAction', 'Add person'),\n }}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n\n if (activeTab === 'companies') {\n return (\n <DealLinkedEntitiesTab\n entityLabel={t('customers.deals.detail.tabs.companySingular', 'Company')}\n entityLabelPlural={t('customers.deals.detail.tabs.companies', 'Companies')}\n manageLabel={t('customers.deals.detail.companiesEditorTitle', 'Manage linked companies')}\n searchPlaceholder={t('customers.deals.detail.companiesSearch', 'Search linked companies\u2026')}\n linkedItems={data.companies}\n linkedCount={data.counts.companies}\n selectedIds={companiesEditorIds}\n disabled={companiesSaving || isSaving}\n savePending={companiesSaving}\n hrefBuilder={(companyId) => `/backend/customers/companies-v2/${encodeURIComponent(companyId)}`}\n onSaveSelection={(next) => handleCompaniesAssociationsChange(next)}\n loadLinkedPage={loadLinkedCompaniesPage}\n searchEntities={searchCompaniesPage}\n fetchEntitiesByIds={fetchCompaniesByIds}\n icon={<Building2 className=\"size-4\" />}\n />\n )\n }\n\n if (activeTab === 'notes') {\n return (\n <NotesSection\n entityId={null}\n dealId={data.deal.id}\n dealOptions={dealOptions}\n entityOptions={entityOptions}\n emptyLabel={t('customers.deals.detail.notesEmpty', 'No notes yet.')}\n viewerUserId={data.viewer?.userId ?? null}\n viewerName={data.viewer?.name ?? null}\n viewerEmail={data.viewer?.email ?? null}\n addActionLabel={t('customers.deals.detail.notesAdd', 'Add note')}\n emptyState={{\n title: t('customers.deals.detail.notesEmptyTitle', 'Keep everyone in the loop'),\n actionLabel: t('customers.deals.detail.notesEmptyAction', 'Add a note'),\n }}\n translator={detailTranslator}\n dataAdapter={notesAdapter}\n renderIcon={renderDictionaryIcon}\n renderColor={renderDictionaryColor}\n iconSuggestions={ICON_SUGGESTIONS}\n readMarkdownPreference={readMarkdownPreferenceCookie}\n writeMarkdownPreference={writeMarkdownPreferenceCookie}\n />\n )\n }\n\n if (activeTab === 'files') {\n return (\n <AttachmentsSection\n entityId={E.customers.customer_deal}\n recordId={data.deal.id}\n title={t('customers.deals.detail.tabs.files', 'Files')}\n description={t('customers.deals.detail.files.subtitle', 'Upload and manage files linked to this deal.')}\n />\n )\n }\n\n if (activeTab === 'changelog') {\n return <ChangelogTab entityId={data.deal.id} entityType=\"deal\" />\n }\n\n return null\n })()}\n </div>\n )\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <InjectionSpot spotId={extensionPoints.hosts.dealHeader.spotId} context={injectionContext} data={data} />\n\n <DealDetailHeader\n deal={data.deal}\n owner={data.owner}\n people={data.people}\n companies={data.companies}\n pipelineName={currentPipelineName}\n stageOptions={data.pipelineStages}\n currentStageId={data.deal.pipelineStageId}\n onStageChange={handleStageChange}\n isStageSaving={isStageSaving}\n onSave={handleHeaderSave}\n onDelete={handleDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n />\n\n <InjectionSpot spotId={extensionPoints.hosts.dealStatusBadges.spotId} context={injectionContext} data={data} onDataChange={setData} />\n\n <PipelineStepper\n stages={data.pipelineStages}\n transitions={data.stageTransitions}\n currentStageId={data.deal.pipelineStageId}\n pipelineName={currentPipelineName}\n closureOutcome={data.deal.closureOutcome}\n footer={data.deal.closureOutcome ? null : (\n <DealClosureActionBar\n embedded\n closureOutcome={data.deal.closureOutcome}\n onWon={() => { void handleWon() }}\n onLost={openLostDialog}\n />\n )}\n />\n\n <DealDetailTabs\n activeTab={activeTab}\n onTabChange={handleTabChange}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n peopleCount={data.counts.people}\n companiesCount={data.counts.companies}\n >\n <CollapsibleZoneLayout\n pageType=\"deal-detail-v3\"\n entityName={dealName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1DefaultWidth=\"540px\"\n zone1={zone1Content}\n zone2={zone2Content}\n />\n </DealDetailTabs>\n\n <InjectionSpot spotId={extensionPoints.hosts.dealFooter.spotId} context={injectionContext} data={data} />\n </div>\n\n {ConfirmDialogElement}\n\n {selectedActivityEntity ? (\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={closeSchedule}\n entityId={selectedActivityEntity.id}\n dealId={data.deal.id}\n entityType={selectedActivityEntity.kind}\n entityName={selectedActivityEntity.label}\n companyName={selectedActivityEntity.kind === 'company' ? selectedActivityEntity.label : data.companies[0]?.label ?? null}\n onActivityCreated={() => { void handleActivityCreated() }}\n editData={scheduleEditData}\n />\n ) : null}\n\n <ConfirmDealLostDialog\n open={lostDialogOpen}\n onClose={closeLostDialog}\n dealTitle={data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')}\n dealValue={amountLabel}\n companyName={data.companies[0]?.label ?? null}\n onConfirm={handleLostConfirm}\n />\n\n <DealWonPopup\n open={wonPopupOpen}\n onClose={closeWonPopup}\n dealTitle={data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')}\n stats={wonStats}\n onViewDashboard={handleViewDashboard}\n onBackToPipeline={handleBackToPipeline}\n />\n\n <DealLostSummaryDialog\n open={lostPopupOpen}\n onClose={closeLostPopup}\n dealTitle={data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')}\n lossNotes={data.deal.lossNotes}\n stats={lostStats}\n onBackToPipeline={handleBackToPipeline}\n onScheduleFollowUp={selectedActivityEntity ? handleScheduleLostFollowUp : undefined}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/customers/extension-points'\nimport Link from 'next/link'\nimport { Building2, FileText, Hash, UserSearch } from 'lucide-react'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { useRouter, useSearchParams, usePathname } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, NotesSection, RecordNotFoundState } from '@open-mercato/ui/backend/detail'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { CustomerDetailSidebar } from '../../../../components/detail/CustomerDetailSidebar'\nimport { buildRecordInjectionContext, useSetCurrentRecordInjectionContext } from '@open-mercato/ui/backend/injection/recordContext'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { CollapsibleZoneLayout, type ZoneSectionDescriptor } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { E } from '#generated/entities.ids.generated'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { DealClosureActionBar } from '../../../../components/detail/DealClosureActionBar'\nimport { DealDetailHeader } from '../../../../components/detail/DealDetailHeader'\nimport { DealDetailTabs, resolveLegacyTab, type DealTabId } from '../../../../components/detail/DealDetailTabs'\nimport { DealForm, useDealAssociationLookups } from '../../../../components/detail/DealForm'\nimport { DealLinkedEntitiesTab } from '../../../../components/detail/DealLinkedEntitiesTab'\nimport { DealPeopleSection } from '../../../../components/detail/DealPeopleSection'\nimport { ConfirmDealLostDialog } from '../../../../components/detail/ConfirmDealLostDialog'\nimport { DealLostSummaryDialog } from '../../../../components/detail/DealLostSummaryDialog'\nimport { DealWonPopup } from '../../../../components/detail/DealWonPopup'\nimport { InlineActivityComposer } from '../../../../components/detail/InlineActivityComposer'\nimport { PipelineStepper } from '../../../../components/detail/PipelineStepper'\nimport { PlannedActivitiesSection } from '../../../../components/detail/PlannedActivitiesSection'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { createCustomerNotesAdapter } from '../../../../components/detail/notesAdapter'\nimport type { InteractionSummary } from '../../../../components/detail/types'\nimport { readMarkdownPreferenceCookie, writeMarkdownPreferenceCookie } from '../../../../lib/markdownPreference'\nimport { ICON_SUGGESTIONS } from '../../../../lib/dictionaries'\nimport { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\n\nimport { formatCurrency, startOfNextQuarter } from './hooks/formatters'\nimport type { DealDetailPayload } from './hooks/types'\nimport { useDealActivities } from './hooks/useDealActivities'\nimport { useDealAssociations } from './hooks/useDealAssociations'\nimport { useDealClosure } from './hooks/useDealClosure'\nimport { useDealData } from './hooks/useDealData'\nimport { useDealFormHandlers } from './hooks/useDealFormHandlers'\nimport { useDealInjectedTabs } from './hooks/useDealInjectedTabs'\nimport { useDealMutationContext } from './hooks/useDealMutationContext'\nimport { useDealPipeline } from './hooks/useDealPipeline'\nimport { useScheduleDialog } from './hooks/useScheduleDialog'\n\nexport default function DealDetailPage({ params }: { params?: { id?: string } }) {\n const id = params?.id ?? ''\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const pathname = usePathname()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n const zoneSections = React.useMemo<ZoneSectionDescriptor[]>(() => [\n { id: 'details', icon: FileText, label: t('customers.people.detail.deals.form.details', 'Deal details') },\n { id: 'custom', icon: Hash, label: t('customers.people.detail.deals.form.customFields', 'Custom fields') },\n ], [t])\n\n const { data, setData, isLoading, error, isNotFound, loadData } = useDealData(id)\n const [isDirty, setIsDirty] = React.useState(false)\n const {\n scheduleDialogOpen,\n scheduleEditData,\n openSchedule,\n openEdit: openScheduleEdit,\n closeSchedule,\n } = useScheduleDialog()\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n\n const currentDealId = data?.deal.id ?? id\n const { injectionContext, runMutationWithContext } = useDealMutationContext({\n currentDealId,\n fallbackId: id,\n data,\n })\n\n // Publish page-load record context with explicit `updatedAt`/`data` to the\n // AppShell-owned `backend:record:current` mount. The deal path is already in the\n // widget's allowlist (presence works) but supplied no version/record payload \u2014\n // this gives the merge dialog its action-log base and field-diff source.\n useSetCurrentRecordInjectionContext(\n buildRecordInjectionContext({\n resourceKind: 'customers.deal',\n resourceId: data?.deal.id ?? null,\n updatedAt: data?.deal.updatedAt ?? null,\n data: data as Record<string, unknown> | null,\n path: pathname,\n }),\n )\n\n const notesAdapter = React.useMemo(\n () => createCustomerNotesAdapter(detailTranslator, { runMutation: runMutationWithContext }),\n [detailTranslator, runMutationWithContext],\n )\n\n const { injectedTabs, injectedTabMap, loading: injectedTabsLoading } = useDealInjectedTabs({\n injectionContext,\n data,\n setData,\n })\n\n const injectedTabIds = React.useMemo(() => injectedTabs.map((tab) => tab.id), [injectedTabs])\n const initialTab = React.useMemo(\n () => resolveLegacyTab(searchParams?.get('tab'), injectedTabIds),\n [injectedTabIds, searchParams],\n )\n const [activeTab, setActiveTab] = React.useState<DealTabId>(initialTab)\n\n React.useEffect(() => {\n setActiveTab(initialTab)\n }, [initialTab])\n\n const { searchCompaniesPage, fetchCompaniesByIds } = useDealAssociationLookups({\n excludeLinkedDealId: data?.deal.id ?? null,\n })\n\n const {\n plannedActivities,\n activityRefreshKey,\n loadPlannedActivities,\n handleActivityCreated,\n handleMarkDone,\n handleCancelActivity,\n } = useDealActivities({ dealId: id, runMutationWithContext })\n\n React.useEffect(() => {\n void Promise.all([loadData({ cache: true }), loadPlannedActivities({ cache: true })])\n }, [loadData, loadPlannedActivities])\n\n const activityEntities = React.useMemo(\n () => (data\n ? [...data.people, ...data.companies].map((entry) => ({\n id: entry.id,\n label: entry.subtitle ? `${entry.label} \u00B7 ${entry.subtitle}` : entry.label,\n kind: entry.kind,\n isPrimary: entry.isPrimary === true,\n }))\n : []),\n [data],\n )\n const [selectedActivityEntityId, setSelectedActivityEntityId] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n setSelectedActivityEntityId((current) => {\n if (activityEntities.length === 1) return activityEntities[0].id\n if (current && activityEntities.some((entry) => entry.id === current)) return current\n const primary = activityEntities.find((entry) => entry.isPrimary)\n return (primary ?? activityEntities[0])?.id ?? null\n })\n }, [activityEntities])\n\n const selectedActivityEntity = React.useMemo(\n () => activityEntities.find((entry) => entry.id === selectedActivityEntityId) ?? null,\n [activityEntities, selectedActivityEntityId],\n )\n\n const dealOptions = React.useMemo(\n () => data ? [{ id: data.deal.id, label: data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal') }] : [],\n [data, t],\n )\n\n const entityOptions = React.useMemo(\n () => activityEntities.map(({ id, label }) => ({ id, label })),\n [activityEntities],\n )\n\n const confirmDiscardIfDirty = React.useCallback(async () => {\n if (!isDirty) return true\n return confirm({\n title: t('customers.deals.detail.unsavedTitle', 'Discard unsaved changes?'),\n description: t(\n 'customers.deals.detail.unsavedDescription',\n 'You have unsaved edits in this deal. Save them first or continue to discard them.',\n ),\n confirmText: t('customers.deals.detail.unsavedConfirm', 'Discard changes'),\n cancelText: t('customers.deals.detail.unsavedCancel', 'Keep editing'),\n variant: 'destructive',\n })\n }, [confirm, isDirty, t])\n\n const {\n peopleEditorIds,\n companiesEditorIds,\n peopleSaving,\n companiesSaving,\n handlePeopleAssociationsChange,\n handleCompaniesAssociationsChange,\n loadLinkedCompaniesPage,\n } = useDealAssociations({\n currentDealId,\n data,\n setData,\n runMutationWithContext,\n onRefresh: () => loadData(),\n })\n\n const { isStageSaving, handleStageChange } = useDealPipeline({\n currentDealId,\n data,\n runMutationWithContext,\n confirmDiscardIfDirty,\n onStageChanged: loadData,\n })\n\n const {\n lostDialogOpen,\n wonPopupOpen,\n lostPopupOpen,\n wonStats,\n lostStats,\n openLostDialog,\n closeLostDialog,\n closeWonPopup,\n closeLostPopup,\n handleWon,\n handleLostConfirm,\n } = useDealClosure({\n currentDealId,\n dealUpdatedAt: data?.deal.updatedAt ?? null,\n runMutationWithContext,\n confirmDiscardIfDirty,\n onClosed: loadData,\n })\n\n const handleTabChange = React.useCallback(async (tab: DealTabId) => {\n if (!(await confirmDiscardIfDirty())) return\n setActiveTab(tab)\n const nextParams = new URLSearchParams(searchParams?.toString() ?? '')\n nextParams.set('tab', tab)\n router.replace(`/backend/customers/deals/${encodeURIComponent(id)}?${nextParams.toString()}`, { scroll: false })\n }, [confirmDiscardIfDirty, id, router, searchParams])\n\n const { isSaving, handleFormSubmit, handleDelete, handleHeaderSave } = useDealFormHandlers({\n data,\n currentDealId,\n loadData,\n runMutationWithContext,\n formWrapperRef,\n confirm,\n })\n\n const handleEditActivity = React.useCallback((activity: InteractionSummary) => {\n if (activity.entityId && activityEntities.some((entry) => entry.id === activity.entityId)) {\n setSelectedActivityEntityId(activity.entityId)\n }\n // Forward `customValues` so per-type chip state (callPhoneNumber,\n // callDirection, taskPriority) round-trips on edit (#1808 phone persistence).\n // Forward `occurredAt` so historical activity edits prefill from the\n // original moment instead of \"today\" (#1807 prefill).\n const rawActivity = activity as unknown as Record<string, unknown>\n openScheduleEdit({\n id: activity.id,\n updatedAt: typeof rawActivity.updatedAt === 'string' ? rawActivity.updatedAt as string : typeof rawActivity.updated_at === 'string' ? rawActivity.updated_at as string : null,\n // Pin the edit payload to the activity's own entity \u2014 the deal page can\n // show activities from more than one linked entity, and the dialog has\n // no entity picker, so it must never silently re-link on save (#6050).\n entityId: activity.entityId ?? selectedActivityEntityId ?? null,\n interactionType: activity.interactionType,\n title: activity.title ?? null,\n body: activity.body ?? null,\n scheduledAt: activity.scheduledAt ?? null,\n occurredAt: activity.occurredAt ?? null,\n durationMinutes: activity.duration ?? null,\n priority: activity.priority ?? null,\n location: activity.location ?? null,\n allDay: activity.allDay ?? null,\n recurrenceRule: activity.recurrenceRule ?? null,\n recurrenceEnd: activity.recurrenceEnd ?? null,\n participants: activity.participants ?? null,\n reminderMinutes: activity.reminderMinutes ?? null,\n visibility: activity.visibility ?? null,\n linkedEntities: activity.linkedEntities ?? null,\n guestPermissions: activity.guestPermissions ?? null,\n ...(rawActivity.customValues && typeof rawActivity.customValues === 'object'\n ? { customValues: rawActivity.customValues as Record<string, unknown> }\n : {}),\n ...(typeof rawActivity.phoneNumber === 'string'\n ? { phoneNumber: rawActivity.phoneNumber as string }\n : {}),\n } as ScheduleActivityEditData & { customValues?: Record<string, unknown> | null; phoneNumber?: string | null })\n }, [activityEntities, openScheduleEdit, selectedActivityEntityId])\n\n const handleViewDashboard = React.useCallback(() => {\n closeWonPopup()\n router.push('/backend')\n }, [closeWonPopup, router])\n\n const handleBackToPipeline = React.useCallback(() => {\n closeWonPopup()\n closeLostPopup()\n router.push('/backend/customers/deals/pipeline')\n }, [closeLostPopup, closeWonPopup, router])\n\n const handleScheduleLostFollowUp = React.useCallback(() => {\n if (!data || !selectedActivityEntity) return\n const nextQuarterDate = startOfNextQuarter(new Date())\n closeLostPopup()\n openScheduleEdit({\n id: '',\n interactionType: 'task',\n title: data.deal.title\n ? t('customers.deals.detail.lost.followUpTitle', 'Revisit {{title}}', { title: data.deal.title })\n : t('customers.deals.detail.lost.followUpFallbackTitle', 'Revisit closed deal'),\n body: data.deal.lossNotes ?? null,\n scheduledAt: nextQuarterDate.toISOString(),\n durationMinutes: 30,\n location: null,\n allDay: false,\n recurrenceRule: null,\n recurrenceEnd: null,\n participants: null,\n reminderMinutes: 1440,\n visibility: 'team',\n linkedEntities: [\n {\n id: data.deal.id,\n type: 'deal',\n label: data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal'),\n },\n ],\n })\n }, [closeLostPopup, data, openScheduleEdit, selectedActivityEntity, t])\n\n const currentPipelineName = data\n ? data.pipelineName ?? wonStats?.pipelineName ?? lostStats?.pipelineName ?? null\n : wonStats?.pipelineName ?? lostStats?.pipelineName ?? null\n const formPipelineOptions = React.useMemo(\n () => data?.deal.pipelineId\n ? [{\n id: data.deal.pipelineId,\n name: currentPipelineName ?? t('customers.deals.detail.pipeline.defaultName', 'Current pipeline'),\n isDefault: false,\n }]\n : [],\n [currentPipelineName, data?.deal.pipelineId, t],\n )\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.deals.detail.loading', 'Loading deal\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.deals.detail.error.notFound', 'Deal not found.')}\n backHref=\"/backend/customers/deals\"\n backLabel={t('customers.deals.detail.actions.backToList', 'Back to deals')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.deals.detail.error.load', 'Failed to load deal.')}\n action={\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/backend/customers/deals\">\n {t('customers.deals.detail.actions.backToList', 'Back to deals')}\n </Link>\n </Button>\n }\n />\n </PageBody>\n </Page>\n )\n }\n\n const amountLabel = formatCurrency(data.deal.valueAmount, data.deal.valueCurrency)\n const dealName = data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')\n\n const zone1Content = (\n <div ref={formWrapperRef}>\n <DealForm\n mode=\"edit\"\n embedded\n trackDirtyWhenEmbedded\n hideFooterActions\n singleColumnGroups\n showAssociationsGroup={false}\n showVersionHistory={false}\n showCancelAction={false}\n injectionSpotId={extensionPoints.hosts.dealForm.spotId}\n optimisticLockUpdatedAt={data.deal.updatedAt}\n onDirtyChange={setIsDirty}\n initialPipelineOptions={formPipelineOptions}\n initialPipelineStageOptions={data.pipelineStages}\n initialOwnerOption={data.owner ? { id: data.owner.id, name: data.owner.name, email: data.owner.email } : null}\n collapsibleGroups={{ pageType: 'deal-detail-v3', chevronPosition: 'right' }}\n sortableGroups={{ pageType: 'deal-detail-v3' }}\n initialValues={{\n ...data.deal,\n valueAmount:\n typeof data.deal.valueAmount === 'string' && data.deal.valueAmount.trim().length\n ? Number(data.deal.valueAmount)\n : null,\n personIds: data.linkedPersonIds,\n companyIds: data.linkedCompanyIds,\n customFields: data.customFields,\n ...Object.fromEntries(Object.entries(data.customFields ?? {}).map(([key, value]) => [`cf_${key}`, value])),\n }}\n onSubmit={handleFormSubmit}\n onCancel={() => { void loadData() }}\n onDelete={handleDelete}\n />\n </div>\n )\n\n const zone2Content = (\n <div className=\"rounded-[10px] border border-border bg-card px-5 py-5\">\n {(() => {\n\n if (activeTab === 'activities') {\n const activityEntitySelection = activityEntities.length > 1 ? (\n <div className=\"rounded-[10px] border border-border bg-muted/20 px-5 py-5\">\n <label htmlFor=\"deal-activity-entity\" className=\"text-sm font-semibold text-foreground\">\n {t('customers.deals.detail.activities.selectEntityLabel', 'Choose customer record')}\n </label>\n <div className=\"mt-1 text-sm text-muted-foreground\">\n {t(\n 'customers.deals.detail.activities.selectEntityDescription',\n 'Pick the person or company that should own new deal activities and follow-ups.',\n )}\n </div>\n <select\n id=\"deal-activity-entity\"\n aria-label={t('customers.deals.detail.activities.selectEntityLabel', 'Choose customer record')}\n className=\"mt-4 h-9 w-full rounded border border-muted-foreground/40 bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n value={selectedActivityEntityId ?? ''}\n onChange={(event) => setSelectedActivityEntityId(event.target.value || null)}\n >\n <option value=\"\">\n {t('customers.deals.detail.activities.selectEntityPlaceholder', 'Select a person or company')}\n </option>\n {activityEntities.map((entry) => (\n <option key={entry.id} value={entry.id}>\n {entry.label}\n </option>\n ))}\n </select>\n </div>\n ) : null\n\n return (\n <div className=\"space-y-4\">\n {activityEntities.length > 1 ? activityEntitySelection : null}\n {activityEntities.length === 0 ? (\n <div className=\"rounded-[10px] border border-border bg-muted/20 px-5 py-5\">\n <div className=\"text-sm font-semibold text-foreground\">\n {t('customers.deals.detail.activities.linkEntityTitle', 'Link a person or company first')}\n </div>\n <div className=\"mt-1 text-sm text-muted-foreground\">\n {t('customers.deals.detail.activities.linkEntityDescription', 'Activities on a deal still need a customer record for timeline ownership.')}\n </div>\n <div className=\"mt-4 flex gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => handleTabChange('people')}>\n {t('customers.deals.detail.tabs.people', 'People')}\n </Button>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => handleTabChange('companies')}>\n {t('customers.deals.detail.tabs.companies', 'Companies')}\n </Button>\n </div>\n </div>\n ) : selectedActivityEntity ? (\n <InlineActivityComposer\n entityType={selectedActivityEntity.kind}\n entityId={selectedActivityEntity.id}\n dealId={data.deal.id}\n onActivityCreated={() => { void handleActivityCreated() }}\n runGuardedMutation={runMutationWithContext}\n onScheduleRequested={openSchedule}\n />\n ) : (\n <EmptyState\n size=\"sm\"\n icon={<UserSearch className=\"h-8 w-8\" aria-hidden=\"true\" />}\n title={t('customers.deals.detail.activities.selectEntityRequiredTitle', 'Choose a person or company to continue')}\n description={t(\n 'customers.deals.detail.activities.selectEntityRequiredDescription',\n 'Select the customer record that should receive new deal activities before logging or scheduling anything.',\n )}\n />\n )}\n <PlannedActivitiesSection\n activities={plannedActivities}\n onComplete={(interactionId) => { void handleMarkDone(interactionId) }}\n onSchedule={selectedActivityEntity ? openSchedule : undefined}\n onEdit={handleEditActivity}\n onCancel={(interactionId) => { void handleCancelActivity(interactionId) }}\n />\n {selectedActivityEntity ? (\n <ActivitiesSection\n entityId={selectedActivityEntity.id}\n entityName={selectedActivityEntity.label}\n dealId={data.deal.id}\n dealOptions={dealOptions}\n entityOptions={entityOptions}\n defaultEntityId={selectedActivityEntity.id}\n addActionLabel={t('customers.deals.detail.activitiesAdd', 'Log activity')}\n emptyState={{\n title: t('customers.deals.detail.activitiesEmptyTitle', 'No activities yet'),\n actionLabel: t('customers.deals.detail.activitiesEmptyAction', 'Log activity'),\n }}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={() => { void handleActivityCreated() }}\n refreshKey={activityRefreshKey}\n onEditActivity={handleEditActivity}\n />\n ) : null}\n </div>\n )\n }\n\n if (activeTab === 'people') {\n return (\n <DealPeopleSection\n dealId={data.deal.id}\n dealName={dealName}\n selectedIds={peopleEditorIds}\n onSaveSelection={(next) => handlePeopleAssociationsChange(next)}\n addActionLabel={t('customers.deals.detail.peopleAdd', 'Add person')}\n disabled={peopleSaving || isSaving}\n emptyLabel={t('customers.deals.detail.peopleEmpty', 'No people linked to this deal yet.')}\n emptyState={{\n title: t('customers.deals.detail.peopleEmptyTitle', 'Link the people involved'),\n actionLabel: t('customers.deals.detail.peopleEmptyAction', 'Add person'),\n }}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n\n if (activeTab === 'companies') {\n return (\n <DealLinkedEntitiesTab\n entityLabel={t('customers.deals.detail.tabs.companySingular', 'Company')}\n entityLabelPlural={t('customers.deals.detail.tabs.companies', 'Companies')}\n manageLabel={t('customers.deals.detail.companiesEditorTitle', 'Manage linked companies')}\n searchPlaceholder={t('customers.deals.detail.companiesSearch', 'Search linked companies\u2026')}\n linkedItems={data.companies}\n linkedCount={data.counts.companies}\n selectedIds={companiesEditorIds}\n disabled={companiesSaving || isSaving}\n savePending={companiesSaving}\n hrefBuilder={(companyId) => `/backend/customers/companies-v2/${encodeURIComponent(companyId)}`}\n onSaveSelection={(next) => handleCompaniesAssociationsChange(next)}\n loadLinkedPage={loadLinkedCompaniesPage}\n searchEntities={searchCompaniesPage}\n fetchEntitiesByIds={fetchCompaniesByIds}\n icon={<Building2 className=\"size-4\" />}\n />\n )\n }\n\n if (activeTab === 'notes') {\n return (\n <NotesSection\n entityId={null}\n dealId={data.deal.id}\n dealOptions={dealOptions}\n entityOptions={entityOptions}\n emptyLabel={t('customers.deals.detail.notesEmpty', 'No notes yet.')}\n viewerUserId={data.viewer?.userId ?? null}\n viewerName={data.viewer?.name ?? null}\n viewerEmail={data.viewer?.email ?? null}\n addActionLabel={t('customers.deals.detail.notesAdd', 'Add note')}\n emptyState={{\n title: t('customers.deals.detail.notesEmptyTitle', 'Keep everyone in the loop'),\n actionLabel: t('customers.deals.detail.notesEmptyAction', 'Add a note'),\n }}\n translator={detailTranslator}\n dataAdapter={notesAdapter}\n renderIcon={renderDictionaryIcon}\n renderColor={renderDictionaryColor}\n iconSuggestions={ICON_SUGGESTIONS}\n readMarkdownPreference={readMarkdownPreferenceCookie}\n writeMarkdownPreference={writeMarkdownPreferenceCookie}\n />\n )\n }\n\n if (activeTab === 'files') {\n return (\n <AttachmentsSection\n entityId={E.customers.customer_deal}\n recordId={data.deal.id}\n title={t('customers.deals.detail.tabs.files', 'Files')}\n description={t('customers.deals.detail.files.subtitle', 'Upload and manage files linked to this deal.')}\n />\n )\n }\n\n if (activeTab === 'changelog') {\n return <ChangelogTab entityId={data.deal.id} entityType=\"deal\" />\n }\n\n return null\n })()}\n {injectedTabMap.get(activeTab)?.()}\n </div>\n )\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <InjectionSpot spotId={extensionPoints.hosts.dealHeader.spotId} context={injectionContext} data={data} />\n\n <DealDetailHeader\n actions={<InjectionSpot spotId={extensionPoints.hosts.dealHeaderActions.spotId} context={{ ...injectionContext, isDirty, isSaving }} data={data} disabled={isSaving} />}\n deal={data.deal}\n owner={data.owner}\n people={data.people}\n companies={data.companies}\n pipelineName={currentPipelineName}\n stageOptions={data.pipelineStages}\n currentStageId={data.deal.pipelineStageId}\n onStageChange={handleStageChange}\n isStageSaving={isStageSaving}\n onSave={handleHeaderSave}\n onDelete={handleDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n />\n\n <InjectionSpot spotId={extensionPoints.hosts.dealStatusBadges.spotId} context={injectionContext} data={data} onDataChange={setData} />\n\n <PipelineStepper\n stages={data.pipelineStages}\n transitions={data.stageTransitions}\n currentStageId={data.deal.pipelineStageId}\n pipelineName={currentPipelineName}\n closureOutcome={data.deal.closureOutcome}\n footer={data.deal.closureOutcome ? null : (\n <DealClosureActionBar\n embedded\n closureOutcome={data.deal.closureOutcome}\n onWon={() => { void handleWon() }}\n onLost={openLostDialog}\n />\n )}\n />\n\n <CustomerDetailSidebar spotId={extensionPoints.hosts.dealSidebar.spotId} context={injectionContext} data={data} onDataChange={setData} disabled={isSaving}>\n <DealDetailTabs\n isLoadingInjectedTabs={injectedTabsLoading}\n activeTab={activeTab}\n onTabChange={handleTabChange}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n peopleCount={data.counts.people}\n companiesCount={data.counts.companies}\n >\n <CollapsibleZoneLayout\n pageType=\"deal-detail-v3\"\n entityName={dealName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1DefaultWidth=\"540px\"\n zone1={zone1Content}\n zone2={zone2Content}\n />\n </DealDetailTabs>\n </CustomerDetailSidebar>\n\n <InjectionSpot spotId={extensionPoints.hosts.dealFooter.spotId} context={injectionContext} data={data} />\n </div>\n\n {ConfirmDialogElement}\n\n {selectedActivityEntity ? (\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={closeSchedule}\n entityId={selectedActivityEntity.id}\n dealId={data.deal.id}\n entityType={selectedActivityEntity.kind}\n entityName={selectedActivityEntity.label}\n companyName={selectedActivityEntity.kind === 'company' ? selectedActivityEntity.label : data.companies[0]?.label ?? null}\n onActivityCreated={() => { void handleActivityCreated() }}\n editData={scheduleEditData}\n />\n ) : null}\n\n <ConfirmDealLostDialog\n open={lostDialogOpen}\n onClose={closeLostDialog}\n dealTitle={data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')}\n dealValue={amountLabel}\n companyName={data.companies[0]?.label ?? null}\n onConfirm={handleLostConfirm}\n />\n\n <DealWonPopup\n open={wonPopupOpen}\n onClose={closeWonPopup}\n dealTitle={data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')}\n stats={wonStats}\n onViewDashboard={handleViewDashboard}\n onBackToPipeline={handleBackToPipeline}\n />\n\n <DealLostSummaryDialog\n open={lostPopupOpen}\n onClose={closeLostPopup}\n dealTitle={data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')}\n lossNotes={data.deal.lossNotes}\n stats={lostStats}\n onBackToPipeline={handleBackToPipeline}\n onScheduleFollowUp={selectedActivityEntity ? handleScheduleLostFollowUp : undefined}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["id"]
7
7
  }
@@ -2,6 +2,7 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { z } from "zod";
5
+ import { E } from "../../../../../../../generated/entities.ids.generated.js";
5
6
  import {
6
7
  Dialog,
7
8
  DialogContent,
@@ -14,6 +15,7 @@ import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
14
15
  import { ComboboxInput } from "@open-mercato/ui/backend/inputs/ComboboxInput";
15
16
  import { createCrud } from "@open-mercato/ui/backend/utils/crud";
16
17
  import { createCrudFormError } from "@open-mercato/ui/backend/utils/serverErrors";
18
+ import { extensionPoints } from "../../../../../extension-points.js";
17
19
  import { useGuardedMutation } from "@open-mercato/ui/backend/injection/useGuardedMutation";
18
20
  import { flash } from "@open-mercato/ui/backend/FlashMessages";
19
21
  import { useT } from "@open-mercato/shared/lib/i18n/context";
@@ -45,10 +47,7 @@ function QuickDealDialog({
45
47
  React.useEffect(() => {
46
48
  if (open) setFormInstanceKey((current) => current + 1);
47
49
  }, [open]);
48
- const { runMutation, retryLastMutation } = useGuardedMutation({
49
- contextId: QUICK_DEAL_CONTEXT_ID,
50
- blockedMessage: translateWithFallback(t, "ui.forms.flash.saveBlocked", "Save blocked by validation")
51
- });
50
+ const { runMutation, retryLastMutation } = useGuardedMutation({ contextId: QUICK_DEAL_CONTEXT_ID, blockedMessage: translateWithFallback(t, "ui.forms.flash.saveBlocked", "Save blocked by validation") });
52
51
  const titleRequiredMessage = translateWithFallback(
53
52
  t,
54
53
  "customers.deals.kanban.quickDeal.title.required",
@@ -253,31 +252,26 @@ function QuickDealDialog({
253
252
  if (values.description && values.description.trim().length) {
254
253
  payload.description = values.description;
255
254
  }
256
- const operation = () => createCrud("customers/deals", payload, {
257
- errorMessage: translateWithFallback(t, "customers.deals.create.error", "Failed to create deal.")
258
- });
259
- await runMutation({
260
- operation,
261
- context: {
262
- formId: QUICK_DEAL_CONTEXT_ID,
263
- resourceKind: "customers.deal",
264
- retryLastMutation
265
- }
255
+ const { result } = await runMutation({
256
+ operation: () => createCrud("customers/deals", payload, {
257
+ errorMessage: translateWithFallback(t, "customers.deals.create.error", "Failed to create deal.")
258
+ }),
259
+ context: { formId: QUICK_DEAL_CONTEXT_ID, resourceKind: "customers.deal", retryLastMutation },
260
+ mutationPayload: payload
266
261
  });
267
262
  flash(
268
- translateWithFallback(
269
- t,
270
- "customers.deals.kanban.quickDeal.success",
271
- "Deal added to {stage}.",
272
- { stage: context.pipelineStageLabel }
273
- ),
263
+ translateWithFallback(t, "customers.deals.kanban.quickDeal.success", "Deal added to {stage}.", { stage: context.pipelineStageLabel }),
274
264
  "success"
275
265
  );
276
- onCreated();
277
- onClose();
266
+ return { resourceId: result?.id ?? result?.entityId };
278
267
  },
279
- [context, currentUserId, onClose, onCreated, retryLastMutation, runMutation, t, titleRequiredMessage]
268
+ [context, currentUserId, t, titleRequiredMessage, runMutation, retryLastMutation]
280
269
  );
270
+ const handleSubmitSuccess = React.useCallback(() => {
271
+ if (!context) return;
272
+ onCreated();
273
+ onClose();
274
+ }, [context, onCreated, onClose]);
281
275
  if (!context) return null;
282
276
  return /* @__PURE__ */ jsx(
283
277
  Dialog,
@@ -300,13 +294,20 @@ function QuickDealDialog({
300
294
  CrudForm,
301
295
  {
302
296
  embedded: true,
297
+ formId: QUICK_DEAL_CONTEXT_ID,
298
+ entityId: "customers.deal",
299
+ entityIds: [E.customers.customer_deal],
300
+ resourceKind: "customers.deal",
301
+ injectionSpotId: extensionPoints.hosts.dealForm.spotId,
302
+ injectionGroupAliases: { details: "basic" },
303
303
  fields,
304
304
  groups,
305
305
  collapsibleGroups: { pageType: "customers.deals.kanban.quickDeal" },
306
306
  initialValues,
307
307
  schema: formSchema,
308
308
  submitLabel: translateWithFallback(t, "customers.deals.kanban.quickDeal.submit", "Add deal"),
309
- onSubmit: handleSubmit
309
+ onSubmit: handleSubmit,
310
+ onSubmitSuccess: handleSubmitSuccess
310
311
  },
311
312
  `${context.pipelineStageId}:${formInstanceKey}`
312
313
  )
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../../src/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { z } from 'zod'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { Avatar } from '@open-mercato/ui/primitives/avatar'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { ComboboxInput } from '@open-mercato/ui/backend/inputs/ComboboxInput'\nimport { createCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { registerComponent } from '@open-mercato/shared/modules/widgets/component-registry'\n\n// Deal status values written by the kanban flow. These intentionally do NOT include 'closed'\n// because the rest of the app only persists 'lost' for lost deals (see StatusFilterPopover\n// notes). 'in_progress' is kept for backwards compatibility with quick-deals created from\n// the previous version of this dialog. Deals written before 0.7.1 carry the misspelled\n// 'loose'; readers still match it through `lib/dealStatus.ts`, but no writer produces it.\nconst STATUS_OPTIONS = ['open', 'in_progress', 'win', 'lost'] as const\n\n/**\n * Tenant currency option. The page resolves these from the currencies module (see\n * `useCurrencyDictionary`) and passes them in; we no longer hardcode the 4-currency\n * list that previously locked tenants on CZK/SEK/HUF/etc. out of quick-add.\n */\nexport type QuickDealCurrencyOption = {\n code: string\n label?: string\n isBase?: boolean\n}\n\nconst FALLBACK_CURRENCIES: QuickDealCurrencyOption[] = [\n { code: 'USD', isBase: true },\n { code: 'EUR' },\n { code: 'GBP' },\n { code: 'PLN' },\n]\n\nexport type QuickDealContext = {\n pipelineId: string\n pipelineName: string\n pipelineStageId: string\n pipelineStageLabel: string\n}\n\nexport type QuickDealCompanyOption = {\n id: string\n label: string\n}\n\n/**\n * Registered component id for the kanban quick-add dialog. Downstream apps can\n * target it from `widgets/components.ts` to replace/wrap the dialog or to\n * transform its props \u2014 e.g. `defaultProbability: null` so quick-create stops\n * seeding a probability that overrides pipeline automation (#4329).\n */\nexport const QUICK_DEAL_DIALOG_COMPONENT_ID = 'dialog:customers.deals.quickDeal'\n\n/** Probability seeded into the quick-add form when the host passes no override. */\nexport const DEFAULT_QUICK_DEAL_PROBABILITY = 25\n\nexport type QuickDealDialogProps = {\n open: boolean\n context: QuickDealContext | null\n onClose: () => void\n onCreated: () => void\n currentUserId?: string\n currentUserLabel?: string\n companies?: QuickDealCompanyOption[]\n /**\n * Probability pre-filled in the collapsed \"More details\" group. `null` leaves\n * the field empty, so quick-create sends no `probability` at all and whatever\n * the pipeline/automation derives for the target stage stands. Defaults to\n * `DEFAULT_QUICK_DEAL_PROBABILITY` to preserve the historic behavior.\n */\n defaultProbability?: number | null\n /**\n * Tenant currency list. When omitted (e.g. dictionary not yet loaded), we render a\n * conservative fallback so the dialog still works end-to-end. The default selection is\n * always the entry with `isBase: true`, falling back to the first item.\n */\n currencies?: QuickDealCurrencyOption[]\n}\n\ntype QuickDealFormValues = {\n title: string\n valueAmount: number | null\n valueCurrency: string\n companyId: string\n status: (typeof STATUS_OPTIONS)[number]\n probability: number | null\n expectedCloseAt: string\n description: string\n}\n\nconst QUICK_DEAL_CONTEXT_ID = 'customers-deals-kanban:quick-deal'\n\nexport function QuickDealDialog({\n open,\n context,\n onClose,\n onCreated,\n currentUserId,\n currentUserLabel,\n companies = [],\n currencies,\n defaultProbability = DEFAULT_QUICK_DEAL_PROBABILITY,\n}: QuickDealDialogProps): React.ReactElement | null {\n const t = useT()\n // Re-mount CrudForm whenever the dialog opens so cleared state is consistently fresh.\n // We also key on `context?.pipelineStageId` so reopening from a different stage doesn't\n // reuse stale field values (the page passes a fresh stage in `context` each time).\n const [formInstanceKey, setFormInstanceKey] = React.useState(0)\n React.useEffect(() => {\n if (open) setFormInstanceKey((current) => current + 1)\n }, [open])\n\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: QUICK_DEAL_CONTEXT_ID,\n blockedMessage: translateWithFallback(t, 'ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n\n const titleRequiredMessage = translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.title.required',\n 'Title is required.',\n )\n\n // Default currency selection: tenant base currency, else first available, else 'USD' as\n // a last-resort literal that satisfies the form validator (which now accepts any 3-char\n // code rather than a hardcoded enum).\n const resolvedCurrencies = React.useMemo(\n () => (currencies && currencies.length > 0 ? currencies : FALLBACK_CURRENCIES),\n [currencies],\n )\n const defaultCurrencyCode = React.useMemo(() => {\n const base = resolvedCurrencies.find((currency) => currency.isBase)\n return base?.code ?? resolvedCurrencies[0]?.code ?? 'USD'\n }, [resolvedCurrencies])\n\n const formSchema = React.useMemo(\n () =>\n z.object({\n title: z.string().trim().min(1, titleRequiredMessage),\n valueAmount: z.number().min(0).nullable().optional(),\n // The set of valid currencies is tenant-defined and resolved at runtime; we accept\n // any non-empty string here and let the server (which knows the canonical list)\n // reject anything bogus.\n valueCurrency: z.string().min(1),\n companyId: z.string().optional(),\n status: z.enum(STATUS_OPTIONS),\n probability: z.number().min(0).max(100).nullable().optional(),\n expectedCloseAt: z.string().optional(),\n description: z.string().optional(),\n }),\n // Cast widens to QuickDealFormValues so CrudForm's TValues generic stays exact.\n [titleRequiredMessage],\n ) as unknown as z.ZodType<QuickDealFormValues>\n\n const initialValues = React.useMemo<Partial<QuickDealFormValues>>(\n () => ({\n title: '',\n valueAmount: null,\n valueCurrency: defaultCurrencyCode,\n companyId: '',\n status: 'open',\n probability: defaultProbability,\n expectedCloseAt: '',\n description: '',\n }),\n [defaultCurrencyCode, defaultProbability],\n )\n\n const fields = React.useMemo<CrudField[]>(\n () => {\n const list: CrudField[] = [\n {\n // CrudForm auto-focuses the first field of the first group on mount; we don't\n // need (and CrudField doesn't accept) an explicit `autoFocus` prop here.\n id: 'title',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.title.label', 'Deal title'),\n type: 'text',\n required: true,\n placeholder: translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.title.placeholder',\n 'e.g. Q3 Expansion \u2014 Lighting Package',\n ),\n },\n {\n id: 'valueAmount',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.value', 'Value'),\n type: 'number',\n layout: 'half',\n placeholder: '0',\n },\n {\n id: 'valueCurrency',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.currency', 'Currency'),\n type: 'select',\n layout: 'half',\n options: resolvedCurrencies.map((currency) => ({\n value: currency.code,\n label: currency.label && currency.label !== currency.code\n ? `${currency.code} \u2014 ${currency.label}`\n : currency.code,\n })),\n },\n {\n // Company is a typeahead (ComboboxInput) rather than a plain <select>: tenants\n // with hundreds of companies get an unusable dropdown otherwise. The `seedOptions`\n // carry the most-recent companies the page already loaded; an async loader could\n // be added later to hit the companies search endpoint for full coverage.\n id: 'companyId',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.company', 'Company'),\n type: 'custom',\n component: ({ value, setValue }) => (\n <ComboboxInput\n value={typeof value === 'string' ? value : ''}\n onChange={(next) => setValue(next)}\n seedOptions={companies.map((company) => ({ value: company.id, label: company.label }))}\n placeholder={translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.companyPh',\n 'Pick a company or add new\u2026',\n )}\n allowCustomValues={false}\n />\n ),\n },\n ]\n // Owner is read-only display of the current user (mirrors original UX). Hidden when\n // we don't know the user \u2014 avoids confusing empty avatar cell.\n if (currentUserLabel) {\n list.push({\n id: 'owner',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.owner', 'Owner'),\n type: 'custom',\n readOnly: true,\n component: () => (\n <div className=\"flex h-9 items-center gap-2 rounded-md border border-input bg-card px-3 text-sm\">\n <Avatar label={currentUserLabel} size=\"sm\" />\n <span>{currentUserLabel}</span>\n </div>\n ),\n })\n }\n // Progressive disclosure: status + probability + close date + description live in\n // a separate \"More details\" group with `defaultExpanded: false` (configured via\n // collapsibleGroups on the host CrudForm).\n list.push(\n {\n id: 'status',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.status', 'Status'),\n type: 'select',\n // Storage value is preserved (`lost` etc.), only the displayed label is\n // translated, so we never write a localised string back to the DB.\n options: STATUS_OPTIONS.map((statusValue) => ({\n value: statusValue,\n label: translateWithFallback(\n t,\n `customers.deals.kanban.quickDeal.status.${statusValue}`,\n statusValue,\n ),\n })),\n },\n {\n id: 'probability',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.probability', 'Probability'),\n type: 'number',\n layout: 'half',\n placeholder: '25',\n },\n {\n id: 'expectedCloseAt',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.expectedClose', 'Expected close'),\n type: 'date',\n layout: 'half',\n },\n {\n id: 'description',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.description', 'Description'),\n type: 'textarea',\n rows: 3,\n placeholder: translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.description.placeholder',\n 'Short context, decision makers or next steps. Markdown supported.',\n ),\n },\n )\n return list\n },\n [companies, currentUserLabel, resolvedCurrencies, t],\n )\n\n const groups = React.useMemo<CrudFormGroup[]>(\n () => [\n {\n id: 'basic',\n // No title \u2014 keep the basic section flush with the dialog header.\n fields: ['title', 'valueAmount', 'valueCurrency', 'companyId', ...(currentUserLabel ? ['owner'] : [])],\n },\n {\n id: 'more',\n title: translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.more',\n 'More details (probability, close date, description)',\n ),\n fields: ['status', 'probability', 'expectedCloseAt', 'description'],\n },\n ],\n [currentUserLabel, t],\n )\n\n const handleSubmit = React.useCallback(\n async (values: QuickDealFormValues) => {\n if (!context) return\n const trimmedTitle = values.title.trim()\n if (!trimmedTitle.length) {\n throw createCrudFormError(titleRequiredMessage, { title: titleRequiredMessage })\n }\n const payload: Record<string, unknown> = {\n title: trimmedTitle,\n pipelineId: context.pipelineId,\n pipelineStageId: context.pipelineStageId,\n valueCurrency: values.valueCurrency,\n }\n if (typeof values.valueAmount === 'number' && Number.isFinite(values.valueAmount)) {\n payload.valueAmount = values.valueAmount\n }\n if (currentUserId) payload.ownerUserId = currentUserId\n if (values.companyId) payload.companyIds = [values.companyId]\n if (values.status) payload.status = values.status\n if (typeof values.probability === 'number' && Number.isFinite(values.probability)) {\n payload.probability = values.probability\n }\n if (values.expectedCloseAt && values.expectedCloseAt.trim().length) {\n payload.expectedCloseAt = values.expectedCloseAt\n }\n if (values.description && values.description.trim().length) {\n payload.description = values.description\n }\n const operation = () =>\n createCrud('customers/deals', payload, {\n errorMessage: translateWithFallback(t, 'customers.deals.create.error', 'Failed to create deal.'),\n })\n await runMutation({\n operation,\n context: {\n formId: QUICK_DEAL_CONTEXT_ID,\n resourceKind: 'customers.deal',\n retryLastMutation,\n },\n })\n flash(\n translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.success',\n 'Deal added to {stage}.',\n { stage: context.pipelineStageLabel },\n ),\n 'success',\n )\n onCreated()\n onClose()\n },\n [context, currentUserId, onClose, onCreated, retryLastMutation, runMutation, t, titleRequiredMessage],\n )\n\n if (!context) return null\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n if (!next) onClose()\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {translateWithFallback(t, 'customers.deals.kanban.quickDeal.title', 'Quick deal')}\n </DialogTitle>\n <DialogDescription>\n {translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.context',\n 'Pipeline: {pipeline} \u00B7 Stage: {stage}',\n { pipeline: context.pipelineName, stage: context.pipelineStageLabel },\n )}\n </DialogDescription>\n </DialogHeader>\n\n <CrudForm<QuickDealFormValues>\n key={`${context.pipelineStageId}:${formInstanceKey}`}\n embedded\n fields={fields}\n groups={groups}\n // The \"More details\" group starts collapsed; users can expand to set\n // status / probability / close date / description. Mirrors the previous\n // \"+ More details\" toggle.\n collapsibleGroups={{ pageType: 'customers.deals.kanban.quickDeal' }}\n initialValues={initialValues}\n schema={formSchema}\n submitLabel={translateWithFallback(t, 'customers.deals.kanban.quickDeal.submit', 'Add deal')}\n onSubmit={handleSubmit}\n />\n </DialogContent>\n </Dialog>\n )\n}\n\n// Register so downstream apps can reach the dialog from `widgets/components.ts`\n// (replace / wrap / propsTransform) instead of forking the whole kanban page\n// just to change a default (#4329).\nregisterComponent<QuickDealDialogProps>({\n id: QUICK_DEAL_DIALOG_COMPONENT_ID,\n component: QuickDealDialog,\n metadata: {\n module: 'customers',\n description: 'Kanban quick-add deal dialog (pipeline board \"+ deal\").',\n },\n})\n\nexport default QuickDealDialog\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { Avatar } from '@open-mercato/ui/primitives/avatar'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { ComboboxInput } from '@open-mercato/ui/backend/inputs/ComboboxInput'\nimport { createCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { extensionPoints } from '../../../../../extension-points'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { registerComponent } from '@open-mercato/shared/modules/widgets/component-registry'\n\n// Deal status values written by the kanban flow. These intentionally do NOT include 'closed'\n// because the rest of the app only persists 'lost' for lost deals (see StatusFilterPopover\n// notes). 'in_progress' is kept for backwards compatibility with quick-deals created from\n// the previous version of this dialog. Deals written before 0.7.1 carry the misspelled\n// 'loose'; readers still match it through `lib/dealStatus.ts`, but no writer produces it.\nconst STATUS_OPTIONS = ['open', 'in_progress', 'win', 'lost'] as const\n\n/**\n * Tenant currency option. The page resolves these from the currencies module (see\n * `useCurrencyDictionary`) and passes them in; we no longer hardcode the 4-currency\n * list that previously locked tenants on CZK/SEK/HUF/etc. out of quick-add.\n */\nexport type QuickDealCurrencyOption = {\n code: string\n label?: string\n isBase?: boolean\n}\n\nconst FALLBACK_CURRENCIES: QuickDealCurrencyOption[] = [\n { code: 'USD', isBase: true },\n { code: 'EUR' },\n { code: 'GBP' },\n { code: 'PLN' },\n]\n\nexport type QuickDealContext = {\n pipelineId: string\n pipelineName: string\n pipelineStageId: string\n pipelineStageLabel: string\n}\n\nexport type QuickDealCompanyOption = {\n id: string\n label: string\n}\n\n/**\n * Registered component id for the kanban quick-add dialog. Downstream apps can\n * target it from `widgets/components.ts` to replace/wrap the dialog or to\n * transform its props \u2014 e.g. `defaultProbability: null` so quick-create stops\n * seeding a probability that overrides pipeline automation (#4329).\n */\nexport const QUICK_DEAL_DIALOG_COMPONENT_ID = 'dialog:customers.deals.quickDeal'\n\n/** Probability seeded into the quick-add form when the host passes no override. */\nexport const DEFAULT_QUICK_DEAL_PROBABILITY = 25\n\nexport type QuickDealDialogProps = {\n open: boolean\n context: QuickDealContext | null\n onClose: () => void\n onCreated: () => void\n currentUserId?: string\n currentUserLabel?: string\n companies?: QuickDealCompanyOption[]\n /**\n * Probability pre-filled in the collapsed \"More details\" group. `null` leaves\n * the field empty, so quick-create sends no `probability` at all and whatever\n * the pipeline/automation derives for the target stage stands. Defaults to\n * `DEFAULT_QUICK_DEAL_PROBABILITY` to preserve the historic behavior.\n */\n defaultProbability?: number | null\n /**\n * Tenant currency list. When omitted (e.g. dictionary not yet loaded), we render a\n * conservative fallback so the dialog still works end-to-end. The default selection is\n * always the entry with `isBase: true`, falling back to the first item.\n */\n currencies?: QuickDealCurrencyOption[]\n}\n\ntype QuickDealFormValues = {\n title: string\n valueAmount: number | null\n valueCurrency: string\n companyId: string\n status: (typeof STATUS_OPTIONS)[number]\n probability: number | null\n expectedCloseAt: string\n description: string\n}\n\nconst QUICK_DEAL_CONTEXT_ID = 'customers-deals-kanban:quick-deal'\n\nexport function QuickDealDialog({\n open,\n context,\n onClose,\n onCreated,\n currentUserId,\n currentUserLabel,\n companies = [],\n currencies,\n defaultProbability = DEFAULT_QUICK_DEAL_PROBABILITY,\n}: QuickDealDialogProps): React.ReactElement | null {\n const t = useT()\n // Re-mount CrudForm whenever the dialog opens so cleared state is consistently fresh.\n // We also key on `context?.pipelineStageId` so reopening from a different stage doesn't\n // reuse stale field values (the page passes a fresh stage in `context` each time).\n const [formInstanceKey, setFormInstanceKey] = React.useState(0)\n React.useEffect(() => {\n if (open) setFormInstanceKey((current) => current + 1)\n }, [open])\n\n\n const { runMutation, retryLastMutation } = useGuardedMutation({ contextId: QUICK_DEAL_CONTEXT_ID, blockedMessage: translateWithFallback(t, 'ui.forms.flash.saveBlocked', 'Save blocked by validation') })\n\n const titleRequiredMessage = translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.title.required',\n 'Title is required.',\n )\n\n // Default currency selection: tenant base currency, else first available, else 'USD' as\n // a last-resort literal that satisfies the form validator (which now accepts any 3-char\n // code rather than a hardcoded enum).\n const resolvedCurrencies = React.useMemo(\n () => (currencies && currencies.length > 0 ? currencies : FALLBACK_CURRENCIES),\n [currencies],\n )\n const defaultCurrencyCode = React.useMemo(() => {\n const base = resolvedCurrencies.find((currency) => currency.isBase)\n return base?.code ?? resolvedCurrencies[0]?.code ?? 'USD'\n }, [resolvedCurrencies])\n\n const formSchema = React.useMemo(\n () =>\n z.object({\n title: z.string().trim().min(1, titleRequiredMessage),\n valueAmount: z.number().min(0).nullable().optional(),\n // The set of valid currencies is tenant-defined and resolved at runtime; we accept\n // any non-empty string here and let the server (which knows the canonical list)\n // reject anything bogus.\n valueCurrency: z.string().min(1),\n companyId: z.string().optional(),\n status: z.enum(STATUS_OPTIONS),\n probability: z.number().min(0).max(100).nullable().optional(),\n expectedCloseAt: z.string().optional(),\n description: z.string().optional(),\n }),\n // Cast widens to QuickDealFormValues so CrudForm's TValues generic stays exact.\n [titleRequiredMessage],\n ) as unknown as z.ZodType<QuickDealFormValues>\n\n const initialValues = React.useMemo<Partial<QuickDealFormValues>>(\n () => ({\n title: '',\n valueAmount: null,\n valueCurrency: defaultCurrencyCode,\n companyId: '',\n status: 'open',\n probability: defaultProbability,\n expectedCloseAt: '',\n description: '',\n }),\n [defaultCurrencyCode, defaultProbability],\n )\n\n const fields = React.useMemo<CrudField[]>(\n () => {\n const list: CrudField[] = [\n {\n // CrudForm auto-focuses the first field of the first group on mount; we don't\n // need (and CrudField doesn't accept) an explicit `autoFocus` prop here.\n id: 'title',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.title.label', 'Deal title'),\n type: 'text',\n required: true,\n placeholder: translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.title.placeholder',\n 'e.g. Q3 Expansion \u2014 Lighting Package',\n ),\n },\n {\n id: 'valueAmount',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.value', 'Value'),\n type: 'number',\n layout: 'half',\n placeholder: '0',\n },\n {\n id: 'valueCurrency',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.currency', 'Currency'),\n type: 'select',\n layout: 'half',\n options: resolvedCurrencies.map((currency) => ({\n value: currency.code,\n label: currency.label && currency.label !== currency.code\n ? `${currency.code} \u2014 ${currency.label}`\n : currency.code,\n })),\n },\n {\n // Company is a typeahead (ComboboxInput) rather than a plain <select>: tenants\n // with hundreds of companies get an unusable dropdown otherwise. The `seedOptions`\n // carry the most-recent companies the page already loaded; an async loader could\n // be added later to hit the companies search endpoint for full coverage.\n id: 'companyId',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.company', 'Company'),\n type: 'custom',\n component: ({ value, setValue }) => (\n <ComboboxInput\n value={typeof value === 'string' ? value : ''}\n onChange={(next) => setValue(next)}\n seedOptions={companies.map((company) => ({ value: company.id, label: company.label }))}\n placeholder={translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.companyPh',\n 'Pick a company or add new\u2026',\n )}\n allowCustomValues={false}\n />\n ),\n },\n ]\n // Owner is read-only display of the current user (mirrors original UX). Hidden when\n // we don't know the user \u2014 avoids confusing empty avatar cell.\n if (currentUserLabel) {\n list.push({\n id: 'owner',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.owner', 'Owner'),\n type: 'custom',\n readOnly: true,\n component: () => (\n <div className=\"flex h-9 items-center gap-2 rounded-md border border-input bg-card px-3 text-sm\">\n <Avatar label={currentUserLabel} size=\"sm\" />\n <span>{currentUserLabel}</span>\n </div>\n ),\n })\n }\n // Progressive disclosure: status + probability + close date + description live in\n // a separate \"More details\" group with `defaultExpanded: false` (configured via\n // collapsibleGroups on the host CrudForm).\n list.push(\n {\n id: 'status',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.status', 'Status'),\n type: 'select',\n // Storage value is preserved (`lost` etc.), only the displayed label is\n // translated, so we never write a localised string back to the DB.\n options: STATUS_OPTIONS.map((statusValue) => ({\n value: statusValue,\n label: translateWithFallback(\n t,\n `customers.deals.kanban.quickDeal.status.${statusValue}`,\n statusValue,\n ),\n })),\n },\n {\n id: 'probability',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.probability', 'Probability'),\n type: 'number',\n layout: 'half',\n placeholder: '25',\n },\n {\n id: 'expectedCloseAt',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.expectedClose', 'Expected close'),\n type: 'date',\n layout: 'half',\n },\n {\n id: 'description',\n label: translateWithFallback(t, 'customers.deals.kanban.quickDeal.description', 'Description'),\n type: 'textarea',\n rows: 3,\n placeholder: translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.description.placeholder',\n 'Short context, decision makers or next steps. Markdown supported.',\n ),\n },\n )\n return list\n },\n [companies, currentUserLabel, resolvedCurrencies, t],\n )\n\n const groups = React.useMemo<CrudFormGroup[]>(\n () => [\n {\n id: 'basic',\n // No title \u2014 keep the basic section flush with the dialog header.\n fields: ['title', 'valueAmount', 'valueCurrency', 'companyId', ...(currentUserLabel ? ['owner'] : [])],\n },\n {\n id: 'more',\n title: translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.more',\n 'More details (probability, close date, description)',\n ),\n fields: ['status', 'probability', 'expectedCloseAt', 'description'],\n },\n ],\n [currentUserLabel, t],\n )\n\n const handleSubmit = React.useCallback(\n async (values: QuickDealFormValues) => {\n if (!context) return\n const trimmedTitle = values.title.trim()\n if (!trimmedTitle.length) {\n throw createCrudFormError(titleRequiredMessage, { title: titleRequiredMessage })\n }\n const payload: Record<string, unknown> = {\n title: trimmedTitle,\n pipelineId: context.pipelineId,\n pipelineStageId: context.pipelineStageId,\n valueCurrency: values.valueCurrency,\n }\n if (typeof values.valueAmount === 'number' && Number.isFinite(values.valueAmount)) {\n payload.valueAmount = values.valueAmount\n }\n if (currentUserId) payload.ownerUserId = currentUserId\n if (values.companyId) payload.companyIds = [values.companyId]\n if (values.status) payload.status = values.status\n if (typeof values.probability === 'number' && Number.isFinite(values.probability)) {\n payload.probability = values.probability\n }\n if (values.expectedCloseAt && values.expectedCloseAt.trim().length) {\n payload.expectedCloseAt = values.expectedCloseAt\n }\n if (values.description && values.description.trim().length) {\n payload.description = values.description\n }\n const { result } = await runMutation({\n operation: () => createCrud<{ id?: string; entityId?: string }>('customers/deals', payload, {\n errorMessage: translateWithFallback(t, 'customers.deals.create.error', 'Failed to create deal.'),\n }),\n context: { formId: QUICK_DEAL_CONTEXT_ID, resourceKind: 'customers.deal', retryLastMutation },\n mutationPayload: payload,\n })\n flash(\n translateWithFallback(t, 'customers.deals.kanban.quickDeal.success', 'Deal added to {stage}.', { stage: context.pipelineStageLabel }),\n 'success',\n )\n return { resourceId: result?.id ?? result?.entityId }\n },\n [context, currentUserId, t, titleRequiredMessage, runMutation, retryLastMutation],\n )\n\n const handleSubmitSuccess = React.useCallback(() => {\n if (!context) return\n onCreated()\n onClose()\n }, [context, onCreated, onClose])\n\n if (!context) return null\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n if (!next) onClose()\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {translateWithFallback(t, 'customers.deals.kanban.quickDeal.title', 'Quick deal')}\n </DialogTitle>\n <DialogDescription>\n {translateWithFallback(\n t,\n 'customers.deals.kanban.quickDeal.context',\n 'Pipeline: {pipeline} \u00B7 Stage: {stage}',\n { pipeline: context.pipelineName, stage: context.pipelineStageLabel },\n )}\n </DialogDescription>\n </DialogHeader>\n\n <CrudForm<QuickDealFormValues>\n key={`${context.pipelineStageId}:${formInstanceKey}`}\n embedded\n formId={QUICK_DEAL_CONTEXT_ID}\n entityId=\"customers.deal\"\n entityIds={[E.customers.customer_deal]}\n resourceKind=\"customers.deal\"\n injectionSpotId={extensionPoints.hosts.dealForm.spotId}\n injectionGroupAliases={{ details: 'basic' }}\n fields={fields}\n groups={groups}\n // The \"More details\" group starts collapsed; users can expand to set\n // status / probability / close date / description. Mirrors the previous\n // \"+ More details\" toggle.\n collapsibleGroups={{ pageType: 'customers.deals.kanban.quickDeal' }}\n initialValues={initialValues}\n schema={formSchema}\n submitLabel={translateWithFallback(t, 'customers.deals.kanban.quickDeal.submit', 'Add deal')}\n onSubmit={handleSubmit}\n onSubmitSuccess={handleSubmitSuccess}\n />\n </DialogContent>\n </Dialog>\n )\n}\n\n// Register so downstream apps can reach the dialog from `widgets/components.ts`\n// (replace / wrap / propsTransform) instead of forking the whole kanban page\n// just to change a default (#4329).\nregisterComponent<QuickDealDialogProps>({\n id: QUICK_DEAL_DIALOG_COMPONENT_ID,\n component: QuickDealDialog,\n metadata: {\n module: 'customers',\n description: 'Kanban quick-add deal dialog (pipeline board \"+ deal\").',\n },\n})\n\nexport default QuickDealDialog\n"],
5
+ "mappings": ";AAkOY,cAuBA,YAvBA;AAhOZ,YAAY,WAAW;AACvB,SAAS,SAAS;AAClB,SAAS,SAAS;AAClB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AACvB,SAAS,gBAAoD;AAC7D,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAC3B,SAAS,2BAA2B;AACpC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,6BAA6B;AACtC,SAAS,yBAAyB;AAOlC,MAAM,iBAAiB,CAAC,QAAQ,eAAe,OAAO,MAAM;AAa5D,MAAM,sBAAiD;AAAA,EACrD,EAAE,MAAM,OAAO,QAAQ,KAAK;AAAA,EAC5B,EAAE,MAAM,MAAM;AAAA,EACd,EAAE,MAAM,MAAM;AAAA,EACd,EAAE,MAAM,MAAM;AAChB;AAoBO,MAAM,iCAAiC;AAGvC,MAAM,iCAAiC;AAoC9C,MAAM,wBAAwB;AAEvB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,CAAC;AAAA,EACb;AAAA,EACA,qBAAqB;AACvB,GAAoD;AAClD,QAAM,IAAI,KAAK;AAIf,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,MAAM,SAAS,CAAC;AAC9D,QAAM,UAAU,MAAM;AACpB,QAAI,KAAM,oBAAmB,CAAC,YAAY,UAAU,CAAC;AAAA,EACvD,GAAG,CAAC,IAAI,CAAC;AAGT,QAAM,EAAE,aAAa,kBAAkB,IAAI,mBAAmB,EAAE,WAAW,uBAAuB,gBAAgB,sBAAsB,GAAG,8BAA8B,4BAA4B,EAAE,CAAC;AAExM,QAAM,uBAAuB;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAKA,QAAM,qBAAqB,MAAM;AAAA,IAC/B,MAAO,cAAc,WAAW,SAAS,IAAI,aAAa;AAAA,IAC1D,CAAC,UAAU;AAAA,EACb;AACA,QAAM,sBAAsB,MAAM,QAAQ,MAAM;AAC9C,UAAM,OAAO,mBAAmB,KAAK,CAAC,aAAa,SAAS,MAAM;AAClE,WAAO,MAAM,QAAQ,mBAAmB,CAAC,GAAG,QAAQ;AAAA,EACtD,GAAG,CAAC,kBAAkB,CAAC;AAEvB,QAAM,aAAa,MAAM;AAAA,IACvB,MACE,EAAE,OAAO;AAAA,MACP,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,GAAG,oBAAoB;AAAA,MACpD,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA,MAInD,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,MAC/B,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,MAC/B,QAAQ,EAAE,KAAK,cAAc;AAAA,MAC7B,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS;AAAA,MAC5D,iBAAiB,EAAE,OAAO,EAAE,SAAS;AAAA,MACrC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,IACnC,CAAC;AAAA;AAAA,IAEH,CAAC,oBAAoB;AAAA,EACvB;AAEA,QAAM,gBAAgB,MAAM;AAAA,IAC1B,OAAO;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAe;AAAA,MACf,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,iBAAiB;AAAA,MACjB,aAAa;AAAA,IACf;AAAA,IACA,CAAC,qBAAqB,kBAAkB;AAAA,EAC1C;AAEA,QAAM,SAAS,MAAM;AAAA,IACnB,MAAM;AACJ,YAAM,OAAoB;AAAA,QACxB;AAAA;AAAA;AAAA,UAGE,IAAI;AAAA,UACJ,OAAO,sBAAsB,GAAG,gDAAgD,YAAY;AAAA,UAC5F,MAAM;AAAA,UACN,UAAU;AAAA,UACV,aAAa;AAAA,YACX;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO,sBAAsB,GAAG,0CAA0C,OAAO;AAAA,UACjF,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO,sBAAsB,GAAG,6CAA6C,UAAU;AAAA,UACvF,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,SAAS,mBAAmB,IAAI,CAAC,cAAc;AAAA,YAC7C,OAAO,SAAS;AAAA,YAChB,OAAO,SAAS,SAAS,SAAS,UAAU,SAAS,OACjD,GAAG,SAAS,IAAI,WAAM,SAAS,KAAK,KACpC,SAAS;AAAA,UACf,EAAE;AAAA,QACJ;AAAA,QACA;AAAA;AAAA;AAAA;AAAA;AAAA,UAKE,IAAI;AAAA,UACJ,OAAO,sBAAsB,GAAG,4CAA4C,SAAS;AAAA,UACrF,MAAM;AAAA,UACN,WAAW,CAAC,EAAE,OAAO,SAAS,MAC5B;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,cAC3C,UAAU,CAAC,SAAS,SAAS,IAAI;AAAA,cACjC,aAAa,UAAU,IAAI,CAAC,aAAa,EAAE,OAAO,QAAQ,IAAI,OAAO,QAAQ,MAAM,EAAE;AAAA,cACrF,aAAa;AAAA,gBACX;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,cACA,mBAAmB;AAAA;AAAA,UACrB;AAAA,QAEJ;AAAA,MACF;AAGA,UAAI,kBAAkB;AACpB,aAAK,KAAK;AAAA,UACR,IAAI;AAAA,UACJ,OAAO,sBAAsB,GAAG,0CAA0C,OAAO;AAAA,UACjF,MAAM;AAAA,UACN,UAAU;AAAA,UACV,WAAW,MACT,qBAAC,SAAI,WAAU,mFACb;AAAA,gCAAC,UAAO,OAAO,kBAAkB,MAAK,MAAK;AAAA,YAC3C,oBAAC,UAAM,4BAAiB;AAAA,aAC1B;AAAA,QAEJ,CAAC;AAAA,MACH;AAIA,WAAK;AAAA,QACH;AAAA,UACE,IAAI;AAAA,UACJ,OAAO,sBAAsB,GAAG,2CAA2C,QAAQ;AAAA,UACnF,MAAM;AAAA;AAAA;AAAA,UAGN,SAAS,eAAe,IAAI,CAAC,iBAAiB;AAAA,YAC5C,OAAO;AAAA,YACP,OAAO;AAAA,cACL;AAAA,cACA,2CAA2C,WAAW;AAAA,cACtD;AAAA,YACF;AAAA,UACF,EAAE;AAAA,QACJ;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO,sBAAsB,GAAG,gDAAgD,aAAa;AAAA,UAC7F,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO,sBAAsB,GAAG,kDAAkD,gBAAgB;AAAA,UAClG,MAAM;AAAA,UACN,QAAQ;AAAA,QACV;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO,sBAAsB,GAAG,gDAAgD,aAAa;AAAA,UAC7F,MAAM;AAAA,UACN,MAAM;AAAA,UACN,aAAa;AAAA,YACX;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,WAAW,kBAAkB,oBAAoB,CAAC;AAAA,EACrD;AAEA,QAAM,SAAS,MAAM;AAAA,IACnB,MAAM;AAAA,MACJ;AAAA,QACE,IAAI;AAAA;AAAA,QAEJ,QAAQ,CAAC,SAAS,eAAe,iBAAiB,aAAa,GAAI,mBAAmB,CAAC,OAAO,IAAI,CAAC,CAAE;AAAA,MACvG;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,QAAQ,CAAC,UAAU,eAAe,mBAAmB,aAAa;AAAA,MACpE;AAAA,IACF;AAAA,IACA,CAAC,kBAAkB,CAAC;AAAA,EACtB;AAEA,QAAM,eAAe,MAAM;AAAA,IACzB,OAAO,WAAgC;AACrC,UAAI,CAAC,QAAS;AACd,YAAM,eAAe,OAAO,MAAM,KAAK;AACvC,UAAI,CAAC,aAAa,QAAQ;AACxB,cAAM,oBAAoB,sBAAsB,EAAE,OAAO,qBAAqB,CAAC;AAAA,MACjF;AACA,YAAM,UAAmC;AAAA,QACvC,OAAO;AAAA,QACP,YAAY,QAAQ;AAAA,QACpB,iBAAiB,QAAQ;AAAA,QACzB,eAAe,OAAO;AAAA,MACxB;AACA,UAAI,OAAO,OAAO,gBAAgB,YAAY,OAAO,SAAS,OAAO,WAAW,GAAG;AACjF,gBAAQ,cAAc,OAAO;AAAA,MAC/B;AACA,UAAI,cAAe,SAAQ,cAAc;AACzC,UAAI,OAAO,UAAW,SAAQ,aAAa,CAAC,OAAO,SAAS;AAC5D,UAAI,OAAO,OAAQ,SAAQ,SAAS,OAAO;AAC3C,UAAI,OAAO,OAAO,gBAAgB,YAAY,OAAO,SAAS,OAAO,WAAW,GAAG;AACjF,gBAAQ,cAAc,OAAO;AAAA,MAC/B;AACA,UAAI,OAAO,mBAAmB,OAAO,gBAAgB,KAAK,EAAE,QAAQ;AAClE,gBAAQ,kBAAkB,OAAO;AAAA,MACnC;AACA,UAAI,OAAO,eAAe,OAAO,YAAY,KAAK,EAAE,QAAQ;AAC1D,gBAAQ,cAAc,OAAO;AAAA,MAC/B;AACA,YAAM,EAAE,OAAO,IAAI,MAAM,YAAY;AAAA,QACnC,WAAW,MAAM,WAA+C,mBAAmB,SAAS;AAAA,UAC1F,cAAc,sBAAsB,GAAG,gCAAgC,wBAAwB;AAAA,QACjG,CAAC;AAAA,QACD,SAAS,EAAE,QAAQ,uBAAuB,cAAc,kBAAkB,kBAAkB;AAAA,QAC5F,iBAAiB;AAAA,MACnB,CAAC;AACD;AAAA,QACE,sBAAsB,GAAG,4CAA4C,0BAA0B,EAAE,OAAO,QAAQ,mBAAmB,CAAC;AAAA,QACpI;AAAA,MACF;AACA,aAAO,EAAE,YAAY,QAAQ,MAAM,QAAQ,SAAS;AAAA,IACtD;AAAA,IACA,CAAC,SAAS,eAAe,GAAG,sBAAsB,aAAa,iBAAiB;AAAA,EAClF;AAEA,QAAM,sBAAsB,MAAM,YAAY,MAAM;AAClD,QAAI,CAAC,QAAS;AACd,cAAU;AACV,YAAQ;AAAA,EACV,GAAG,CAAC,SAAS,WAAW,OAAO,CAAC;AAEhC,MAAI,CAAC,QAAS,QAAO;AAErB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,cAAc,CAAC,SAAS;AACtB,YAAI,CAAC,KAAM,SAAQ;AAAA,MACrB;AAAA,MAEA,+BAAC,iBACC;AAAA,6BAAC,gBACC;AAAA,8BAAC,eACE,gCAAsB,GAAG,0CAA0C,YAAY,GAClF;AAAA,UACA,oBAAC,qBACE;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA,EAAE,UAAU,QAAQ,cAAc,OAAO,QAAQ,mBAAmB;AAAA,UACtE,GACF;AAAA,WACF;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YAEC,UAAQ;AAAA,YACR,QAAQ;AAAA,YACR,UAAS;AAAA,YACT,WAAW,CAAC,EAAE,UAAU,aAAa;AAAA,YACrC,cAAa;AAAA,YACb,iBAAiB,gBAAgB,MAAM,SAAS;AAAA,YAChD,uBAAuB,EAAE,SAAS,QAAQ;AAAA,YAC1C;AAAA,YACA;AAAA,YAIA,mBAAmB,EAAE,UAAU,mCAAmC;AAAA,YAClE;AAAA,YACA,QAAQ;AAAA,YACR,aAAa,sBAAsB,GAAG,2CAA2C,UAAU;AAAA,YAC3F,UAAU;AAAA,YACV,iBAAiB;AAAA;AAAA,UAlBZ,GAAG,QAAQ,eAAe,IAAI,eAAe;AAAA,QAmBpD;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;AAKA,kBAAwC;AAAA,EACtC,IAAI;AAAA,EACJ,WAAW;AAAA,EACX,UAAU;AAAA,IACR,QAAQ;AAAA,IACR,aAAa;AAAA,EACf;AACF,CAAC;AAED,IAAO,0BAAQ;",
6
6
  "names": []
7
7
  }
@@ -10,6 +10,7 @@ import { E } from "../../../../../../generated/entities.ids.generated.js";
10
10
  import { useT } from "@open-mercato/shared/lib/i18n/context";
11
11
  import { useOrganizationScopeDetail } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
12
12
  import { flash } from "@open-mercato/ui/backend/FlashMessages";
13
+ import { extensionPoints } from "../../../../extension-points.js";
13
14
  import {
14
15
  buildPersonPayload,
15
16
  createPersonFormFields,
@@ -47,6 +48,10 @@ function CreatePersonPage() {
47
48
  fields,
48
49
  groups,
49
50
  initialValues,
51
+ injectionSpotId: extensionPoints.hosts.personForm.spotId,
52
+ legacyInjectionSpotId: "crud-form:customers.customer_entity",
53
+ entityId: "customers.person",
54
+ resourceKind: "customers.person",
50
55
  entityIds: [E.customers.customer_entity, E.customers.customer_person_profile],
51
56
  submitLabel: t("customers.people.form.submit"),
52
57
  cancelHref: returnTo ?? "/backend/customers/people",
@@ -112,6 +117,10 @@ function CreatePersonPage() {
112
117
  }
113
118
  }
114
119
  flash(t("customers.people.form.success"), "success");
120
+ return newId ? { resourceId: newId } : void 0;
121
+ },
122
+ onSubmitSuccess: async (_values, result) => {
123
+ const newId = result?.resourceId;
115
124
  if (returnTo) router.push(returnTo);
116
125
  else if (newId) router.push(`/backend/customers/people-v2/${newId}`);
117
126
  else router.push("/backend/customers/people");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/customers/backend/customers/people/create/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { createCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport {\n buildPersonPayload,\n createPersonFormFields,\n createPersonFormGroups,\n createPersonFormSchema,\n type PersonFormValues,\n} from '../../../../components/formConfig'\n\nexport default function CreatePersonPage() {\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { organizationId } = useOrganizationScopeDetail()\n\n const formSchema = React.useMemo(() => createPersonFormSchema(), [])\n const fields = React.useMemo(() => createPersonFormFields(t), [t])\n const groups = React.useMemo(() => createPersonFormGroups(t), [t])\n const returnTo = searchParams.get('returnTo')\n const companyParam = searchParams.get('companyId')\n const companyEntityId = React.useMemo(() => {\n if (!companyParam) return undefined\n const trimmed = companyParam.trim()\n return trimmed.length ? trimmed : undefined\n }, [companyParam])\n const initialValues = React.useMemo<Partial<PersonFormValues>>(\n () => ({\n addresses: [] as PersonFormValues['addresses'],\n ...(companyEntityId ? { companyEntityId } : {}),\n }),\n [companyEntityId],\n )\n\n return (\n <Page>\n <PageBody>\n <CrudForm<PersonFormValues>\n title={t('customers.people.create.title')}\n titleHeadingLevel={1}\n backHref={returnTo ?? '/backend/customers/people'}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n submitLabel={t('customers.people.form.submit')}\n cancelHref={returnTo ?? '/backend/customers/people'}\n schema={formSchema}\n onSubmit={async (values) => {\n const addresses = Array.isArray(values.addresses) ? values.addresses : []\n let payload: Record<string, unknown>\n try {\n payload = buildPersonPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error && err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.people.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n throw err\n }\n\n const { result: created } = await createCrud<{ id?: string; entityId?: string }>(\n 'customers/people',\n payload,\n )\n const newId =\n created && typeof created.id === 'string'\n ? created.id\n : (typeof created?.entityId === 'string' ? created.entityId : null)\n\n if (newId && addresses.length) {\n const normalize = (value?: string | null) => {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n return trimmed.length ? trimmed : undefined\n }\n for (const entry of addresses) {\n const normalizedLine1 = normalize(entry.addressLine1)\n if (!normalizedLine1) continue\n const body: Record<string, unknown> = {\n entityId: newId,\n ...(organizationId ? { organizationId } : {}),\n addressLine1: normalizedLine1,\n isPrimary: entry.isPrimary ?? false,\n }\n const name = normalize(entry.name)\n if (name !== undefined) body.name = name\n const purpose = normalize(entry.purpose)\n if (purpose !== undefined) body.purpose = purpose\n const line2 = normalize(entry.addressLine2)\n if (line2 !== undefined) body.addressLine2 = line2\n const buildingNumber = normalize(entry.buildingNumber)\n if (buildingNumber !== undefined) body.buildingNumber = buildingNumber\n const flatNumber = normalize(entry.flatNumber)\n if (flatNumber !== undefined) body.flatNumber = flatNumber\n const city = normalize(entry.city)\n if (city !== undefined) body.city = city\n const region = normalize(entry.region)\n if (region !== undefined) body.region = region\n const postalCode = normalize(entry.postalCode)\n if (postalCode !== undefined) body.postalCode = postalCode\n const country = normalize(entry.country)\n if (country !== undefined) body.country = country.toUpperCase()\n if (typeof entry.latitude === 'number') body.latitude = entry.latitude\n if (typeof entry.longitude === 'number') body.longitude = entry.longitude\n try {\n await createCrud('customers/addresses', body)\n } catch (addressErr) {\n const message =\n (addressErr instanceof Error && addressErr.message\n ? addressErr.message\n : null) ||\n t('customers.people.detail.addresses.error')\n flash(message, 'error')\n }\n }\n }\n\n flash(t('customers.people.form.success'), 'success')\n if (returnTo) router.push(returnTo)\n else if (newId) router.push(`/backend/customers/people-v2/${newId}`)\n else router.push('/backend/customers/people')\n }}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { createCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { extensionPoints } from '../../../../extension-points'\nimport {\n buildPersonPayload,\n createPersonFormFields,\n createPersonFormGroups,\n createPersonFormSchema,\n type PersonFormValues,\n} from '../../../../components/formConfig'\n\nexport default function CreatePersonPage() {\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { organizationId } = useOrganizationScopeDetail()\n\n const formSchema = React.useMemo(() => createPersonFormSchema(), [])\n const fields = React.useMemo(() => createPersonFormFields(t), [t])\n const groups = React.useMemo(() => createPersonFormGroups(t), [t])\n const returnTo = searchParams.get('returnTo')\n const companyParam = searchParams.get('companyId')\n const companyEntityId = React.useMemo(() => {\n if (!companyParam) return undefined\n const trimmed = companyParam.trim()\n return trimmed.length ? trimmed : undefined\n }, [companyParam])\n const initialValues = React.useMemo<Partial<PersonFormValues>>(\n () => ({\n addresses: [] as PersonFormValues['addresses'],\n ...(companyEntityId ? { companyEntityId } : {}),\n }),\n [companyEntityId],\n )\n\n return (\n <Page>\n <PageBody>\n <CrudForm<PersonFormValues>\n title={t('customers.people.create.title')}\n titleHeadingLevel={1}\n backHref={returnTo ?? '/backend/customers/people'}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n injectionSpotId={extensionPoints.hosts.personForm.spotId}\n legacyInjectionSpotId=\"crud-form:customers.customer_entity\"\n entityId=\"customers.person\"\n resourceKind=\"customers.person\"\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n submitLabel={t('customers.people.form.submit')}\n cancelHref={returnTo ?? '/backend/customers/people'}\n schema={formSchema}\n onSubmit={async (values) => {\n const addresses = Array.isArray(values.addresses) ? values.addresses : []\n let payload: Record<string, unknown>\n try {\n payload = buildPersonPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error && err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.people.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n throw err\n }\n\n const { result: created } = await createCrud<{ id?: string; entityId?: string }>(\n 'customers/people',\n payload,\n )\n const newId =\n created && typeof created.id === 'string'\n ? created.id\n : (typeof created?.entityId === 'string' ? created.entityId : null)\n\n if (newId && addresses.length) {\n const normalize = (value?: string | null) => {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n return trimmed.length ? trimmed : undefined\n }\n for (const entry of addresses) {\n const normalizedLine1 = normalize(entry.addressLine1)\n if (!normalizedLine1) continue\n const body: Record<string, unknown> = {\n entityId: newId,\n ...(organizationId ? { organizationId } : {}),\n addressLine1: normalizedLine1,\n isPrimary: entry.isPrimary ?? false,\n }\n const name = normalize(entry.name)\n if (name !== undefined) body.name = name\n const purpose = normalize(entry.purpose)\n if (purpose !== undefined) body.purpose = purpose\n const line2 = normalize(entry.addressLine2)\n if (line2 !== undefined) body.addressLine2 = line2\n const buildingNumber = normalize(entry.buildingNumber)\n if (buildingNumber !== undefined) body.buildingNumber = buildingNumber\n const flatNumber = normalize(entry.flatNumber)\n if (flatNumber !== undefined) body.flatNumber = flatNumber\n const city = normalize(entry.city)\n if (city !== undefined) body.city = city\n const region = normalize(entry.region)\n if (region !== undefined) body.region = region\n const postalCode = normalize(entry.postalCode)\n if (postalCode !== undefined) body.postalCode = postalCode\n const country = normalize(entry.country)\n if (country !== undefined) body.country = country.toUpperCase()\n if (typeof entry.latitude === 'number') body.latitude = entry.latitude\n if (typeof entry.longitude === 'number') body.longitude = entry.longitude\n try {\n await createCrud('customers/addresses', body)\n } catch (addressErr) {\n const message =\n (addressErr instanceof Error && addressErr.message\n ? addressErr.message\n : null) ||\n t('customers.people.detail.addresses.error')\n flash(message, 'error')\n }\n }\n }\n\n flash(t('customers.people.form.success'), 'success')\n return newId ? { resourceId: newId } : undefined\n }}\n onSubmitSuccess={async (_values, result) => {\n const newId = result?.resourceId\n if (returnTo) router.push(returnTo)\n else if (newId) router.push(`/backend/customers/people-v2/${newId}`)\n else router.push('/backend/customers/people')\n }}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }