@open-mercato/core 0.5.1-develop.2975.ccbadc8198 → 0.5.1-develop.2996.ce62fd491c
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/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities/sidebar_variant/index.js +25 -0
- package/dist/generated/entities/sidebar_variant/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +1 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +13 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/authUi.js +1 -1
- package/dist/helpers/integration/authUi.js.map +2 -2
- package/dist/modules/audit_logs/services/actionLogService.js +4 -5
- package/dist/modules/audit_logs/services/actionLogService.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +224 -35
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +3 -3
- package/dist/modules/auth/api/sidebar/variants/[id]/route.js +161 -0
- package/dist/modules/auth/api/sidebar/variants/[id]/route.js.map +7 -0
- package/dist/modules/auth/api/sidebar/variants/route.js +142 -0
- package/dist/modules/auth/api/sidebar/variants/route.js.map +7 -0
- package/dist/modules/auth/backend/sidebar-customization/page.js +16 -0
- package/dist/modules/auth/backend/sidebar-customization/page.js.map +7 -0
- package/dist/modules/auth/backend/sidebar-customization/page.meta.js +28 -0
- package/dist/modules/auth/backend/sidebar-customization/page.meta.js.map +7 -0
- package/dist/modules/auth/data/entities.js +45 -4
- package/dist/modules/auth/data/entities.js.map +2 -2
- package/dist/modules/auth/data/validators.js +63 -1
- package/dist/modules/auth/data/validators.js.map +2 -2
- package/dist/modules/auth/migrations/Migration20260427081815.js +15 -0
- package/dist/modules/auth/migrations/Migration20260427081815.js.map +7 -0
- package/dist/modules/auth/migrations/Migration20260427124900.js +15 -0
- package/dist/modules/auth/migrations/Migration20260427124900.js.map +7 -0
- package/dist/modules/auth/migrations/Migration20260427143311.js +72 -0
- package/dist/modules/auth/migrations/Migration20260427143311.js.map +7 -0
- package/dist/modules/auth/services/sidebarPreferencesService.js +176 -16
- package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/[id]/page.js +3 -1
- package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +4 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +8 -3
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js +3 -2
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
- package/dist/modules/customers/components/formConfig.js +3 -3
- package/dist/modules/customers/components/formConfig.js.map +2 -2
- package/dist/modules/customers/lib/displayName.js +12 -0
- package/dist/modules/customers/lib/displayName.js.map +2 -2
- package/dist/modules/entities/cli.js +5 -6
- package/dist/modules/entities/cli.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/reset-password/page.js +124 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/reset-password/page.js.map +7 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/reset-password/page.meta.js +11 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/reset-password/page.meta.js.map +7 -0
- package/generated/entities/sidebar_variant/index.ts +11 -0
- package/generated/entities.ids.generated.ts +1 -0
- package/generated/entity-fields-registry.ts +13 -0
- package/package.json +6 -6
- package/src/helpers/integration/authUi.ts +1 -1
- package/src/modules/audit_logs/services/actionLogService.ts +5 -6
- package/src/modules/auth/api/sidebar/preferences/route.ts +266 -34
- package/src/modules/auth/api/sidebar/variants/[id]/route.ts +183 -0
- package/src/modules/auth/api/sidebar/variants/route.ts +157 -0
- package/src/modules/auth/backend/sidebar-customization/page.meta.ts +34 -0
- package/src/modules/auth/backend/sidebar-customization/page.tsx +17 -0
- package/src/modules/auth/data/entities.ts +48 -2
- package/src/modules/auth/data/validators.ts +70 -0
- package/src/modules/auth/migrations/.snapshot-open-mercato.json +790 -71
- package/src/modules/auth/migrations/Migration20260427081815.ts +16 -0
- package/src/modules/auth/migrations/Migration20260427124900.ts +19 -0
- package/src/modules/auth/migrations/Migration20260427143311.ts +83 -0
- package/src/modules/auth/services/sidebarPreferencesService.ts +243 -18
- package/src/modules/customers/backend/customers/companies/[id]/page.tsx +5 -4
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +6 -5
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +13 -9
- package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +3 -2
- package/src/modules/customers/components/formConfig.tsx +3 -3
- package/src/modules/customers/lib/displayName.ts +21 -0
- package/src/modules/entities/cli.ts +5 -6
- package/src/modules/portal/frontend/[orgSlug]/portal/reset-password/page.meta.ts +9 -0
- package/src/modules/portal/frontend/[orgSlug]/portal/reset-password/page.tsx +168 -0
- package/src/modules/portal/i18n/de.json +20 -0
- package/src/modules/portal/i18n/en.json +20 -0
- package/src/modules/portal/i18n/es.json +20 -0
- package/src/modules/portal/i18n/pl.json +20 -0
|
@@ -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 { 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 companyName =\n data?.company?.displayName && data.company.displayName.trim().length\n ? data.company.displayName\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 { 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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",
|
|
6
6
|
"names": ["params", "id", "companyId", "error"]
|
|
7
7
|
}
|
|
@@ -23,6 +23,7 @@ import { useOrganizationScopeDetail } from "@open-mercato/shared/lib/frontend/us
|
|
|
23
23
|
import { DealsSection } from "../../../../components/detail/DealsSection.js";
|
|
24
24
|
import { ActivityLogTab } from "../../../../components/detail/ActivityLogTab.js";
|
|
25
25
|
import { CompanyPeopleSection } from "../../../../components/detail/CompanyPeopleSection.js";
|
|
26
|
+
import { coerceDisplayName } from "../../../../lib/displayName.js";
|
|
26
27
|
import { CompanyDetailHeader } from "../../../../components/detail/CompanyDetailHeader.js";
|
|
27
28
|
import { CompanyDetailTabs, resolveLegacyTab } from "../../../../components/detail/CompanyDetailTabs.js";
|
|
28
29
|
import { CompanyKpiBar } from "../../../../components/detail/CompanyKpiBar.js";
|
|
@@ -83,7 +84,8 @@ function CompanyDetailV2Page({ params }) {
|
|
|
83
84
|
contextId: mutationContextId,
|
|
84
85
|
blockedMessage: t("ui.forms.flash.saveBlocked", "Save blocked by validation")
|
|
85
86
|
});
|
|
86
|
-
const
|
|
87
|
+
const companyDisplayName = coerceDisplayName(data?.company?.displayName);
|
|
88
|
+
const companyName = companyDisplayName.trim().length ? companyDisplayName : t("customers.companies.list.deleteFallbackName", "this company");
|
|
87
89
|
const initialLoadDoneRef = React.useRef(false);
|
|
88
90
|
const loadData = React.useCallback(async () => {
|
|
89
91
|
if (!id) {
|
|
@@ -341,7 +343,7 @@ function CompanyDetailV2Page({ params }) {
|
|
|
341
343
|
CompanyPeopleSection,
|
|
342
344
|
{
|
|
343
345
|
companyId,
|
|
344
|
-
companyName:
|
|
346
|
+
companyName: companyDisplayName,
|
|
345
347
|
initialPeople: [],
|
|
346
348
|
addActionLabel: t("customers.companies.detail.people.add", "Add person"),
|
|
347
349
|
emptyLabel: t("customers.companies.detail.people.empty", "No people linked to this company yet."),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/customers/backend/customers/companies-v2/%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 { Building2, Hash, Users, BarChart3, StickyNote } from 'lucide-react'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { CollapsibleZoneLayout, type ZoneSectionDescriptor } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { ActivityLogTab } from '../../../../components/detail/ActivityLogTab'\nimport { CompanyPeopleSection, type CompanyPersonSummary } from '../../../../components/detail/CompanyPeopleSection'\nimport type { TagSummary } from '../../../../components/detail/types'\nimport type { TagsSectionController } from '@open-mercato/ui/backend/detail'\nimport { CompanyDetailHeader } from '../../../../components/detail/CompanyDetailHeader'\nimport { CompanyDetailTabs, resolveLegacyTab, type CompanyTabId } from '../../../../components/detail/CompanyDetailTabs'\nimport { CompanyKpiBar } from '../../../../components/detail/CompanyKpiBar'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { useInteractionMutations } from '../../../../components/detail/hooks/useInteractionMutations'\nimport {\n buildCompanyEditPayload,\n createCompanyEditFields,\n createCompanyDaneFiremyGroups,\n createCompanyEditSchema,\n mapCompanyOverviewToFormValues,\n type CompanyEditFormValues,\n type CompanyOverview,\n} from '../../../../components/formConfig'\n\nexport default function CompanyDetailV2Page({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n\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\n // Tab state\n const initialTab = React.useMemo(() => {\n return resolveLegacyTab(searchParams?.get('tab'))\n }, [searchParams])\n const [activeTab, setActiveTab] = React.useState<CompanyTabId>(initialTab)\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n\n // Form state\n const [isDirty, setIsDirty] = React.useState(false)\n const [isSaving, setIsSaving] = React.useState(false)\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n const { organizationId } = useOrganizationScopeDetail()\n const formSchema = React.useMemo(() => createCompanyEditSchema(), [])\n const formFields = React.useMemo(() => createCompanyEditFields(t), [t])\n const formGroups = React.useMemo(() => createCompanyDaneFiremyGroups(t), [t])\n const initialValues = React.useMemo(\n () => (data ? mapCompanyOverviewToFormValues(data) : undefined),\n [data],\n )\n const zoneSections = React.useMemo<ZoneSectionDescriptor[]>(() => [\n { id: 'identity', icon: Building2, label: t('customers.companies.form.sections.identity', 'Identity') },\n { id: 'contact', icon: Hash, label: t('customers.companies.form.sections.contact', 'Contact') },\n { id: 'classification', icon: Users, label: t('customers.companies.form.sections.classification', 'Classification') },\n { id: 'businessProfile', icon: BarChart3, label: t('customers.companies.form.sections.businessProfile', 'Business profile') },\n { id: 'notes', icon: StickyNote, label: t('customers.companies.form.groups.notes', 'Notes') },\n { id: 'customFields', icon: Hash, label: t('customers.companies.form.groups.customAttributes', 'Custom attributes') },\n ], [t])\n const [scheduleDialogOpen, setScheduleDialogOpen] = React.useState(false)\n const [scheduleEditData, setScheduleEditData] = React.useState<ScheduleActivityEditData | null>(null)\n const [activityRefreshKey, setActivityRefreshKey] = React.useState(0)\n const [dealCount, setDealCount] = React.useState(0)\n\n const currentCompanyId = data?.company?.id ?? null\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\n const companyName =\n data?.company?.displayName && data.company.displayName.trim().length\n ? data.company.displayName\n : t('customers.companies.list.deleteFallbackName', 'this company')\n\n // Data loading\n const initialLoadDoneRef = React.useRef(false)\n const loadData = React.useCallback(async () => {\n if (!id) {\n setError(t('customers.companies.detail.error.notFound', 'Company 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<CompanyOverview>(\n `/api/customers/companies/${encodeURIComponent(id)}`,\n undefined,\n { errorMessage: t('customers.companies.detail.error.load', 'Failed to load company.') },\n )\n setData(payload as CompanyOverview)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.companies.detail.error.load', 'Failed to load company.')\n setError(message)\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch((err) => console.warn('[companies-v2] loadData failed', err))\n }, [loadData])\n\n React.useEffect(() => {\n setDealCount(data?.counts?.deals ?? 0)\n }, [data?.counts?.deals])\n\n const handleActivityCreated = React.useCallback(() => {\n setActivityRefreshKey((k) => k + 1)\n loadData().catch((err) => console.warn('[companies-v2] reload after activity failed', err))\n }, [loadData])\n\n // Planned activities for the activity-log tab\n const plannedActivities = React.useMemo(() => {\n return data?.plannedActivitiesPreview ?? []\n }, [data?.plannedActivitiesPreview])\n\n // Injection context for UMES\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 { completeInteraction: handleMarkDone, cancelInteraction: handleCancelActivity } = useInteractionMutations({\n runMutationWithContext,\n onAfterChange: handleActivityCreated,\n logContext: 'customers.companies-v2',\n })\n\n const handleEditActivity = React.useCallback((activity: { id: string; interactionType?: string; title?: string | null; body?: string | null; scheduledAt?: string | null; [key: string]: unknown }) => {\n const raw = activity as Record<string, unknown>\n const durationValue = typeof raw.duration === 'number'\n ? raw.duration\n : typeof raw.durationMinutes === 'number'\n ? raw.durationMinutes as number\n : null\n setScheduleEditData({\n id: activity.id,\n interactionType: typeof activity.interactionType === 'string' ? activity.interactionType : undefined,\n title: typeof activity.title === 'string' ? activity.title : null,\n body: typeof activity.body === 'string' ? activity.body : null,\n scheduledAt: typeof activity.scheduledAt === 'string' ? activity.scheduledAt : null,\n durationMinutes: durationValue,\n location: typeof raw.location === 'string' ? raw.location as string : null,\n allDay: typeof raw.allDay === 'boolean' ? raw.allDay as boolean : null,\n recurrenceRule: typeof raw.recurrenceRule === 'string' ? raw.recurrenceRule as string : null,\n recurrenceEnd: typeof raw.recurrenceEnd === 'string' ? raw.recurrenceEnd as string : null,\n participants: Array.isArray(raw.participants) ? raw.participants as ScheduleActivityEditData['participants'] : null,\n reminderMinutes: typeof raw.reminderMinutes === 'number' ? raw.reminderMinutes as number : null,\n visibility: typeof raw.visibility === 'string' ? raw.visibility as string : null,\n linkedEntities: Array.isArray(raw.linkedEntities) ? raw.linkedEntities as ScheduleActivityEditData['linkedEntities'] : null,\n guestPermissions: raw.guestPermissions && typeof raw.guestPermissions === 'object'\n ? raw.guestPermissions as ScheduleActivityEditData['guestPermissions']\n : null,\n })\n setScheduleDialogOpen(true)\n }, [])\n\n const openNewScheduleDialog = React.useCallback(() => {\n setScheduleEditData(null)\n setScheduleDialogOpen(true)\n }, [])\n\n // Injected tabs from UMES\n const { widgets: injectedTabWidgets } = useInjectionWidgets('detail:customers.company:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const tabId = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel ?? widget.module.metadata.title ?? tabId\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: unknown) => setData(next as CompanyOverview)}\n />\n )\n return { id: tabId, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext],\n )\n\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n // Tags\n const handleTagsChange = React.useCallback((nextTags: TagSummary[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n const tagsSectionControllerRef = React.useRef<TagsSectionController | null>(null)\n\n // Section action (for tabs that expose add/create buttons)\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction((prev) => (action !== null ? action : prev))\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 // Deals scope\n const dealsScope = React.useMemo(\n () => (currentCompanyId ? ({ kind: 'company', entityId: currentCompanyId } as const) : null),\n [currentCompanyId],\n )\n\n // Delete handler (shared between header and form)\n const handleDelete = React.useCallback(async () => {\n const companyId = data?.company?.id ?? ''\n if (!companyId) return\n const approved = await confirm({\n title: t('customers.companies.detail.deleteConfirmTitle', 'Delete company?'),\n description: t('customers.companies.detail.deleteConfirmDescription', 'This action cannot be undone.'),\n confirmText: t('customers.companies.detail.actions.delete', 'Delete company'),\n cancelText: t('customers.companies.detail.actions.cancel', 'Cancel'),\n variant: 'destructive',\n })\n if (!approved) return\n await runMutationWithContext(\n () => deleteCrud('customers/companies', { id: companyId }),\n { id: companyId, operation: 'deleteCompany' },\n )\n flash(t('customers.companies.list.deleteSuccess', 'Company deleted.'), 'success')\n router.push('/backend/customers/companies')\n }, [confirm, data?.company?.id, router, runMutationWithContext, t])\n\n // Form submit handler (lifted from CompanyDataTab)\n const handleFormSubmit = React.useCallback(\n async (values: CompanyEditFormValues) => {\n setIsSaving(true)\n try {\n let payload: Record<string, unknown>\n try {\n payload = buildCompanyEditPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error) {\n if (err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.companies.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n if (err.message === 'ANNUAL_REVENUE_INVALID') {\n const message = t('customers.companies.form.annualRevenue.error')\n throw createCrudFormError(message, { annualRevenue: message })\n }\n }\n throw err\n }\n await updateCrud('customers/companies', payload)\n flash(t('customers.companies.form.updateSuccess', 'Company updated.'), 'success')\n await loadData()\n } finally {\n setIsSaving(false)\n }\n },\n [loadData, organizationId, t],\n )\n\n // Save handler (triggers form submit via ref)\n const handleHeaderSave = React.useCallback(() => {\n const form = formWrapperRef.current?.querySelector('form')\n if (form) form.requestSubmit()\n }, [])\n\n // Loading / error states\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.companies.detail.loading', 'Loading company\u2026')} />\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\">\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 companyId = data.company.id\n const useCanonicalInteractions = data.interactionMode === 'canonical'\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n {/* UMES header injection */}\n <InjectionSpot spotId=\"detail:customers.company:header\" context={injectionContext} data={data} />\n <InjectionSpot spotId=\"detail:customers.company:status-badges\" context={injectionContext} data={data} />\n\n {/* Persistent company header */}\n <CompanyDetailHeader\n data={data}\n onTagsChange={handleTagsChange}\n tagsSectionControllerRef={tagsSectionControllerRef}\n onSave={handleHeaderSave}\n onDelete={handleDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n onDataReload={() => { loadData().catch((err) => console.warn('[companies-v2] onDataReload failed', err)) }}\n />\n\n {/* KPI bar \u2014 always visible above zones */}\n <CompanyKpiBar data={data} />\n\n {/* Two-zone layout: zone1 = form, zone2 = tabs */}\n <CollapsibleZoneLayout\n pageType=\"company-v2\"\n entityName={companyName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1={\n <div ref={formWrapperRef}>\n <CrudForm<CompanyEditFormValues>\n embedded\n trackDirtyWhenEmbedded\n injectionSpotId=\"customers.company\"\n entityIds={[E.customers.customer_entity, E.customers.customer_company_profile]}\n schema={formSchema}\n fields={formFields}\n groups={formGroups}\n initialValues={initialValues}\n onSubmit={handleFormSubmit}\n onDelete={handleDelete}\n hideFooterActions\n collapsibleGroups={{ pageType: 'company-v2', chevronPosition: 'left' }}\n sortableGroups={{ pageType: 'company-v2' }}\n onDirtyChange={setIsDirty}\n />\n </div>\n }\n zone2={\n <CompanyDetailTabs\n activeTab={activeTab}\n onTabChange={setActiveTab}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n peopleCount={data.counts?.people ?? 0}\n dealsCount={dealCount}\n activitiesCount={data.counts?.activities ?? 0}\n sectionAction={sectionAction}\n >\n {activeTab === 'people' && (\n <CompanyPeopleSection\n companyId={companyId}\n companyName={data.company?.displayName ?? ''}\n initialPeople={[]}\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 translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n onPeopleChange={(next) => {\n setData((prev) => {\n if (!prev) return prev\n const nextCount = next.length\n return {\n ...prev,\n people: next,\n counts: prev.counts ? { ...prev.counts, people: nextCount } : prev.counts,\n }\n })\n }}\n />\n )}\n\n {activeTab === 'deals' && (\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 translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n onCountDelta={(delta) => setDealCount((current) => Math.max(0, current + delta))}\n />\n )}\n\n {activeTab === 'activity-log' && (\n <ActivityLogTab\n entityId={companyId}\n plannedActivities={plannedActivities}\n onActivityCreated={handleActivityCreated}\n onScheduleRequested={openNewScheduleDialog}\n onMarkDone={handleMarkDone}\n onEditActivity={handleEditActivity}\n onCancelActivity={handleCancelActivity}\n runGuardedMutation={runMutationWithContext}\n refreshKey={activityRefreshKey}\n useCanonicalInteractions={useCanonicalInteractions}\n />\n )}\n\n {activeTab === 'changelog' && companyId && (\n <ChangelogTab entityId={companyId} entityType=\"company\" />\n )}\n\n {activeTab === 'files' && (\n <AttachmentsSection\n entityId={E.customers.customer_entity}\n recordId={companyId}\n title={t('customers.companies.detail.tabs.files', 'Files')}\n description={t('customers.companies.detail.files.subtitle', 'Upload and manage files linked to this company.')}\n />\n )}\n\n {/* Injected tabs from UMES */}\n {injectedTabMap.has(activeTab) && injectedTabMap.get(activeTab)!()}\n </CompanyDetailTabs>\n }\n />\n\n {/* UMES footer injection */}\n <InjectionSpot spotId=\"detail:customers.company:footer\" context={injectionContext} data={data} />\n\n {/* Schedule Activity Dialog */}\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={() => { setScheduleDialogOpen(false); setScheduleEditData(null) }}\n entityId={companyId}\n entityName={companyName}\n entityType=\"company\"\n onActivityCreated={handleActivityCreated}\n editData={scheduleEditData}\n />\n {ConfirmDialogElement}\n </div>\n </PageBody>\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 { Building2, Hash, Users, BarChart3, StickyNote } from 'lucide-react'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { CollapsibleZoneLayout, type ZoneSectionDescriptor } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { ActivityLogTab } from '../../../../components/detail/ActivityLogTab'\nimport { CompanyPeopleSection, type CompanyPersonSummary } from '../../../../components/detail/CompanyPeopleSection'\nimport type { TagSummary } from '../../../../components/detail/types'\nimport type { TagsSectionController } from '@open-mercato/ui/backend/detail'\nimport { coerceDisplayName } from '../../../../lib/displayName'\nimport { CompanyDetailHeader } from '../../../../components/detail/CompanyDetailHeader'\nimport { CompanyDetailTabs, resolveLegacyTab, type CompanyTabId } from '../../../../components/detail/CompanyDetailTabs'\nimport { CompanyKpiBar } from '../../../../components/detail/CompanyKpiBar'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { useInteractionMutations } from '../../../../components/detail/hooks/useInteractionMutations'\nimport {\n buildCompanyEditPayload,\n createCompanyEditFields,\n createCompanyDaneFiremyGroups,\n createCompanyEditSchema,\n mapCompanyOverviewToFormValues,\n type CompanyEditFormValues,\n type CompanyOverview,\n} from '../../../../components/formConfig'\n\nexport default function CompanyDetailV2Page({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n\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\n // Tab state\n const initialTab = React.useMemo(() => {\n return resolveLegacyTab(searchParams?.get('tab'))\n }, [searchParams])\n const [activeTab, setActiveTab] = React.useState<CompanyTabId>(initialTab)\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n\n // Form state\n const [isDirty, setIsDirty] = React.useState(false)\n const [isSaving, setIsSaving] = React.useState(false)\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n const { organizationId } = useOrganizationScopeDetail()\n const formSchema = React.useMemo(() => createCompanyEditSchema(), [])\n const formFields = React.useMemo(() => createCompanyEditFields(t), [t])\n const formGroups = React.useMemo(() => createCompanyDaneFiremyGroups(t), [t])\n const initialValues = React.useMemo(\n () => (data ? mapCompanyOverviewToFormValues(data) : undefined),\n [data],\n )\n const zoneSections = React.useMemo<ZoneSectionDescriptor[]>(() => [\n { id: 'identity', icon: Building2, label: t('customers.companies.form.sections.identity', 'Identity') },\n { id: 'contact', icon: Hash, label: t('customers.companies.form.sections.contact', 'Contact') },\n { id: 'classification', icon: Users, label: t('customers.companies.form.sections.classification', 'Classification') },\n { id: 'businessProfile', icon: BarChart3, label: t('customers.companies.form.sections.businessProfile', 'Business profile') },\n { id: 'notes', icon: StickyNote, label: t('customers.companies.form.groups.notes', 'Notes') },\n { id: 'customFields', icon: Hash, label: t('customers.companies.form.groups.customAttributes', 'Custom attributes') },\n ], [t])\n const [scheduleDialogOpen, setScheduleDialogOpen] = React.useState(false)\n const [scheduleEditData, setScheduleEditData] = React.useState<ScheduleActivityEditData | null>(null)\n const [activityRefreshKey, setActivityRefreshKey] = React.useState(0)\n const [dealCount, setDealCount] = React.useState(0)\n\n const currentCompanyId = data?.company?.id ?? null\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\n const companyDisplayName = coerceDisplayName(data?.company?.displayName)\n const companyName = companyDisplayName.trim().length\n ? companyDisplayName\n : t('customers.companies.list.deleteFallbackName', 'this company')\n\n // Data loading\n const initialLoadDoneRef = React.useRef(false)\n const loadData = React.useCallback(async () => {\n if (!id) {\n setError(t('customers.companies.detail.error.notFound', 'Company 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<CompanyOverview>(\n `/api/customers/companies/${encodeURIComponent(id)}`,\n undefined,\n { errorMessage: t('customers.companies.detail.error.load', 'Failed to load company.') },\n )\n setData(payload as CompanyOverview)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.companies.detail.error.load', 'Failed to load company.')\n setError(message)\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch((err) => console.warn('[companies-v2] loadData failed', err))\n }, [loadData])\n\n React.useEffect(() => {\n setDealCount(data?.counts?.deals ?? 0)\n }, [data?.counts?.deals])\n\n const handleActivityCreated = React.useCallback(() => {\n setActivityRefreshKey((k) => k + 1)\n loadData().catch((err) => console.warn('[companies-v2] reload after activity failed', err))\n }, [loadData])\n\n // Planned activities for the activity-log tab\n const plannedActivities = React.useMemo(() => {\n return data?.plannedActivitiesPreview ?? []\n }, [data?.plannedActivitiesPreview])\n\n // Injection context for UMES\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 { completeInteraction: handleMarkDone, cancelInteraction: handleCancelActivity } = useInteractionMutations({\n runMutationWithContext,\n onAfterChange: handleActivityCreated,\n logContext: 'customers.companies-v2',\n })\n\n const handleEditActivity = React.useCallback((activity: { id: string; interactionType?: string; title?: string | null; body?: string | null; scheduledAt?: string | null; [key: string]: unknown }) => {\n const raw = activity as Record<string, unknown>\n const durationValue = typeof raw.duration === 'number'\n ? raw.duration\n : typeof raw.durationMinutes === 'number'\n ? raw.durationMinutes as number\n : null\n setScheduleEditData({\n id: activity.id,\n interactionType: typeof activity.interactionType === 'string' ? activity.interactionType : undefined,\n title: typeof activity.title === 'string' ? activity.title : null,\n body: typeof activity.body === 'string' ? activity.body : null,\n scheduledAt: typeof activity.scheduledAt === 'string' ? activity.scheduledAt : null,\n durationMinutes: durationValue,\n location: typeof raw.location === 'string' ? raw.location as string : null,\n allDay: typeof raw.allDay === 'boolean' ? raw.allDay as boolean : null,\n recurrenceRule: typeof raw.recurrenceRule === 'string' ? raw.recurrenceRule as string : null,\n recurrenceEnd: typeof raw.recurrenceEnd === 'string' ? raw.recurrenceEnd as string : null,\n participants: Array.isArray(raw.participants) ? raw.participants as ScheduleActivityEditData['participants'] : null,\n reminderMinutes: typeof raw.reminderMinutes === 'number' ? raw.reminderMinutes as number : null,\n visibility: typeof raw.visibility === 'string' ? raw.visibility as string : null,\n linkedEntities: Array.isArray(raw.linkedEntities) ? raw.linkedEntities as ScheduleActivityEditData['linkedEntities'] : null,\n guestPermissions: raw.guestPermissions && typeof raw.guestPermissions === 'object'\n ? raw.guestPermissions as ScheduleActivityEditData['guestPermissions']\n : null,\n })\n setScheduleDialogOpen(true)\n }, [])\n\n const openNewScheduleDialog = React.useCallback(() => {\n setScheduleEditData(null)\n setScheduleDialogOpen(true)\n }, [])\n\n // Injected tabs from UMES\n const { widgets: injectedTabWidgets } = useInjectionWidgets('detail:customers.company:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const tabId = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel ?? widget.module.metadata.title ?? tabId\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: unknown) => setData(next as CompanyOverview)}\n />\n )\n return { id: tabId, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext],\n )\n\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n // Tags\n const handleTagsChange = React.useCallback((nextTags: TagSummary[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n const tagsSectionControllerRef = React.useRef<TagsSectionController | null>(null)\n\n // Section action (for tabs that expose add/create buttons)\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction((prev) => (action !== null ? action : prev))\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 // Deals scope\n const dealsScope = React.useMemo(\n () => (currentCompanyId ? ({ kind: 'company', entityId: currentCompanyId } as const) : null),\n [currentCompanyId],\n )\n\n // Delete handler (shared between header and form)\n const handleDelete = React.useCallback(async () => {\n const companyId = data?.company?.id ?? ''\n if (!companyId) return\n const approved = await confirm({\n title: t('customers.companies.detail.deleteConfirmTitle', 'Delete company?'),\n description: t('customers.companies.detail.deleteConfirmDescription', 'This action cannot be undone.'),\n confirmText: t('customers.companies.detail.actions.delete', 'Delete company'),\n cancelText: t('customers.companies.detail.actions.cancel', 'Cancel'),\n variant: 'destructive',\n })\n if (!approved) return\n await runMutationWithContext(\n () => deleteCrud('customers/companies', { id: companyId }),\n { id: companyId, operation: 'deleteCompany' },\n )\n flash(t('customers.companies.list.deleteSuccess', 'Company deleted.'), 'success')\n router.push('/backend/customers/companies')\n }, [confirm, data?.company?.id, router, runMutationWithContext, t])\n\n // Form submit handler (lifted from CompanyDataTab)\n const handleFormSubmit = React.useCallback(\n async (values: CompanyEditFormValues) => {\n setIsSaving(true)\n try {\n let payload: Record<string, unknown>\n try {\n payload = buildCompanyEditPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error) {\n if (err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.companies.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n if (err.message === 'ANNUAL_REVENUE_INVALID') {\n const message = t('customers.companies.form.annualRevenue.error')\n throw createCrudFormError(message, { annualRevenue: message })\n }\n }\n throw err\n }\n await updateCrud('customers/companies', payload)\n flash(t('customers.companies.form.updateSuccess', 'Company updated.'), 'success')\n await loadData()\n } finally {\n setIsSaving(false)\n }\n },\n [loadData, organizationId, t],\n )\n\n // Save handler (triggers form submit via ref)\n const handleHeaderSave = React.useCallback(() => {\n const form = formWrapperRef.current?.querySelector('form')\n if (form) form.requestSubmit()\n }, [])\n\n // Loading / error states\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.companies.detail.loading', 'Loading company\u2026')} />\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\">\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 companyId = data.company.id\n const useCanonicalInteractions = data.interactionMode === 'canonical'\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n {/* UMES header injection */}\n <InjectionSpot spotId=\"detail:customers.company:header\" context={injectionContext} data={data} />\n <InjectionSpot spotId=\"detail:customers.company:status-badges\" context={injectionContext} data={data} />\n\n {/* Persistent company header */}\n <CompanyDetailHeader\n data={data}\n onTagsChange={handleTagsChange}\n tagsSectionControllerRef={tagsSectionControllerRef}\n onSave={handleHeaderSave}\n onDelete={handleDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n onDataReload={() => { loadData().catch((err) => console.warn('[companies-v2] onDataReload failed', err)) }}\n />\n\n {/* KPI bar \u2014 always visible above zones */}\n <CompanyKpiBar data={data} />\n\n {/* Two-zone layout: zone1 = form, zone2 = tabs */}\n <CollapsibleZoneLayout\n pageType=\"company-v2\"\n entityName={companyName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1={\n <div ref={formWrapperRef}>\n <CrudForm<CompanyEditFormValues>\n embedded\n trackDirtyWhenEmbedded\n injectionSpotId=\"customers.company\"\n entityIds={[E.customers.customer_entity, E.customers.customer_company_profile]}\n schema={formSchema}\n fields={formFields}\n groups={formGroups}\n initialValues={initialValues}\n onSubmit={handleFormSubmit}\n onDelete={handleDelete}\n hideFooterActions\n collapsibleGroups={{ pageType: 'company-v2', chevronPosition: 'left' }}\n sortableGroups={{ pageType: 'company-v2' }}\n onDirtyChange={setIsDirty}\n />\n </div>\n }\n zone2={\n <CompanyDetailTabs\n activeTab={activeTab}\n onTabChange={setActiveTab}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n peopleCount={data.counts?.people ?? 0}\n dealsCount={dealCount}\n activitiesCount={data.counts?.activities ?? 0}\n sectionAction={sectionAction}\n >\n {activeTab === 'people' && (\n <CompanyPeopleSection\n companyId={companyId}\n companyName={companyDisplayName}\n initialPeople={[]}\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 translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n onPeopleChange={(next) => {\n setData((prev) => {\n if (!prev) return prev\n const nextCount = next.length\n return {\n ...prev,\n people: next,\n counts: prev.counts ? { ...prev.counts, people: nextCount } : prev.counts,\n }\n })\n }}\n />\n )}\n\n {activeTab === 'deals' && (\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 translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n onCountDelta={(delta) => setDealCount((current) => Math.max(0, current + delta))}\n />\n )}\n\n {activeTab === 'activity-log' && (\n <ActivityLogTab\n entityId={companyId}\n plannedActivities={plannedActivities}\n onActivityCreated={handleActivityCreated}\n onScheduleRequested={openNewScheduleDialog}\n onMarkDone={handleMarkDone}\n onEditActivity={handleEditActivity}\n onCancelActivity={handleCancelActivity}\n runGuardedMutation={runMutationWithContext}\n refreshKey={activityRefreshKey}\n useCanonicalInteractions={useCanonicalInteractions}\n />\n )}\n\n {activeTab === 'changelog' && companyId && (\n <ChangelogTab entityId={companyId} entityType=\"company\" />\n )}\n\n {activeTab === 'files' && (\n <AttachmentsSection\n entityId={E.customers.customer_entity}\n recordId={companyId}\n title={t('customers.companies.detail.tabs.files', 'Files')}\n description={t('customers.companies.detail.files.subtitle', 'Upload and manage files linked to this company.')}\n />\n )}\n\n {/* Injected tabs from UMES */}\n {injectedTabMap.has(activeTab) && injectedTabMap.get(activeTab)!()}\n </CompanyDetailTabs>\n }\n />\n\n {/* UMES footer injection */}\n <InjectionSpot spotId=\"detail:customers.company:footer\" context={injectionContext} data={data} />\n\n {/* Schedule Activity Dialog */}\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={() => { setScheduleDialogOpen(false); setScheduleEditData(null) }}\n entityId={companyId}\n entityName={companyName}\n entityType=\"company\"\n onActivityCreated={handleActivityCreated}\n editData={scheduleEditData}\n />\n {ConfirmDialogElement}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["companyId"]
|
|
7
7
|
}
|
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
createPersonEditSchema,
|
|
40
40
|
mapPersonOverviewToFormValues
|
|
41
41
|
} from "../../../../components/formConfig.js";
|
|
42
|
+
import { coerceDisplayName, coerceDisplayNameOrNull } from "../../../../lib/displayName.js";
|
|
42
43
|
function PersonDetailV2Page({ params }) {
|
|
43
44
|
const id = params?.id;
|
|
44
45
|
const t = useT();
|
|
@@ -73,8 +74,12 @@ function PersonDetailV2Page({ params }) {
|
|
|
73
74
|
contextId: mutationContextId,
|
|
74
75
|
blockedMessage: t("ui.forms.flash.saveBlocked", "Save blocked by validation")
|
|
75
76
|
});
|
|
76
|
-
const
|
|
77
|
-
const
|
|
77
|
+
const personDisplayName = coerceDisplayName(data?.person?.displayName);
|
|
78
|
+
const personName = personDisplayName.trim().length ? personDisplayName : t("customers.people.list.deleteFallbackName", "this person");
|
|
79
|
+
const personDisplayNameForGroups = personDisplayName.trim().length ? personDisplayName.trim() : null;
|
|
80
|
+
const scheduleDialogCompanyName = coerceDisplayNameOrNull(
|
|
81
|
+
data?.company?.displayName ?? data?.companies?.[0]?.displayName ?? null
|
|
82
|
+
);
|
|
78
83
|
const groups = React.useMemo(
|
|
79
84
|
() => createPersonPersonalDataGroups(t, { entityName: personDisplayNameForGroups }),
|
|
80
85
|
[t, personDisplayNameForGroups]
|
|
@@ -490,7 +495,7 @@ function PersonDetailV2Page({ params }) {
|
|
|
490
495
|
},
|
|
491
496
|
entityId: personId,
|
|
492
497
|
entityName: personName,
|
|
493
|
-
companyName:
|
|
498
|
+
companyName: scheduleDialogCompanyName,
|
|
494
499
|
entityType: "person",
|
|
495
500
|
onActivityCreated: handleActivityCreated,
|
|
496
501
|
editData: scheduleEditData
|