@open-mercato/core 0.6.3-develop.3809.1.bde5459e65 → 0.6.3-develop.3811.1.be22750402

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.
package/AGENTS.md CHANGED
@@ -2,6 +2,42 @@
2
2
 
3
3
  `@open-mercato/core` contains all core business modules (auth, catalog, customers, sales, etc.). This guide covers the full extensibility contract and module development patterns.
4
4
 
5
+ ## Always
6
+
7
+ - Preserve auto-discovery contracts for module files, API routes, pages, subscribers, workers, widgets, and generated registries.
8
+ - Export `openApi` from every API route file.
9
+ - Use `makeCrudRoute` with `indexer: { entityType }` for CRUD routes that should participate in query indexing.
10
+ - Wire custom write routes through the mutation guard contract.
11
+ - Use declarative feature guards and add new `acl.ts` features to `setup.ts` `defaultRoleFeatures`.
12
+ - Use `findWithDecryption` / `findOneWithDecryption` for encrypted entities.
13
+ - Implement domain writes through commands so audit, undo, cache, events, and indexing stay consistent.
14
+ - Run `yarn generate` after changing module files discovered by the generator.
15
+
16
+ ## Ask First
17
+
18
+ - Ask before changing any contract surface from `BACKWARD_COMPATIBILITY.md`: auto-discovery, public types, import paths, event IDs, widget spot IDs, API URLs, DB schema, DI names, ACL features, notification IDs, CLI commands, or generated file contracts.
19
+ - Ask before moving versioned generated files or changing where generated registries live.
20
+ - Ask before applying migrations with `yarn db:migrate`; normal PRs should include migration files and snapshots.
21
+
22
+ ## Never
23
+
24
+ - Never create direct ORM relationships between modules; use foreign key IDs and fetch separately.
25
+ - Never expose cross-tenant data or omit tenant/organization scoping.
26
+ - Never hand-edit generated files.
27
+ - Never import generated app bootstrap files from packages.
28
+ - Never run raw `em.find` / `em.findOne` between scalar mutations and `em.flush()` on the same `EntityManager` without `withAtomicFlush`.
29
+ - Never hand-roll AES/KMS encryption or bypass `TenantDataEncryptionService`.
30
+ - Never compare raw feature arrays with exact string checks when wildcard grants apply.
31
+
32
+ ## Validation Commands
33
+
34
+ ```bash
35
+ yarn db:generate
36
+ yarn generate
37
+ yarn workspace @open-mercato/core build
38
+ yarn workspace @open-mercato/core test
39
+ ```
40
+
5
41
  ## Core Modules
6
42
 
7
43
  | Module | Path | Description |
@@ -593,7 +629,7 @@ const crud = makeCrudRoute({
593
629
  })
594
630
  ```
595
631
 
596
- ### Key Rules
632
+ ### Response Enricher Rules
597
633
 
598
634
  - MUST implement `enrichMany()` for batch endpoints (prevents N+1 queries)
599
635
  - MUST namespace enriched fields with `_moduleName` prefix (e.g. `_example.todoCount`)
@@ -13,6 +13,7 @@ import { collectCustomFieldValues } from "@open-mercato/ui/backend/utils/customF
13
13
  import { mapCrudServerErrorToFormErrors } from "@open-mercato/ui/backend/utils/serverErrors";
14
14
  import { E } from "../../../../../../generated/entities.ids.generated.js";
15
15
  import { useT } from "@open-mercato/shared/lib/i18n/context";
16
+ import { RecordNotFoundState, ErrorMessage } from "@open-mercato/ui/backend/detail";
16
17
  import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
17
18
  import { DetailFieldsSection } from "@open-mercato/ui/backend/detail";
18
19
  import {
@@ -64,6 +65,7 @@ function CustomerCompanyDetailPage({ params }) {
64
65
  const [data, setData] = React.useState(null);
65
66
  const [isLoading, setIsLoading] = React.useState(true);
66
67
  const [error, setError] = React.useState(null);
68
+ const [isNotFound, setIsNotFound] = React.useState(false);
67
69
  const [activeTab, setActiveTab] = React.useState(initialTab);
68
70
  const [sectionAction, setSectionAction] = React.useState(null);
69
71
  const [isDeleting, setIsDeleting] = React.useState(false);
@@ -192,7 +194,7 @@ function CustomerCompanyDetailPage({ params }) {
192
194
  );
193
195
  React.useEffect(() => {
194
196
  if (!id) {
195
- setError(t("customers.companies.detail.error.notFound", "Company not found."));
197
+ setIsNotFound(true);
196
198
  setIsLoading(false);
197
199
  return;
198
200
  }
@@ -214,8 +216,12 @@ function CustomerCompanyDetailPage({ params }) {
214
216
  setData(payload);
215
217
  } catch (err) {
216
218
  if (cancelled) return;
217
- const message = err instanceof Error ? err.message : t("customers.companies.detail.error.load", "Failed to load company.");
218
- setError(message);
219
+ if (err.status === 404) {
220
+ setIsNotFound(true);
221
+ } else {
222
+ const message = err instanceof Error ? err.message : t("customers.companies.detail.error.load", "Failed to load company.");
223
+ setError(message);
224
+ }
219
225
  setData(null);
220
226
  } finally {
221
227
  if (!cancelled) setIsLoading(false);
@@ -439,11 +445,24 @@ function CustomerCompanyDetailPage({ params }) {
439
445
  /* @__PURE__ */ jsx("span", { children: t("customers.companies.detail.loading", "Loading company\u2026") })
440
446
  ] }) }) });
441
447
  }
448
+ if (isNotFound) {
449
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
450
+ RecordNotFoundState,
451
+ {
452
+ label: t("customers.companies.detail.error.notFound", "Company not found."),
453
+ backHref: "/backend/customers/companies",
454
+ backLabel: t("customers.companies.detail.actions.backToList", "Back to companies")
455
+ }
456
+ ) }) });
457
+ }
442
458
  if (error || !data?.company?.id) {
443
- return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsxs("div", { className: "flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground", children: [
444
- /* @__PURE__ */ jsx("p", { children: error || t("customers.companies.detail.error.notFound", "Company not found.") }),
445
- /* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", children: /* @__PURE__ */ jsx(Link, { href: "/backend/customers/companies", children: t("customers.companies.detail.actions.backToList", "Back to companies") }) })
446
- ] }) }) });
459
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
460
+ ErrorMessage,
461
+ {
462
+ label: error ?? t("customers.companies.detail.error.notFound", "Company not found."),
463
+ action: /* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", size: "sm", children: /* @__PURE__ */ jsx(Link, { href: "/backend/customers/companies", children: t("customers.companies.detail.actions.backToList", "Back to companies") }) })
464
+ }
465
+ ) }) });
447
466
  }
448
467
  const { company, profile } = data;
449
468
  const companyId = company.id;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/customers/backend/customers/companies/%5Bid%5D/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Separator } from '@open-mercato/ui/primitives/separator'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { mapCrudServerErrorToFormErrors } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { DetailFieldsSection, type DetailFieldConfig } from '@open-mercato/ui/backend/detail'\nimport {\n ActivitiesSection,\n} from '../../../../components/detail/ActivitiesSection'\nimport {\n NotesSection,\n type CommentSummary,\n type SectionAction,\n} from '@open-mercato/ui/backend/detail'\nimport {\n TagsSection,\n type TagOption,\n} from '../../../../components/detail/TagsSection'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { AddressesSection } from '../../../../components/detail/AddressesSection'\nimport { TasksSection } from '../../../../components/detail/TasksSection'\nimport { CustomDataSection } from '../../../../components/detail/CustomDataSection'\nimport { CompanyHighlights } from '../../../../components/detail/CompanyHighlights'\nimport { normalizeCustomFieldSubmitValue } from '../../../../components/detail/customFieldUtils'\nimport { InlineDictionaryEditor, renderMultilineMarkdownDisplay } from '../../../../components/detail/InlineEditors'\nimport { formatTemplate } from '../../../../components/detail/utils'\nimport { coerceDisplayName } from '../../../../lib/displayName'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport {\n CompanyPeopleSection,\n type CompanyPersonSummary,\n} from '../../../../components/detail/CompanyPeopleSection'\nimport { AnnualRevenueField } from '../../../../components/detail/AnnualRevenueField'\nimport type { ActivitySummary, DealSummary, TagSummary, TodoLinkSummary } from '../../../../components/detail/types'\nimport { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\nimport { ICON_SUGGESTIONS } from '../../../../lib/dictionaries'\nimport { createCustomerNotesAdapter } from '../../../../components/detail/notesAdapter'\nimport { readMarkdownPreferenceCookie, writeMarkdownPreferenceCookie } from '../../../../lib/markdownPreference'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { DetailTabsLayout } from '../../../../components/detail/DetailTabsLayout'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'\n\ntype CompanyOverview = {\n company: {\n id: string\n displayName: string\n description?: string | null\n ownerUserId?: string | null\n primaryEmail?: string | null\n primaryPhone?: string | null\n status?: string | null\n lifecycleStage?: string | null\n source?: string | null\n nextInteractionAt?: string | null\n nextInteractionName?: string | null\n nextInteractionRefId?: string | null\n nextInteractionIcon?: string | null\n nextInteractionColor?: string | null\n organizationId?: string | null\n }\n profile: {\n id: string\n legalName?: string | null\n brandName?: string | null\n domain?: string | null\n websiteUrl?: string | null\n industry?: string | null\n sizeBucket?: string | null\n annualRevenue?: string | null\n } | null\n customFields: Record<string, unknown>\n tags: TagSummary[]\n comments: CommentSummary[]\n activities: ActivitySummary[]\n deals: DealSummary[]\n todos: TodoLinkSummary[]\n people: CompanyPersonSummary[]\n viewer?: {\n userId: string | null\n name?: string | null\n email?: string | null\n } | null\n}\n\ntype SectionKey = 'notes' | 'activities' | 'deals' | 'people' | 'addresses' | 'tasks' | string\n\nexport default function CustomerCompanyDetailPage({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n const notesAdapter = React.useMemo(() => createCustomerNotesAdapter(detailTranslator), [detailTranslator])\n const router = useRouter()\n const searchParams = useSearchParams()\n const initialTab = React.useMemo(() => {\n const raw = searchParams?.get('tab')\n if (raw === 'notes' || raw === 'activities' || raw === 'deals' || raw === 'people' || raw === 'addresses' || raw === 'tasks') {\n return raw\n }\n return 'notes'\n }, [searchParams])\n const [data, setData] = React.useState<CompanyOverview | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [activeTab, setActiveTab] = React.useState<SectionKey>(initialTab)\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n const [isDeleting, setIsDeleting] = React.useState(false)\n const currentCompanyId = data?.company?.id ?? null\n const companyDisplayName = coerceDisplayName(data?.company?.displayName)\n const companyName = companyDisplayName.trim().length\n ? companyDisplayName\n : t('customers.companies.list.deleteFallbackName', 'this company')\n const translateCompanyDetail = React.useCallback(\n (key: string, fallback?: string, params?: Record<string, string | number>) => {\n const mappedKey = key.startsWith('customers.people.detail.')\n ? key.replace('customers.people.detail.', 'customers.companies.detail.')\n : key\n const adjustedFallback =\n key.startsWith('customers.people.detail.') && fallback\n ? fallback\n .replace(/\\bPerson\\b/g, 'Company')\n .replace(/\\bperson\\b/g, 'company')\n .replace(/\\bPeople\\b/g, 'Companies')\n .replace(/\\bpeople\\b/g, 'companies')\n : fallback\n const translated = t(mappedKey, params)\n if (translated !== mappedKey || mappedKey === key) return translated\n const fallbackValue = t(key, params)\n if (fallbackValue !== key) return fallbackValue\n if (!adjustedFallback) return mappedKey\n return formatTemplate(adjustedFallback, params)\n },\n [t],\n )\n const sectionLoaderLabel =\n activeTab === 'activities'\n ? t('customers.companies.detail.activities.loading', 'Loading activities\u2026')\n : activeTab === 'deals'\n ? t('customers.companies.detail.deals.loading', 'Loading deals\u2026')\n : activeTab === 'people'\n ? t('customers.companies.detail.people.loading', 'Loading people\u2026')\n : t('customers.companies.detail.sectionLoading', 'Loading\u2026')\n const mutationContextId = React.useMemo(\n () => (currentCompanyId ? `customer-company:${currentCompanyId}` : `customer-company:${id ?? 'pending'}`),\n [currentCompanyId, id],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n companyId?: string | null\n resourceKind: string\n resourceId?: string\n data: CompanyOverview | null\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n companyId: currentCompanyId,\n resourceKind: 'customers.company',\n resourceId: currentCompanyId ?? (id ?? undefined),\n data,\n retryLastMutation,\n }),\n [currentCompanyId, data, id, mutationContextId, retryLastMutation],\n )\n const runMutationWithContext = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: injectionContext,\n })\n },\n [injectionContext, runMutation],\n )\n\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction(action)\n }, [])\n\n const handleSectionAction = React.useCallback(() => {\n if (!sectionAction || sectionAction.disabled) return\n sectionAction.onClick()\n }, [sectionAction])\n\n React.useEffect(() => {\n setSectionAction(null)\n }, [activeTab])\n\n const validators = React.useMemo(() => ({\n email: (value: string) => {\n if (!value) return null\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n return emailRegex.test(value) ? null : t('customers.companies.detail.inline.emailInvalid', 'Enter a valid email address.')\n },\n phone: (value: string) => {\n if (!value) return null\n return value.length >= 3 ? null : t('customers.companies.detail.inline.phoneInvalid', 'Phone number is too short.')\n },\n displayName: (value: string) => {\n const trimmed = value.trim()\n return trimmed.length ? null : t('customers.companies.form.displayName.error', 'Company name is required.')\n },\n website: (value: string) => {\n if (!value) return null\n try {\n const url = new URL(value.trim())\n return url.protocol === 'http:' || url.protocol === 'https:'\n ? null\n : t('customers.companies.detail.inline.websiteInvalid', 'Use a valid http(s) address.')\n } catch {\n return t('customers.companies.detail.inline.websiteInvalid', 'Use a valid http(s) address.')\n }\n },\n annualRevenue: (value: string) => {\n if (!value) return null\n const normalized = value.replace(/[, ]+/g, '')\n const amount = Number(normalized)\n if (Number.isNaN(amount) || amount < 0) {\n return t('customers.companies.detail.inline.annualRevenueInvalid', 'Enter a non-negative number.')\n }\n return null\n },\n }), [t])\n\n const { widgets: injectedTabWidgets } = useInjectionWidgets('customers.company.detail:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const id = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel ?? widget.module.metadata.title\n const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0\n const render = () => (\n <widget.module.Widget\n context={injectionContext}\n data={data}\n onDataChange={(next) => setData(next as CompanyOverview)}\n />\n )\n return { id, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext],\n )\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n const tabs = React.useMemo(\n () => [\n { id: 'notes' as const, label: t('customers.companies.detail.tabs.notes', 'Notes') },\n { id: 'activities' as const, label: t('customers.companies.detail.tabs.activities', 'Activities') },\n { id: 'deals' as const, label: t('customers.companies.detail.tabs.deals', 'Deals') },\n { id: 'people' as const, label: t('customers.companies.detail.tabs.people', 'People') },\n { id: 'addresses' as const, label: t('customers.companies.detail.tabs.addresses', 'Addresses') },\n { id: 'tasks' as const, label: t('customers.companies.detail.tabs.tasks', 'Tasks') },\n ...injectedTabs.map((tab) => ({ id: tab.id as SectionKey, label: tab.label })),\n ],\n [injectedTabs, t],\n )\n\n React.useEffect(() => {\n if (!id) {\n setError(t('customers.companies.detail.error.notFound', 'Company not found.'))\n setIsLoading(false)\n return\n }\n const companyId = id\n let cancelled = false\n async function load() {\n setIsLoading(true)\n setError(null)\n try {\n const search = new URLSearchParams()\n search.append('include', 'todos')\n search.append('include', 'people')\n const payload = await readApiResultOrThrow<CompanyOverview>(\n `/api/customers/companies/${encodeURIComponent(companyId)}?${search.toString()}`,\n undefined,\n { errorMessage: t('customers.companies.detail.error.load', 'Failed to load company.') },\n )\n if (cancelled) return\n setData(payload as CompanyOverview)\n } catch (err) {\n if (cancelled) return\n const message = err instanceof Error ? err.message : t('customers.companies.detail.error.load', 'Failed to load company.')\n setError(message)\n setData(null)\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n load().catch(() => {})\n return () => {\n cancelled = true\n }\n }, [id, t])\n\n const saveCompany = React.useCallback(\n async (patch: Record<string, unknown>, apply: (prev: CompanyOverview) => CompanyOverview) => {\n if (!data) return\n const payload = { id: data.company.id, ...patch }\n await runMutationWithContext(\n () => apiCallOrThrow(\n '/api/customers/companies',\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { errorMessage: t('customers.companies.detail.inline.error', 'Unable to update company.') },\n ),\n payload,\n )\n setData((prev) => (prev ? apply(prev) : prev))\n },\n [data, runMutationWithContext, t],\n )\n\n const updateDisplayName = React.useCallback(\n async (next: string | null) => {\n const send = typeof next === 'string' ? next : ''\n await saveCompany(\n { displayName: send },\n (prev) => ({\n ...prev,\n company: {\n ...prev.company,\n displayName: next && next.length ? next : prev.company.displayName,\n },\n })\n )\n },\n [saveCompany],\n )\n\n const updateCompanyField = React.useCallback(\n async (field: 'primaryEmail' | 'primaryPhone' | 'status' | 'lifecycleStage' | 'source', next: string | null) => {\n const send = typeof next === 'string' ? next : ''\n await saveCompany(\n { [field]: send },\n (prev) => ({\n ...prev,\n company: {\n ...prev.company,\n [field]: next && next.length ? next : null,\n },\n })\n )\n },\n [saveCompany],\n )\n\n const updateProfileField = React.useCallback(\n async (\n field: 'brandName' | 'legalName' | 'websiteUrl' | 'industry' | 'domain' | 'sizeBucket',\n next: string | null,\n ) => {\n const send = typeof next === 'string' ? next : ''\n await saveCompany(\n { [field]: send },\n (prev) => {\n if (!prev.profile) return prev\n const nextValue = next && next.length ? next : null\n return {\n ...prev,\n profile: {\n ...prev.profile,\n [field]: nextValue,\n },\n }\n }\n )\n },\n [saveCompany],\n )\n\n const submitCustomFields = React.useCallback(\n async (prefixedValues: Record<string, unknown>, { showFlash = true } = {}) => {\n if (!data) throw new Error(t('customers.companies.detail.inline.error', 'Unable to update company.'))\n const customPayload = collectCustomFieldValues(prefixedValues, {\n transform: (value) => normalizeCustomFieldSubmitValue(value),\n })\n const normalized: Record<string, unknown> = {}\n for (const [fieldId, value] of Object.entries(customPayload)) {\n normalized[`cf_${fieldId}`] = value\n }\n if (!Object.keys(customPayload).length) {\n if (showFlash) flash(t('ui.forms.flash.saveSuccess', 'Saved successfully.'), 'success')\n return\n }\n const payload = {\n id: data.company.id,\n customFields: customPayload,\n }\n try {\n await runMutationWithContext(\n () => apiCallOrThrow(\n '/api/customers/companies',\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { errorMessage: t('customers.companies.detail.inline.error', 'Unable to update company.') },\n ),\n payload,\n )\n } catch (err) {\n const { message: helperMessage, fieldErrors } = mapCrudServerErrorToFormErrors(err)\n const message = helperMessage ?? t('customers.companies.detail.inline.error', 'Unable to update company.')\n const mappedErrors: Record<string, string> | undefined = fieldErrors\n ? Object.entries(fieldErrors).reduce<Record<string, string>>((acc, [key, value]) => {\n const formKey = key.startsWith('cf_') ? key : `cf_${key}`\n acc[formKey] = value\n return acc\n }, {})\n : undefined\n const error = new Error(message) as Error & { fieldErrors?: Record<string, string> }\n if (mappedErrors && Object.keys(mappedErrors).length) error.fieldErrors = mappedErrors\n throw error\n }\n setData((prev) => {\n if (!prev) return prev\n return {\n ...prev,\n customFields: {\n ...prev.customFields,\n ...normalized,\n },\n }\n })\n if (showFlash) flash(t('ui.forms.flash.saveSuccess', 'Saved successfully.'), 'success')\n },\n [data, runMutationWithContext, t],\n )\n\n const handleAnnualRevenueChange = React.useCallback(\n async ({ amount, currency }: { amount: number | null; currency: string | null }) => {\n await saveCompany(\n { annualRevenue: amount ?? null },\n (prev) => {\n if (!prev.profile) return prev\n return {\n ...prev,\n profile: {\n ...prev.profile,\n annualRevenue: amount === null ? null : String(amount),\n },\n }\n }\n )\n await submitCustomFields(\n { cf_annual_revenue_currency: currency ?? null },\n { showFlash: false },\n )\n flash(t('ui.forms.flash.saveSuccess', 'Saved successfully.'), 'success')\n },\n [saveCompany, submitCustomFields, t],\n )\n\n const handleDelete = React.useCallback(async () => {\n if (!currentCompanyId) return\n const confirmed = await confirm({\n title: t('customers.companies.list.deleteConfirm', undefined, { name: companyName }),\n variant: 'destructive',\n })\n if (!confirmed) return\n setIsDeleting(true)\n try {\n await runMutationWithContext(\n () => apiCallOrThrow(\n `/api/customers/companies?id=${encodeURIComponent(currentCompanyId)}`,\n {\n method: 'DELETE',\n headers: { 'content-type': 'application/json' },\n },\n { errorMessage: t('customers.companies.list.deleteError', 'Failed to delete company.') },\n ),\n { id: currentCompanyId },\n )\n flash(t('customers.companies.list.deleteSuccess', 'Company deleted.'), 'success')\n router.push('/backend/customers/companies')\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.companies.list.deleteError', 'Failed to delete company.')\n flash(message, 'error')\n } finally {\n setIsDeleting(false)\n }\n }, [companyName, confirm, currentCompanyId, router, runMutationWithContext, t])\n\n const handleTagsChange = React.useCallback((nextTags: TagOption[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n\n const handleCustomFieldsSubmit = React.useCallback(\n async (values: Record<string, unknown>) => {\n await submitCustomFields(values)\n },\n [submitCustomFields],\n )\n\n const handleNotesLoadingChange = React.useCallback(() => {}, [])\n\n const handleActivitiesLoadingChange = React.useCallback(() => {}, [])\n\n const handleDealsLoadingChange = React.useCallback(() => {}, [])\n\n const handlePeopleLoadingChange = React.useCallback(() => {}, [])\n\n const handleAddressesLoadingChange = React.useCallback(() => {}, [])\n\n const handleTasksLoadingChange = React.useCallback(() => {}, [])\n\n const dealsScope = React.useMemo(\n () => (currentCompanyId ? ({ kind: 'company', entityId: currentCompanyId } as const) : null),\n [currentCompanyId],\n )\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-6 w-6\" />\n <span>{t('customers.companies.detail.loading', 'Loading company\u2026')}</span>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data?.company?.id) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <p>{error || t('customers.companies.detail.error.notFound', 'Company not found.')}</p>\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/customers/companies\">\n {t('customers.companies.detail.actions.backToList', 'Back to companies')}\n </Link>\n </Button>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n const { company, profile } = data\n const companyId = company.id\n\n const annualRevenueCurrency =\n typeof data.customFields?.annual_revenue_currency === 'string'\n ? (data.customFields.annual_revenue_currency as string)\n : null\n\n const detailFields: DetailFieldConfig[] = [\n {\n key: 'displayName',\n kind: 'text',\n label: t('customers.companies.detail.fields.displayName', 'Display name'),\n value: company.displayName,\n placeholder: t('customers.companies.form.displayName.placeholder', 'Enter company name'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n validator: validators.displayName,\n onSave: updateDisplayName,\n },\n {\n key: 'legalName',\n kind: 'text',\n label: t('customers.companies.detail.fields.legalName', 'Legal name'),\n value: profile?.legalName ?? null,\n placeholder: t('customers.companies.detail.fields.legalNamePlaceholder', 'Add legal name'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n onSave: (value) => updateProfileField('legalName', value),\n },\n {\n key: 'brandName',\n kind: 'text',\n label: t('customers.companies.detail.fields.brandName', 'Brand name'),\n value: profile?.brandName ?? null,\n placeholder: t('customers.companies.detail.fields.brandNamePlaceholder', 'Add brand name'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n onSave: (value) => updateProfileField('brandName', value),\n },\n {\n key: 'description',\n kind: 'multiline',\n label: t('customers.companies.detail.fields.description', 'Description'),\n value: company.description ?? null,\n placeholder: t('customers.companies.detail.fields.descriptionPlaceholder', 'Describe the company'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n gridClassName: 'sm:col-span-2 xl:col-span-3',\n renderDisplay: renderMultilineMarkdownDisplay,\n onSave: async (next) => {\n const send = typeof next === 'string' ? next : ''\n await saveCompany(\n { description: send },\n (prev) => ({\n ...prev,\n company: { ...prev.company, description: next && next.length ? next : null },\n })\n )\n },\n },\n {\n key: 'lifecycleStage',\n kind: 'custom',\n label: t('customers.companies.detail.fields.lifecycleStage', 'Lifecycle stage'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n render: () => (\n <InlineDictionaryEditor\n label={t('customers.companies.detail.fields.lifecycleStage', 'Lifecycle stage')}\n value={company.lifecycleStage ?? null}\n emptyLabel={t('customers.companies.detail.noValue', 'Not provided')}\n kind=\"lifecycle-stages\"\n onSave={(next) => updateCompanyField('lifecycleStage', next)}\n selectClassName=\"h-9 w-full rounded border px-3 text-sm\"\n variant=\"muted\"\n activateOnClick\n />\n ),\n },\n {\n key: 'source',\n kind: 'custom',\n label: t('customers.companies.detail.fields.source', 'Source'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n render: () => (\n <InlineDictionaryEditor\n label={t('customers.companies.detail.fields.source', 'Source')}\n value={company.source ?? null}\n emptyLabel={t('customers.companies.detail.noValue', 'Not provided')}\n kind=\"sources\"\n onSave={(next) => updateCompanyField('source', next)}\n selectClassName=\"h-9 w-full rounded border px-3 text-sm\"\n variant=\"muted\"\n activateOnClick\n />\n ),\n },\n {\n key: 'domain',\n kind: 'text',\n label: t('customers.companies.detail.fields.domain', 'Domain'),\n value: profile?.domain ?? null,\n placeholder: t('customers.companies.detail.fields.domainPlaceholder', 'example.com'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n onSave: (value) => updateProfileField('domain', value),\n },\n {\n key: 'industry',\n kind: 'custom',\n label: t('customers.companies.detail.fields.industry', 'Industry'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n render: () => (\n <InlineDictionaryEditor\n label={t('customers.companies.detail.fields.industry', 'Industry')}\n value={profile?.industry ?? null}\n emptyLabel={t('customers.companies.detail.noValue', 'Not provided')}\n kind=\"industries\"\n onSave={(next) => updateProfileField('industry', next)}\n selectClassName=\"h-9 w-full rounded border px-3 text-sm\"\n variant=\"muted\"\n activateOnClick\n />\n ),\n },\n {\n key: 'sizeBucket',\n kind: 'text',\n label: t('customers.companies.detail.fields.sizeBucket', 'Company size'),\n value: profile?.sizeBucket ?? null,\n placeholder: t('customers.companies.detail.fields.sizeBucketPlaceholder', 'Add size bucket'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n onSave: (value) => updateProfileField('sizeBucket', value),\n },\n {\n key: 'annualRevenue',\n kind: 'custom',\n label: t('customers.companies.detail.fields.annualRevenue', 'Annual revenue'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n render: () => (\n <AnnualRevenueField\n label={t('customers.companies.detail.fields.annualRevenue', 'Annual revenue')}\n amount={profile?.annualRevenue ?? null}\n currency={annualRevenueCurrency}\n emptyLabel={t('customers.companies.detail.noValue', 'Not provided')}\n validator={validators.annualRevenue}\n onSave={handleAnnualRevenueChange}\n />\n ),\n },\n {\n key: 'websiteUrl',\n kind: 'text',\n label: t('customers.companies.detail.fields.website', 'Website'),\n value: profile?.websiteUrl ?? null,\n placeholder: t('customers.companies.detail.fields.websitePlaceholder', 'https://example.com'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n inputType: 'url',\n validator: validators.website,\n onSave: (value) => updateProfileField('websiteUrl', value),\n },\n ]\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-8\">\n <CompanyHighlights\n company={company}\n profile={profile ?? null}\n validators={validators}\n onDisplayNameSave={updateDisplayName}\n utilityActions={(\n <SendObjectMessageDialog\n object={{\n entityModule: 'customers',\n entityType: 'company',\n entityId: companyId,\n previewData: {\n title: company.displayName,\n subtitle: company.primaryEmail ?? undefined,\n metadata: {\n [t('customers.companies.detail.highlights.primaryPhone')]: company.primaryPhone ?? '-',\n [t('customers.companies.detail.fields.industry')]: profile?.industry ?? '-',\n },\n },\n }}\n viewHref={`/backend/customers/companies/${companyId}`}\n />\n )}\n onPrimaryEmailSave={(value) => updateCompanyField('primaryEmail', value)}\n onPrimaryPhoneSave={(value) => updateCompanyField('primaryPhone', value)}\n onStatusSave={(value) => updateCompanyField('status', value)}\n onNextInteractionSave={async (payload) => {\n await saveCompany(\n {\n nextInteraction: payload\n ? {\n at: payload.at,\n name: payload.name ?? undefined,\n refId: payload.refId ?? undefined,\n icon: payload.icon ?? undefined,\n color: payload.color ?? undefined,\n }\n : null,\n },\n (prev) => ({\n ...prev,\n company: {\n ...prev.company,\n nextInteractionAt: payload?.at ?? null,\n nextInteractionName: payload?.name ?? null,\n nextInteractionRefId: payload?.refId ?? null,\n nextInteractionIcon: payload?.icon ?? null,\n nextInteractionColor: payload?.color ?? null,\n },\n })\n )\n }}\n onDelete={handleDelete}\n isDeleting={isDeleting}\n />\n\n <DetailTabsLayout\n className=\"space-y-6\"\n tabs={tabs}\n activeTab={activeTab}\n onTabChange={setActiveTab}\n sectionAction={sectionAction}\n onSectionAction={handleSectionAction}\n navAriaLabel={t('customers.companies.detail.tabs.label', 'Company detail sections')}\n navClassName=\"gap-4\"\n >\n {(() => {\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n if (activeTab === 'notes') {\n return (\n <NotesSection\n entityId={companyId}\n emptyLabel={t('customers.companies.detail.empty.comments', '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.companies.detail.notes.addLabel', 'Add note')}\n emptyState={{\n title: t('customers.companies.detail.emptyState.notes.title', 'Keep everyone in the loop'),\n actionLabel: t('customers.companies.detail.emptyState.notes.action', 'Create a note'),\n }}\n onActionChange={handleSectionActionChange}\n translator={translateCompanyDetail}\n onLoadingChange={handleNotesLoadingChange}\n dataAdapter={notesAdapter}\n renderIcon={renderDictionaryIcon}\n renderColor={renderDictionaryColor}\n iconSuggestions={ICON_SUGGESTIONS}\n readMarkdownPreference={readMarkdownPreferenceCookie}\n writeMarkdownPreference={writeMarkdownPreferenceCookie}\n />\n )\n }\n if (activeTab === 'activities') {\n return (\n <ActivitiesSection\n entityId={companyId}\n runGuardedMutation={runMutationWithContext}\n addActionLabel={t('customers.companies.detail.activities.add', 'Log activity')}\n emptyState={{\n title: t('customers.companies.detail.emptyState.activities.title', 'No activities logged yet'),\n actionLabel: t('customers.companies.detail.emptyState.activities.action', 'Log activity'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleActivitiesLoadingChange}\n />\n )\n }\n if (activeTab === 'deals') {\n return (\n <DealsSection\n scope={dealsScope}\n emptyLabel={t('customers.companies.detail.empty.deals', 'No deals linked to this company.')}\n addActionLabel={t('customers.companies.detail.actions.addDeal', 'Add deal')}\n emptyState={{\n title: t('customers.companies.detail.emptyState.deals.title', 'No deals yet'),\n actionLabel: t('customers.companies.detail.emptyState.deals.action', 'Create a deal'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleDealsLoadingChange}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n if (activeTab === 'people') {\n return (\n <CompanyPeopleSection\n companyId={companyId}\n initialPeople={data.people ?? []}\n addActionLabel={t('customers.companies.detail.people.add', 'Add person')}\n emptyLabel={t('customers.companies.detail.people.empty', 'No people linked to this company yet.')}\n emptyState={{\n title: t('customers.companies.detail.emptyState.people.title', 'Build the account team'),\n actionLabel: t('customers.companies.detail.emptyState.people.action', 'Create person'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handlePeopleLoadingChange}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n onPeopleChange={(next) => {\n setData((prev) => (prev ? { ...prev, people: next } : prev))\n }}\n />\n )\n }\n if (activeTab === 'addresses') {\n return (\n <AddressesSection\n entityId={companyId}\n emptyLabel={t('customers.companies.detail.empty.addresses', 'No addresses recorded.')}\n addActionLabel={t('customers.companies.detail.addresses.add', 'Add address')}\n emptyState={{\n title: t('customers.companies.detail.emptyState.addresses.title', 'No addresses yet'),\n actionLabel: t('customers.companies.detail.emptyState.addresses.action', 'Add address'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleAddressesLoadingChange}\n translator={detailTranslator}\n />\n )\n }\n if (activeTab === 'tasks') {\n return (\n <TasksSection\n entityId={companyId}\n initialTasks={data.todos}\n runGuardedMutation={runMutationWithContext}\n emptyLabel={t('customers.companies.detail.empty.todos', 'No tasks linked to this company.')}\n addActionLabel={t('customers.companies.detail.tasks.add', 'Add task')}\n emptyState={{\n title: t('customers.companies.detail.emptyState.tasks.title', 'Plan what happens next'),\n actionLabel: t('customers.companies.detail.emptyState.tasks.action', 'Create task'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleTasksLoadingChange}\n translator={translateCompanyDetail}\n entityName={companyName}\n dialogContextKey=\"customers.companies.detail.tasks.dialog.context\"\n dialogContextFallback=\"This task will be linked to {{name}}\"\n />\n )\n }\n return null\n })()}\n </DetailTabsLayout>\n\n <div className=\"space-y-6\">\n <div className=\"space-y-3\">\n <h2 className=\"text-sm font-semibold\">{t('customers.companies.detail.sections.details', 'Company details')}</h2>\n <DetailFieldsSection fields={detailFields} />\n <InjectionSpot\n spotId=\"customers.company.detail:details\"\n context={injectionContext}\n data={data}\n onDataChange={(next) => setData(next as CompanyOverview)}\n />\n </div>\n\n <CustomDataSection\n entityIds={[E.customers.customer_entity, E.customers.customer_company_profile]}\n values={data.customFields ?? {}}\n onSubmit={handleCustomFieldsSubmit}\n title={t('customers.companies.detail.sections.customFields', 'Custom fields')}\n />\n\n <TagsSection\n entityId={companyId}\n tags={data.tags}\n onChange={handleTagsChange}\n isSubmitting={false}\n />\n </div>\n\n <Separator className=\"my-4\" />\n </div>\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Separator } from '@open-mercato/ui/primitives/separator'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { mapCrudServerErrorToFormErrors } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { RecordNotFoundState, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { DetailFieldsSection, type DetailFieldConfig } from '@open-mercato/ui/backend/detail'\nimport {\n ActivitiesSection,\n} from '../../../../components/detail/ActivitiesSection'\nimport {\n NotesSection,\n type CommentSummary,\n type SectionAction,\n} from '@open-mercato/ui/backend/detail'\nimport {\n TagsSection,\n type TagOption,\n} from '../../../../components/detail/TagsSection'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { AddressesSection } from '../../../../components/detail/AddressesSection'\nimport { TasksSection } from '../../../../components/detail/TasksSection'\nimport { CustomDataSection } from '../../../../components/detail/CustomDataSection'\nimport { CompanyHighlights } from '../../../../components/detail/CompanyHighlights'\nimport { normalizeCustomFieldSubmitValue } from '../../../../components/detail/customFieldUtils'\nimport { InlineDictionaryEditor, renderMultilineMarkdownDisplay } from '../../../../components/detail/InlineEditors'\nimport { formatTemplate } from '../../../../components/detail/utils'\nimport { coerceDisplayName } from '../../../../lib/displayName'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport {\n CompanyPeopleSection,\n type CompanyPersonSummary,\n} from '../../../../components/detail/CompanyPeopleSection'\nimport { AnnualRevenueField } from '../../../../components/detail/AnnualRevenueField'\nimport type { ActivitySummary, DealSummary, TagSummary, TodoLinkSummary } from '../../../../components/detail/types'\nimport { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\nimport { ICON_SUGGESTIONS } from '../../../../lib/dictionaries'\nimport { createCustomerNotesAdapter } from '../../../../components/detail/notesAdapter'\nimport { readMarkdownPreferenceCookie, writeMarkdownPreferenceCookie } from '../../../../lib/markdownPreference'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { DetailTabsLayout } from '../../../../components/detail/DetailTabsLayout'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'\n\ntype CompanyOverview = {\n company: {\n id: string\n displayName: string\n description?: string | null\n ownerUserId?: string | null\n primaryEmail?: string | null\n primaryPhone?: string | null\n status?: string | null\n lifecycleStage?: string | null\n source?: string | null\n nextInteractionAt?: string | null\n nextInteractionName?: string | null\n nextInteractionRefId?: string | null\n nextInteractionIcon?: string | null\n nextInteractionColor?: string | null\n organizationId?: string | null\n }\n profile: {\n id: string\n legalName?: string | null\n brandName?: string | null\n domain?: string | null\n websiteUrl?: string | null\n industry?: string | null\n sizeBucket?: string | null\n annualRevenue?: string | null\n } | null\n customFields: Record<string, unknown>\n tags: TagSummary[]\n comments: CommentSummary[]\n activities: ActivitySummary[]\n deals: DealSummary[]\n todos: TodoLinkSummary[]\n people: CompanyPersonSummary[]\n viewer?: {\n userId: string | null\n name?: string | null\n email?: string | null\n } | null\n}\n\ntype SectionKey = 'notes' | 'activities' | 'deals' | 'people' | 'addresses' | 'tasks' | string\n\nexport default function CustomerCompanyDetailPage({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n const notesAdapter = React.useMemo(() => createCustomerNotesAdapter(detailTranslator), [detailTranslator])\n const router = useRouter()\n const searchParams = useSearchParams()\n const initialTab = React.useMemo(() => {\n const raw = searchParams?.get('tab')\n if (raw === 'notes' || raw === 'activities' || raw === 'deals' || raw === 'people' || raw === 'addresses' || raw === 'tasks') {\n return raw\n }\n return 'notes'\n }, [searchParams])\n const [data, setData] = React.useState<CompanyOverview | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n const [activeTab, setActiveTab] = React.useState<SectionKey>(initialTab)\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n const [isDeleting, setIsDeleting] = React.useState(false)\n const currentCompanyId = data?.company?.id ?? null\n const companyDisplayName = coerceDisplayName(data?.company?.displayName)\n const companyName = companyDisplayName.trim().length\n ? companyDisplayName\n : t('customers.companies.list.deleteFallbackName', 'this company')\n const translateCompanyDetail = React.useCallback(\n (key: string, fallback?: string, params?: Record<string, string | number>) => {\n const mappedKey = key.startsWith('customers.people.detail.')\n ? key.replace('customers.people.detail.', 'customers.companies.detail.')\n : key\n const adjustedFallback =\n key.startsWith('customers.people.detail.') && fallback\n ? fallback\n .replace(/\\bPerson\\b/g, 'Company')\n .replace(/\\bperson\\b/g, 'company')\n .replace(/\\bPeople\\b/g, 'Companies')\n .replace(/\\bpeople\\b/g, 'companies')\n : fallback\n const translated = t(mappedKey, params)\n if (translated !== mappedKey || mappedKey === key) return translated\n const fallbackValue = t(key, params)\n if (fallbackValue !== key) return fallbackValue\n if (!adjustedFallback) return mappedKey\n return formatTemplate(adjustedFallback, params)\n },\n [t],\n )\n const sectionLoaderLabel =\n activeTab === 'activities'\n ? t('customers.companies.detail.activities.loading', 'Loading activities\u2026')\n : activeTab === 'deals'\n ? t('customers.companies.detail.deals.loading', 'Loading deals\u2026')\n : activeTab === 'people'\n ? t('customers.companies.detail.people.loading', 'Loading people\u2026')\n : t('customers.companies.detail.sectionLoading', 'Loading\u2026')\n const mutationContextId = React.useMemo(\n () => (currentCompanyId ? `customer-company:${currentCompanyId}` : `customer-company:${id ?? 'pending'}`),\n [currentCompanyId, id],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n companyId?: string | null\n resourceKind: string\n resourceId?: string\n data: CompanyOverview | null\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n companyId: currentCompanyId,\n resourceKind: 'customers.company',\n resourceId: currentCompanyId ?? (id ?? undefined),\n data,\n retryLastMutation,\n }),\n [currentCompanyId, data, id, mutationContextId, retryLastMutation],\n )\n const runMutationWithContext = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: injectionContext,\n })\n },\n [injectionContext, runMutation],\n )\n\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction(action)\n }, [])\n\n const handleSectionAction = React.useCallback(() => {\n if (!sectionAction || sectionAction.disabled) return\n sectionAction.onClick()\n }, [sectionAction])\n\n React.useEffect(() => {\n setSectionAction(null)\n }, [activeTab])\n\n const validators = React.useMemo(() => ({\n email: (value: string) => {\n if (!value) return null\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n return emailRegex.test(value) ? null : t('customers.companies.detail.inline.emailInvalid', 'Enter a valid email address.')\n },\n phone: (value: string) => {\n if (!value) return null\n return value.length >= 3 ? null : t('customers.companies.detail.inline.phoneInvalid', 'Phone number is too short.')\n },\n displayName: (value: string) => {\n const trimmed = value.trim()\n return trimmed.length ? null : t('customers.companies.form.displayName.error', 'Company name is required.')\n },\n website: (value: string) => {\n if (!value) return null\n try {\n const url = new URL(value.trim())\n return url.protocol === 'http:' || url.protocol === 'https:'\n ? null\n : t('customers.companies.detail.inline.websiteInvalid', 'Use a valid http(s) address.')\n } catch {\n return t('customers.companies.detail.inline.websiteInvalid', 'Use a valid http(s) address.')\n }\n },\n annualRevenue: (value: string) => {\n if (!value) return null\n const normalized = value.replace(/[, ]+/g, '')\n const amount = Number(normalized)\n if (Number.isNaN(amount) || amount < 0) {\n return t('customers.companies.detail.inline.annualRevenueInvalid', 'Enter a non-negative number.')\n }\n return null\n },\n }), [t])\n\n const { widgets: injectedTabWidgets } = useInjectionWidgets('customers.company.detail:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const id = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel ?? widget.module.metadata.title\n const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0\n const render = () => (\n <widget.module.Widget\n context={injectionContext}\n data={data}\n onDataChange={(next) => setData(next as CompanyOverview)}\n />\n )\n return { id, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext],\n )\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n const tabs = React.useMemo(\n () => [\n { id: 'notes' as const, label: t('customers.companies.detail.tabs.notes', 'Notes') },\n { id: 'activities' as const, label: t('customers.companies.detail.tabs.activities', 'Activities') },\n { id: 'deals' as const, label: t('customers.companies.detail.tabs.deals', 'Deals') },\n { id: 'people' as const, label: t('customers.companies.detail.tabs.people', 'People') },\n { id: 'addresses' as const, label: t('customers.companies.detail.tabs.addresses', 'Addresses') },\n { id: 'tasks' as const, label: t('customers.companies.detail.tabs.tasks', 'Tasks') },\n ...injectedTabs.map((tab) => ({ id: tab.id as SectionKey, label: tab.label })),\n ],\n [injectedTabs, t],\n )\n\n React.useEffect(() => {\n if (!id) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n const companyId = id\n let cancelled = false\n async function load() {\n setIsLoading(true)\n setError(null)\n try {\n const search = new URLSearchParams()\n search.append('include', 'todos')\n search.append('include', 'people')\n const payload = await readApiResultOrThrow<CompanyOverview>(\n `/api/customers/companies/${encodeURIComponent(companyId)}?${search.toString()}`,\n undefined,\n { errorMessage: t('customers.companies.detail.error.load', 'Failed to load company.') },\n )\n if (cancelled) return\n setData(payload as CompanyOverview)\n } catch (err) {\n if (cancelled) return\n if ((err as { status?: number }).status === 404) {\n setIsNotFound(true)\n } else {\n const message = err instanceof Error ? err.message : t('customers.companies.detail.error.load', 'Failed to load company.')\n setError(message)\n }\n setData(null)\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n load().catch(() => {})\n return () => {\n cancelled = true\n }\n }, [id, t])\n\n const saveCompany = React.useCallback(\n async (patch: Record<string, unknown>, apply: (prev: CompanyOverview) => CompanyOverview) => {\n if (!data) return\n const payload = { id: data.company.id, ...patch }\n await runMutationWithContext(\n () => apiCallOrThrow(\n '/api/customers/companies',\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { errorMessage: t('customers.companies.detail.inline.error', 'Unable to update company.') },\n ),\n payload,\n )\n setData((prev) => (prev ? apply(prev) : prev))\n },\n [data, runMutationWithContext, t],\n )\n\n const updateDisplayName = React.useCallback(\n async (next: string | null) => {\n const send = typeof next === 'string' ? next : ''\n await saveCompany(\n { displayName: send },\n (prev) => ({\n ...prev,\n company: {\n ...prev.company,\n displayName: next && next.length ? next : prev.company.displayName,\n },\n })\n )\n },\n [saveCompany],\n )\n\n const updateCompanyField = React.useCallback(\n async (field: 'primaryEmail' | 'primaryPhone' | 'status' | 'lifecycleStage' | 'source', next: string | null) => {\n const send = typeof next === 'string' ? next : ''\n await saveCompany(\n { [field]: send },\n (prev) => ({\n ...prev,\n company: {\n ...prev.company,\n [field]: next && next.length ? next : null,\n },\n })\n )\n },\n [saveCompany],\n )\n\n const updateProfileField = React.useCallback(\n async (\n field: 'brandName' | 'legalName' | 'websiteUrl' | 'industry' | 'domain' | 'sizeBucket',\n next: string | null,\n ) => {\n const send = typeof next === 'string' ? next : ''\n await saveCompany(\n { [field]: send },\n (prev) => {\n if (!prev.profile) return prev\n const nextValue = next && next.length ? next : null\n return {\n ...prev,\n profile: {\n ...prev.profile,\n [field]: nextValue,\n },\n }\n }\n )\n },\n [saveCompany],\n )\n\n const submitCustomFields = React.useCallback(\n async (prefixedValues: Record<string, unknown>, { showFlash = true } = {}) => {\n if (!data) throw new Error(t('customers.companies.detail.inline.error', 'Unable to update company.'))\n const customPayload = collectCustomFieldValues(prefixedValues, {\n transform: (value) => normalizeCustomFieldSubmitValue(value),\n })\n const normalized: Record<string, unknown> = {}\n for (const [fieldId, value] of Object.entries(customPayload)) {\n normalized[`cf_${fieldId}`] = value\n }\n if (!Object.keys(customPayload).length) {\n if (showFlash) flash(t('ui.forms.flash.saveSuccess', 'Saved successfully.'), 'success')\n return\n }\n const payload = {\n id: data.company.id,\n customFields: customPayload,\n }\n try {\n await runMutationWithContext(\n () => apiCallOrThrow(\n '/api/customers/companies',\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { errorMessage: t('customers.companies.detail.inline.error', 'Unable to update company.') },\n ),\n payload,\n )\n } catch (err) {\n const { message: helperMessage, fieldErrors } = mapCrudServerErrorToFormErrors(err)\n const message = helperMessage ?? t('customers.companies.detail.inline.error', 'Unable to update company.')\n const mappedErrors: Record<string, string> | undefined = fieldErrors\n ? Object.entries(fieldErrors).reduce<Record<string, string>>((acc, [key, value]) => {\n const formKey = key.startsWith('cf_') ? key : `cf_${key}`\n acc[formKey] = value\n return acc\n }, {})\n : undefined\n const error = new Error(message) as Error & { fieldErrors?: Record<string, string> }\n if (mappedErrors && Object.keys(mappedErrors).length) error.fieldErrors = mappedErrors\n throw error\n }\n setData((prev) => {\n if (!prev) return prev\n return {\n ...prev,\n customFields: {\n ...prev.customFields,\n ...normalized,\n },\n }\n })\n if (showFlash) flash(t('ui.forms.flash.saveSuccess', 'Saved successfully.'), 'success')\n },\n [data, runMutationWithContext, t],\n )\n\n const handleAnnualRevenueChange = React.useCallback(\n async ({ amount, currency }: { amount: number | null; currency: string | null }) => {\n await saveCompany(\n { annualRevenue: amount ?? null },\n (prev) => {\n if (!prev.profile) return prev\n return {\n ...prev,\n profile: {\n ...prev.profile,\n annualRevenue: amount === null ? null : String(amount),\n },\n }\n }\n )\n await submitCustomFields(\n { cf_annual_revenue_currency: currency ?? null },\n { showFlash: false },\n )\n flash(t('ui.forms.flash.saveSuccess', 'Saved successfully.'), 'success')\n },\n [saveCompany, submitCustomFields, t],\n )\n\n const handleDelete = React.useCallback(async () => {\n if (!currentCompanyId) return\n const confirmed = await confirm({\n title: t('customers.companies.list.deleteConfirm', undefined, { name: companyName }),\n variant: 'destructive',\n })\n if (!confirmed) return\n setIsDeleting(true)\n try {\n await runMutationWithContext(\n () => apiCallOrThrow(\n `/api/customers/companies?id=${encodeURIComponent(currentCompanyId)}`,\n {\n method: 'DELETE',\n headers: { 'content-type': 'application/json' },\n },\n { errorMessage: t('customers.companies.list.deleteError', 'Failed to delete company.') },\n ),\n { id: currentCompanyId },\n )\n flash(t('customers.companies.list.deleteSuccess', 'Company deleted.'), 'success')\n router.push('/backend/customers/companies')\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.companies.list.deleteError', 'Failed to delete company.')\n flash(message, 'error')\n } finally {\n setIsDeleting(false)\n }\n }, [companyName, confirm, currentCompanyId, router, runMutationWithContext, t])\n\n const handleTagsChange = React.useCallback((nextTags: TagOption[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n\n const handleCustomFieldsSubmit = React.useCallback(\n async (values: Record<string, unknown>) => {\n await submitCustomFields(values)\n },\n [submitCustomFields],\n )\n\n const handleNotesLoadingChange = React.useCallback(() => {}, [])\n\n const handleActivitiesLoadingChange = React.useCallback(() => {}, [])\n\n const handleDealsLoadingChange = React.useCallback(() => {}, [])\n\n const handlePeopleLoadingChange = React.useCallback(() => {}, [])\n\n const handleAddressesLoadingChange = React.useCallback(() => {}, [])\n\n const handleTasksLoadingChange = React.useCallback(() => {}, [])\n\n const dealsScope = React.useMemo(\n () => (currentCompanyId ? ({ kind: 'company', entityId: currentCompanyId } as const) : null),\n [currentCompanyId],\n )\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-6 w-6\" />\n <span>{t('customers.companies.detail.loading', 'Loading company\u2026')}</span>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.companies.detail.error.notFound', 'Company not found.')}\n backHref=\"/backend/customers/companies\"\n backLabel={t('customers.companies.detail.actions.backToList', 'Back to companies')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data?.company?.id) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.companies.detail.error.notFound', 'Company not found.')}\n action={\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/backend/customers/companies\">\n {t('customers.companies.detail.actions.backToList', 'Back to companies')}\n </Link>\n </Button>\n }\n />\n </PageBody>\n </Page>\n )\n }\n\n const { company, profile } = data\n const companyId = company.id\n\n const annualRevenueCurrency =\n typeof data.customFields?.annual_revenue_currency === 'string'\n ? (data.customFields.annual_revenue_currency as string)\n : null\n\n const detailFields: DetailFieldConfig[] = [\n {\n key: 'displayName',\n kind: 'text',\n label: t('customers.companies.detail.fields.displayName', 'Display name'),\n value: company.displayName,\n placeholder: t('customers.companies.form.displayName.placeholder', 'Enter company name'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n validator: validators.displayName,\n onSave: updateDisplayName,\n },\n {\n key: 'legalName',\n kind: 'text',\n label: t('customers.companies.detail.fields.legalName', 'Legal name'),\n value: profile?.legalName ?? null,\n placeholder: t('customers.companies.detail.fields.legalNamePlaceholder', 'Add legal name'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n onSave: (value) => updateProfileField('legalName', value),\n },\n {\n key: 'brandName',\n kind: 'text',\n label: t('customers.companies.detail.fields.brandName', 'Brand name'),\n value: profile?.brandName ?? null,\n placeholder: t('customers.companies.detail.fields.brandNamePlaceholder', 'Add brand name'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n onSave: (value) => updateProfileField('brandName', value),\n },\n {\n key: 'description',\n kind: 'multiline',\n label: t('customers.companies.detail.fields.description', 'Description'),\n value: company.description ?? null,\n placeholder: t('customers.companies.detail.fields.descriptionPlaceholder', 'Describe the company'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n gridClassName: 'sm:col-span-2 xl:col-span-3',\n renderDisplay: renderMultilineMarkdownDisplay,\n onSave: async (next) => {\n const send = typeof next === 'string' ? next : ''\n await saveCompany(\n { description: send },\n (prev) => ({\n ...prev,\n company: { ...prev.company, description: next && next.length ? next : null },\n })\n )\n },\n },\n {\n key: 'lifecycleStage',\n kind: 'custom',\n label: t('customers.companies.detail.fields.lifecycleStage', 'Lifecycle stage'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n render: () => (\n <InlineDictionaryEditor\n label={t('customers.companies.detail.fields.lifecycleStage', 'Lifecycle stage')}\n value={company.lifecycleStage ?? null}\n emptyLabel={t('customers.companies.detail.noValue', 'Not provided')}\n kind=\"lifecycle-stages\"\n onSave={(next) => updateCompanyField('lifecycleStage', next)}\n selectClassName=\"h-9 w-full rounded border px-3 text-sm\"\n variant=\"muted\"\n activateOnClick\n />\n ),\n },\n {\n key: 'source',\n kind: 'custom',\n label: t('customers.companies.detail.fields.source', 'Source'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n render: () => (\n <InlineDictionaryEditor\n label={t('customers.companies.detail.fields.source', 'Source')}\n value={company.source ?? null}\n emptyLabel={t('customers.companies.detail.noValue', 'Not provided')}\n kind=\"sources\"\n onSave={(next) => updateCompanyField('source', next)}\n selectClassName=\"h-9 w-full rounded border px-3 text-sm\"\n variant=\"muted\"\n activateOnClick\n />\n ),\n },\n {\n key: 'domain',\n kind: 'text',\n label: t('customers.companies.detail.fields.domain', 'Domain'),\n value: profile?.domain ?? null,\n placeholder: t('customers.companies.detail.fields.domainPlaceholder', 'example.com'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n onSave: (value) => updateProfileField('domain', value),\n },\n {\n key: 'industry',\n kind: 'custom',\n label: t('customers.companies.detail.fields.industry', 'Industry'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n render: () => (\n <InlineDictionaryEditor\n label={t('customers.companies.detail.fields.industry', 'Industry')}\n value={profile?.industry ?? null}\n emptyLabel={t('customers.companies.detail.noValue', 'Not provided')}\n kind=\"industries\"\n onSave={(next) => updateProfileField('industry', next)}\n selectClassName=\"h-9 w-full rounded border px-3 text-sm\"\n variant=\"muted\"\n activateOnClick\n />\n ),\n },\n {\n key: 'sizeBucket',\n kind: 'text',\n label: t('customers.companies.detail.fields.sizeBucket', 'Company size'),\n value: profile?.sizeBucket ?? null,\n placeholder: t('customers.companies.detail.fields.sizeBucketPlaceholder', 'Add size bucket'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n onSave: (value) => updateProfileField('sizeBucket', value),\n },\n {\n key: 'annualRevenue',\n kind: 'custom',\n label: t('customers.companies.detail.fields.annualRevenue', 'Annual revenue'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n render: () => (\n <AnnualRevenueField\n label={t('customers.companies.detail.fields.annualRevenue', 'Annual revenue')}\n amount={profile?.annualRevenue ?? null}\n currency={annualRevenueCurrency}\n emptyLabel={t('customers.companies.detail.noValue', 'Not provided')}\n validator={validators.annualRevenue}\n onSave={handleAnnualRevenueChange}\n />\n ),\n },\n {\n key: 'websiteUrl',\n kind: 'text',\n label: t('customers.companies.detail.fields.website', 'Website'),\n value: profile?.websiteUrl ?? null,\n placeholder: t('customers.companies.detail.fields.websitePlaceholder', 'https://example.com'),\n emptyLabel: t('customers.companies.detail.noValue', 'Not provided'),\n inputType: 'url',\n validator: validators.website,\n onSave: (value) => updateProfileField('websiteUrl', value),\n },\n ]\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-8\">\n <CompanyHighlights\n company={company}\n profile={profile ?? null}\n validators={validators}\n onDisplayNameSave={updateDisplayName}\n utilityActions={(\n <SendObjectMessageDialog\n object={{\n entityModule: 'customers',\n entityType: 'company',\n entityId: companyId,\n previewData: {\n title: company.displayName,\n subtitle: company.primaryEmail ?? undefined,\n metadata: {\n [t('customers.companies.detail.highlights.primaryPhone')]: company.primaryPhone ?? '-',\n [t('customers.companies.detail.fields.industry')]: profile?.industry ?? '-',\n },\n },\n }}\n viewHref={`/backend/customers/companies/${companyId}`}\n />\n )}\n onPrimaryEmailSave={(value) => updateCompanyField('primaryEmail', value)}\n onPrimaryPhoneSave={(value) => updateCompanyField('primaryPhone', value)}\n onStatusSave={(value) => updateCompanyField('status', value)}\n onNextInteractionSave={async (payload) => {\n await saveCompany(\n {\n nextInteraction: payload\n ? {\n at: payload.at,\n name: payload.name ?? undefined,\n refId: payload.refId ?? undefined,\n icon: payload.icon ?? undefined,\n color: payload.color ?? undefined,\n }\n : null,\n },\n (prev) => ({\n ...prev,\n company: {\n ...prev.company,\n nextInteractionAt: payload?.at ?? null,\n nextInteractionName: payload?.name ?? null,\n nextInteractionRefId: payload?.refId ?? null,\n nextInteractionIcon: payload?.icon ?? null,\n nextInteractionColor: payload?.color ?? null,\n },\n })\n )\n }}\n onDelete={handleDelete}\n isDeleting={isDeleting}\n />\n\n <DetailTabsLayout\n className=\"space-y-6\"\n tabs={tabs}\n activeTab={activeTab}\n onTabChange={setActiveTab}\n sectionAction={sectionAction}\n onSectionAction={handleSectionAction}\n navAriaLabel={t('customers.companies.detail.tabs.label', 'Company detail sections')}\n navClassName=\"gap-4\"\n >\n {(() => {\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n if (activeTab === 'notes') {\n return (\n <NotesSection\n entityId={companyId}\n emptyLabel={t('customers.companies.detail.empty.comments', '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.companies.detail.notes.addLabel', 'Add note')}\n emptyState={{\n title: t('customers.companies.detail.emptyState.notes.title', 'Keep everyone in the loop'),\n actionLabel: t('customers.companies.detail.emptyState.notes.action', 'Create a note'),\n }}\n onActionChange={handleSectionActionChange}\n translator={translateCompanyDetail}\n onLoadingChange={handleNotesLoadingChange}\n dataAdapter={notesAdapter}\n renderIcon={renderDictionaryIcon}\n renderColor={renderDictionaryColor}\n iconSuggestions={ICON_SUGGESTIONS}\n readMarkdownPreference={readMarkdownPreferenceCookie}\n writeMarkdownPreference={writeMarkdownPreferenceCookie}\n />\n )\n }\n if (activeTab === 'activities') {\n return (\n <ActivitiesSection\n entityId={companyId}\n runGuardedMutation={runMutationWithContext}\n addActionLabel={t('customers.companies.detail.activities.add', 'Log activity')}\n emptyState={{\n title: t('customers.companies.detail.emptyState.activities.title', 'No activities logged yet'),\n actionLabel: t('customers.companies.detail.emptyState.activities.action', 'Log activity'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleActivitiesLoadingChange}\n />\n )\n }\n if (activeTab === 'deals') {\n return (\n <DealsSection\n scope={dealsScope}\n emptyLabel={t('customers.companies.detail.empty.deals', 'No deals linked to this company.')}\n addActionLabel={t('customers.companies.detail.actions.addDeal', 'Add deal')}\n emptyState={{\n title: t('customers.companies.detail.emptyState.deals.title', 'No deals yet'),\n actionLabel: t('customers.companies.detail.emptyState.deals.action', 'Create a deal'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleDealsLoadingChange}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n if (activeTab === 'people') {\n return (\n <CompanyPeopleSection\n companyId={companyId}\n initialPeople={data.people ?? []}\n addActionLabel={t('customers.companies.detail.people.add', 'Add person')}\n emptyLabel={t('customers.companies.detail.people.empty', 'No people linked to this company yet.')}\n emptyState={{\n title: t('customers.companies.detail.emptyState.people.title', 'Build the account team'),\n actionLabel: t('customers.companies.detail.emptyState.people.action', 'Create person'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handlePeopleLoadingChange}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n onPeopleChange={(next) => {\n setData((prev) => (prev ? { ...prev, people: next } : prev))\n }}\n />\n )\n }\n if (activeTab === 'addresses') {\n return (\n <AddressesSection\n entityId={companyId}\n emptyLabel={t('customers.companies.detail.empty.addresses', 'No addresses recorded.')}\n addActionLabel={t('customers.companies.detail.addresses.add', 'Add address')}\n emptyState={{\n title: t('customers.companies.detail.emptyState.addresses.title', 'No addresses yet'),\n actionLabel: t('customers.companies.detail.emptyState.addresses.action', 'Add address'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleAddressesLoadingChange}\n translator={detailTranslator}\n />\n )\n }\n if (activeTab === 'tasks') {\n return (\n <TasksSection\n entityId={companyId}\n initialTasks={data.todos}\n runGuardedMutation={runMutationWithContext}\n emptyLabel={t('customers.companies.detail.empty.todos', 'No tasks linked to this company.')}\n addActionLabel={t('customers.companies.detail.tasks.add', 'Add task')}\n emptyState={{\n title: t('customers.companies.detail.emptyState.tasks.title', 'Plan what happens next'),\n actionLabel: t('customers.companies.detail.emptyState.tasks.action', 'Create task'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleTasksLoadingChange}\n translator={translateCompanyDetail}\n entityName={companyName}\n dialogContextKey=\"customers.companies.detail.tasks.dialog.context\"\n dialogContextFallback=\"This task will be linked to {{name}}\"\n />\n )\n }\n return null\n })()}\n </DetailTabsLayout>\n\n <div className=\"space-y-6\">\n <div className=\"space-y-3\">\n <h2 className=\"text-sm font-semibold\">{t('customers.companies.detail.sections.details', 'Company details')}</h2>\n <DetailFieldsSection fields={detailFields} />\n <InjectionSpot\n spotId=\"customers.company.detail:details\"\n context={injectionContext}\n data={data}\n onDataChange={(next) => setData(next as CompanyOverview)}\n />\n </div>\n\n <CustomDataSection\n entityIds={[E.customers.customer_entity, E.customers.customer_company_profile]}\n values={data.customFields ?? {}}\n onSubmit={handleCustomFieldsSubmit}\n title={t('customers.companies.detail.sections.customFields', 'Custom fields')}\n />\n\n <TagsSection\n entityId={companyId}\n tags={data.tags}\n onChange={handleTagsChange}\n isSubmitting={false}\n />\n </div>\n\n <Separator className=\"my-4\" />\n </div>\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["params", "id", "companyId", "error"]
7
7
  }
@@ -6,10 +6,11 @@ function useDealData(id) {
6
6
  const [data, setData] = React.useState(null);
7
7
  const [isLoading, setIsLoading] = React.useState(true);
8
8
  const [error, setError] = React.useState(null);
9
+ const [isNotFound, setIsNotFound] = React.useState(false);
9
10
  const initialLoadDoneRef = React.useRef(false);
10
11
  const loadData = React.useCallback(async () => {
11
12
  if (!id) {
12
- setError(t("customers.deals.detail.error.notFound", "Deal not found."));
13
+ setIsNotFound(true);
13
14
  setIsLoading(false);
14
15
  return;
15
16
  }
@@ -25,15 +26,19 @@ function useDealData(id) {
25
26
  );
26
27
  setData(payload);
27
28
  } catch (loadError) {
28
- const message = loadError instanceof Error ? loadError.message : t("customers.deals.detail.error.load", "Failed to load deal.");
29
- setError(message);
29
+ if (loadError.status === 404) {
30
+ setIsNotFound(true);
31
+ } else {
32
+ const message = loadError instanceof Error ? loadError.message : t("customers.deals.detail.error.load", "Failed to load deal.");
33
+ setError(message);
34
+ }
30
35
  if (!initialLoadDoneRef.current) setData(null);
31
36
  } finally {
32
37
  setIsLoading(false);
33
38
  initialLoadDoneRef.current = true;
34
39
  }
35
40
  }, [id, t]);
36
- return { data, setData, isLoading, error, loadData };
41
+ return { data, setData, isLoading, error, isNotFound, loadData };
37
42
  }
38
43
  export {
39
44
  useDealData
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../../src/modules/customers/backend/customers/deals/%5Bid%5D/hooks/useDealData.ts"],
4
- "sourcesContent": ["import * as React from 'react'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { DealDetailPayload } from './types'\n\ntype UseDealDataResult = {\n data: DealDetailPayload | null\n setData: React.Dispatch<React.SetStateAction<DealDetailPayload | null>>\n isLoading: boolean\n error: string | null\n loadData: () => Promise<void>\n}\n\nexport function useDealData(id: string): UseDealDataResult {\n const t = useT()\n const [data, setData] = React.useState<DealDetailPayload | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const initialLoadDoneRef = React.useRef(false)\n\n const loadData = React.useCallback(async () => {\n if (!id) {\n setError(t('customers.deals.detail.error.notFound', 'Deal not found.'))\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n try {\n const payload = await readApiResultOrThrow<DealDetailPayload>(\n `/api/customers/deals/${encodeURIComponent(id)}?include=stages&view=lite`,\n undefined,\n { errorMessage: t('customers.deals.detail.error.load', 'Failed to load deal.') },\n )\n setData(payload)\n } catch (loadError) {\n const message =\n loadError instanceof Error\n ? loadError.message\n : t('customers.deals.detail.error.load', 'Failed to load deal.')\n setError(message)\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n return { data, setData, isLoading, error, loadData }\n}\n"],
5
- "mappings": "AAAA,YAAY,WAAW;AACvB,SAAS,4BAA4B;AACrC,SAAS,YAAY;AAWd,SAAS,YAAY,IAA+B;AACzD,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAmC,IAAI;AACrE,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,IAAI;AACrD,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAwB,IAAI;AAC5D,QAAM,qBAAqB,MAAM,OAAO,KAAK;AAE7C,QAAM,WAAW,MAAM,YAAY,YAAY;AAC7C,QAAI,CAAC,IAAI;AACP,eAAS,EAAE,yCAAyC,iBAAiB,CAAC;AACtE,mBAAa,KAAK;AAClB;AAAA,IACF;AACA,QAAI,CAAC,mBAAmB,SAAS;AAC/B,mBAAa,IAAI;AAAA,IACnB;AACA,aAAS,IAAI;AACb,QAAI;AACF,YAAM,UAAU,MAAM;AAAA,QACpB,wBAAwB,mBAAmB,EAAE,CAAC;AAAA,QAC9C;AAAA,QACA,EAAE,cAAc,EAAE,qCAAqC,sBAAsB,EAAE;AAAA,MACjF;AACA,cAAQ,OAAO;AAAA,IACjB,SAAS,WAAW;AAClB,YAAM,UACJ,qBAAqB,QACjB,UAAU,UACV,EAAE,qCAAqC,sBAAsB;AACnE,eAAS,OAAO;AAChB,UAAI,CAAC,mBAAmB,QAAS,SAAQ,IAAI;AAAA,IAC/C,UAAE;AACA,mBAAa,KAAK;AAClB,yBAAmB,UAAU;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,IAAI,CAAC,CAAC;AAEV,SAAO,EAAE,MAAM,SAAS,WAAW,OAAO,SAAS;AACrD;",
4
+ "sourcesContent": ["import * as React from 'react'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { DealDetailPayload } from './types'\n\ntype UseDealDataResult = {\n data: DealDetailPayload | null\n setData: React.Dispatch<React.SetStateAction<DealDetailPayload | null>>\n isLoading: boolean\n error: string | null\n isNotFound: boolean\n loadData: () => Promise<void>\n}\n\nexport function useDealData(id: string): UseDealDataResult {\n const t = useT()\n const [data, setData] = React.useState<DealDetailPayload | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n const initialLoadDoneRef = React.useRef(false)\n\n const loadData = React.useCallback(async () => {\n if (!id) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n try {\n const payload = await readApiResultOrThrow<DealDetailPayload>(\n `/api/customers/deals/${encodeURIComponent(id)}?include=stages&view=lite`,\n undefined,\n { errorMessage: t('customers.deals.detail.error.load', 'Failed to load deal.') },\n )\n setData(payload)\n } catch (loadError) {\n if ((loadError as { status?: number }).status === 404) {\n setIsNotFound(true)\n } else {\n const message =\n loadError instanceof Error\n ? loadError.message\n : t('customers.deals.detail.error.load', 'Failed to load deal.')\n setError(message)\n }\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n return { data, setData, isLoading, error, isNotFound, loadData }\n}\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;AACvB,SAAS,4BAA4B;AACrC,SAAS,YAAY;AAYd,SAAS,YAAY,IAA+B;AACzD,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAmC,IAAI;AACrE,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,IAAI;AACrD,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAwB,IAAI;AAC5D,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,KAAK;AACxD,QAAM,qBAAqB,MAAM,OAAO,KAAK;AAE7C,QAAM,WAAW,MAAM,YAAY,YAAY;AAC7C,QAAI,CAAC,IAAI;AACP,oBAAc,IAAI;AAClB,mBAAa,KAAK;AAClB;AAAA,IACF;AACA,QAAI,CAAC,mBAAmB,SAAS;AAC/B,mBAAa,IAAI;AAAA,IACnB;AACA,aAAS,IAAI;AACb,QAAI;AACF,YAAM,UAAU,MAAM;AAAA,QACpB,wBAAwB,mBAAmB,EAAE,CAAC;AAAA,QAC9C;AAAA,QACA,EAAE,cAAc,EAAE,qCAAqC,sBAAsB,EAAE;AAAA,MACjF;AACA,cAAQ,OAAO;AAAA,IACjB,SAAS,WAAW;AAClB,UAAK,UAAkC,WAAW,KAAK;AACrD,sBAAc,IAAI;AAAA,MACpB,OAAO;AACL,cAAM,UACJ,qBAAqB,QACjB,UAAU,UACV,EAAE,qCAAqC,sBAAsB;AACnE,iBAAS,OAAO;AAAA,MAClB;AACA,UAAI,CAAC,mBAAmB,QAAS,SAAQ,IAAI;AAAA,IAC/C,UAAE;AACA,mBAAa,KAAK;AAClB,yBAAmB,UAAU;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,IAAI,CAAC,CAAC;AAEV,SAAO,EAAE,MAAM,SAAS,WAAW,OAAO,YAAY,SAAS;AACjE;",
6
6
  "names": []
7
7
  }
@@ -7,7 +7,7 @@ import { EmptyState } from "@open-mercato/ui/primitives/empty-state";
7
7
  import { useRouter, useSearchParams } from "next/navigation";
8
8
  import { Page, PageBody } from "@open-mercato/ui/backend/Page";
9
9
  import { Button } from "@open-mercato/ui/primitives/button";
10
- import { AttachmentsSection, ErrorMessage, LoadingMessage, NotesSection } from "@open-mercato/ui/backend/detail";
10
+ import { AttachmentsSection, ErrorMessage, LoadingMessage, NotesSection, RecordNotFoundState } from "@open-mercato/ui/backend/detail";
11
11
  import { InjectionSpot } from "@open-mercato/ui/backend/injection/InjectionSpot";
12
12
  import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
13
13
  import { CollapsibleZoneLayout } from "@open-mercato/ui/backend/crud/CollapsibleZoneLayout";
@@ -49,7 +49,7 @@ function DealDetailPage({ params }) {
49
49
  const searchParams = useSearchParams();
50
50
  const { confirm, ConfirmDialogElement } = useConfirmDialog();
51
51
  const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t]);
52
- const { data, setData, isLoading, error, loadData } = useDealData(id);
52
+ const { data, setData, isLoading, error, isNotFound, loadData } = useDealData(id);
53
53
  const [isDirty, setIsDirty] = React.useState(false);
54
54
  const {
55
55
  scheduleDialogOpen,
@@ -254,12 +254,22 @@ function DealDetailPage({ params }) {
254
254
  if (isLoading) {
255
255
  return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(LoadingMessage, { label: t("customers.deals.detail.loading", "Loading deal\u2026") }) }) });
256
256
  }
257
+ if (isNotFound) {
258
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
259
+ RecordNotFoundState,
260
+ {
261
+ label: t("customers.deals.detail.error.notFound", "Deal not found."),
262
+ backHref: "/backend/customers/deals",
263
+ backLabel: t("customers.deals.detail.actions.backToList", "Back to deals")
264
+ }
265
+ ) }) });
266
+ }
257
267
  if (error || !data) {
258
268
  return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
259
269
  ErrorMessage,
260
270
  {
261
- label: error || t("customers.deals.detail.error.notFound", "Deal not found."),
262
- action: /* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", children: /* @__PURE__ */ jsx(Link, { href: "/backend/customers/deals", children: t("customers.deals.detail.actions.backToList", "Back to deals") }) })
271
+ label: error ?? t("customers.deals.detail.error.load", "Failed to load deal."),
272
+ action: /* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", size: "sm", children: /* @__PURE__ */ jsx(Link, { href: "/backend/customers/deals", children: t("customers.deals.detail.actions.backToList", "Back to deals") }) })
263
273
  }
264
274
  ) }) });
265
275
  }