@open-mercato/core 0.10.1-develop.7772.1.9d3d6ce261 → 0.10.1-develop.7774.1.9a13ef7580

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/customers/ai-tools.js.map +2 -2
  3. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +1 -1
  4. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  5. package/dist/modules/customers/backend/customers/deals/[id]/page.js +1 -1
  6. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  7. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +1 -1
  8. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  9. package/dist/modules/customers/components/detail/CompanyDetailTabs.js +3 -2
  10. package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
  11. package/dist/modules/customers/components/detail/DealDetailTabs.js +3 -2
  12. package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
  13. package/dist/modules/customers/components/detail/PersonDetailTabs.js +3 -2
  14. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  15. package/dist/modules/sales/api/documents/factory.js +1 -1
  16. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  17. package/dist/modules/sales/api/orders/route.js +5 -4
  18. package/dist/modules/sales/api/orders/route.js.map +2 -2
  19. package/dist/modules/sales/api/quotes/route.js +5 -4
  20. package/dist/modules/sales/api/quotes/route.js.map +2 -2
  21. package/dist/modules/sales/backend/sales/documents/[id]/page.js +23 -1
  22. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  23. package/dist/modules/sales/components/documents/SalesDocumentExtensionSpot.js +26 -0
  24. package/dist/modules/sales/components/documents/SalesDocumentExtensionSpot.js.map +7 -0
  25. package/dist/modules/sales/extension-points.js +26 -0
  26. package/dist/modules/sales/extension-points.js.map +2 -2
  27. package/package.json +7 -7
  28. package/src/modules/catalog/AGENTS.md +2 -2
  29. package/src/modules/customers/AGENTS.md +2 -2
  30. package/src/modules/customers/ai-tools.ts +6 -9
  31. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +1 -1
  32. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +1 -1
  33. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +1 -1
  34. package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +5 -1
  35. package/src/modules/customers/components/detail/DealDetailTabs.tsx +6 -2
  36. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +6 -2
  37. package/src/modules/sales/api/documents/factory.ts +1 -1
  38. package/src/modules/sales/api/orders/route.ts +4 -3
  39. package/src/modules/sales/api/quotes/route.ts +4 -3
  40. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +19 -1
  41. package/src/modules/sales/components/documents/SalesDocumentExtensionSpot.tsx +44 -0
  42. package/src/modules/sales/extension-points.ts +26 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/customers/backend/customers/people-v2/%5Bid%5D/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/customers/extension-points'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams, usePathname } from 'next/navigation'\nimport { User, Hash, Users, Building2 } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { CollapsibleZoneLayout, type ZoneSectionDescriptor } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { useIsMobile } from '@open-mercato/ui/hooks/useIsMobile'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, RecordNotFoundState, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useCustomerInjectedTabs } from '../../../../components/detail/useCustomerInjectedTabs'\nimport { CustomerDetailSidebar } from '../../../../components/detail/CustomerDetailSidebar'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { buildRecordInjectionContext, useSetCurrentRecordInjectionContext } from '@open-mercato/ui/backend/injection/recordContext'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\nimport { PersonEmailThreadsTab } from '../../../../components/detail/PersonEmailThreadsTab'\nimport { ActivitiesCard } from '../../../../components/detail/ActivitiesCard'\nimport type { ActivityKind } from '../../../../components/detail/ActivitiesAddNewMenu'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { TasksSection } from '../../../../components/detail/TasksSection'\nimport type { TagSummary } from '../../../../components/detail/types'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { PersonDetailHeader } from '../../../../components/detail/PersonDetailHeader'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { PersonDetailTabs, PERSON_DETAIL_TAB_IDS, resolveLegacyTab, type PersonTabId } from '../../../../components/detail/PersonDetailTabs'\nimport { AddressesSection } from '../../../../components/detail/AddressesSection'\nimport { PersonCompaniesSection } from '../../../../components/detail/PersonCompaniesSection'\nimport { MobilePersonDetail } from '../../../../components/detail/MobilePersonDetail'\nimport type { TagsSectionController } from '@open-mercato/ui/backend/detail'\nimport {\n buildPersonEditPayload,\n createPersonEditFields,\n createPersonPersonalDataGroups,\n createPersonEditSchema,\n mapPersonOverviewToFormValues,\n type PersonEditFormValues,\n type PersonOverview,\n} from '../../../../components/formConfig'\nimport { coerceDisplayName, coerceDisplayNameOrNull } from '../../../../lib/displayName'\nimport { isDetailNotFoundStatus } from '@open-mercato/core/modules/customers/lib/detailHelpers'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customers')\n\nexport default function PersonDetailV2Page({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const pathname = usePathname()\n const { organizationId } = useOrganizationScopeDetail()\n const isMobile = useIsMobile()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n\n\n const formSchema = React.useMemo(() => createPersonEditSchema(), [])\n const fields = React.useMemo(() => createPersonEditFields(t), [t])\n\n const [data, setData] = React.useState<PersonOverview | null>(null)\n // Mirror the latest `data` into a ref so save handlers always read the current\n // optimistic-lock token (`person.updatedAt`) instead of the value captured in\n // their `useCallback` closure. Without this, a header-field save issued after a\n // prior in-page reload would send a stale token (or none), letting a concurrent\n // two-tab overwrite slip through without the 409 + conflict bar (#2055, Alina A7).\n const dataRef = React.useRef<PersonOverview | null>(null)\n React.useEffect(() => {\n dataRef.current = data\n }, [data])\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n\n // Form state lifted for header Save button\n const [isDirty, setIsDirty] = React.useState(false)\n const [isSaving, setIsSaving] = React.useState(false)\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\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 currentPersonId = data?.person?.id ?? null\n const mutationContextId = React.useMemo(\n () => (currentPersonId ? `customer-person:${currentPersonId}` : `customer-person:${id ?? 'pending'}`),\n [currentPersonId, id],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n personId?: string | null\n resourceKind: string\n resourceId?: string\n data: PersonOverview | null\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const personDisplayName = coerceDisplayName(data?.person?.displayName)\n const personName = personDisplayName.trim().length\n ? personDisplayName\n : t('customers.people.list.deleteFallbackName', 'this person')\n\n const personDisplayNameForGroups = personDisplayName.trim().length\n ? personDisplayName.trim()\n : null\n\n const scheduleDialogCompanyName = coerceDisplayNameOrNull(\n data?.company?.displayName ?? data?.companies?.[0]?.displayName ?? null,\n )\n\n const groups = React.useMemo(\n () => createPersonPersonalDataGroups(t, { entityName: personDisplayNameForGroups }),\n [t, personDisplayNameForGroups],\n )\n\n const zoneSections = React.useMemo<ZoneSectionDescriptor[]>(() => [\n { id: 'personalData', icon: User, label: t('customers.people.form.groups.personalData', 'Personal data') },\n { id: 'companyRole', icon: Building2, label: t('customers.people.form.groups.companyRole', 'Company & role') },\n { id: 'customFields', icon: Hash, label: t('customers.people.form.groups.customAttributes', 'Custom attributes') },\n { id: 'roles', icon: Users, label: t('customers.people.form.groups.roles', 'My roles') },\n ], [t])\n\n // Data loading\n const initialLoadDoneRef = React.useRef(false)\n const loadData = React.useCallback(async (lockTokenOverride?: string | null) => {\n if (!id) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n setIsNotFound(false)\n try {\n const payload = await readApiResultOrThrow<PersonOverview>(\n `/api/customers/people/${encodeURIComponent(id)}`,\n undefined,\n { errorMessage: t('customers.people.detail.error.load', 'Failed to load person.') },\n )\n // When the caller is the save handler, pin the optimistic-lock token to the\n // value the write itself returned rather than the one this GET observed \u2014 a\n // concurrent third-party bump between save and reload must stay stale so the\n // next in-page save 409s (#2055, Alina A7). Applied in the same state update\n // as the refresh to avoid a redundant second re-render.\n const next = lockTokenOverride && payload?.person\n ? { ...payload, person: { ...payload.person, updatedAt: lockTokenOverride, updated_at: lockTokenOverride } }\n : payload\n setData(next as PersonOverview)\n } catch (err) {\n if (isDetailNotFoundStatus((err as { status?: number }).status)) {\n setIsNotFound(true)\n } else {\n const message = err instanceof Error ? err.message : t('customers.people.detail.error.load', 'Failed to load person.')\n setError(message)\n }\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch((err) => logger.warn('loadData failed', { component: 'people-v2', 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) => logger.warn('reload after activity failed', { component: 'people-v2', err }))\n }, [loadData])\n\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 personId: currentPersonId,\n resourceKind: 'customers.person',\n resourceId: currentPersonId ?? (id ?? undefined),\n data,\n isDirty,\n isSaving,\n retryLastMutation,\n }),\n [currentPersonId, data, isDirty, isSaving, 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 // Publish page-load record context to the AppShell-owned `backend:record:current`\n // mount so the enterprise record_locks widget resolves `customers.person` + id\n // explicitly (the hardcoded path allowlist misses the `people-v2` route).\n // Presence/acquire/heartbeat run on load; the hook clears on unmount/record switch.\n useSetCurrentRecordInjectionContext(\n buildRecordInjectionContext({\n resourceKind: 'customers.person',\n resourceId: currentPersonId,\n updatedAt: data?.person?.updatedAt ?? data?.person?.updated_at ?? null,\n data: data as Record<string, unknown> | null,\n path: pathname,\n }),\n )\n\n const handleAddActivity = React.useCallback((kind: ActivityKind) => {\n setScheduleEditData({\n id: '',\n interactionType: kind,\n title: null,\n body: null,\n scheduledAt: null,\n durationMinutes: null,\n location: null,\n allDay: null,\n recurrenceRule: null,\n recurrenceEnd: null,\n participants: null,\n reminderMinutes: null,\n visibility: null,\n linkedEntities: null,\n guestPermissions: null,\n })\n setScheduleDialogOpen(true)\n }, [])\n\n const handleEditActivity = React.useCallback((activity: { id: string; interactionType?: string; title?: string | null; body?: string | null; scheduledAt?: string | null; occurredAt?: 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 // Forward `customValues` so per-type chip state (callPhoneNumber, callDirection,\n // taskPriority, \u2026) round-trips on edit (#1808 phone persistence).\n // Forward `occurredAt` so historical activity edits prefill from the original\n // moment instead of \"today\" (#1807 prefill).\n const editPayload = {\n id: activity.id,\n updatedAt: typeof raw.updatedAt === 'string' ? raw.updatedAt as string : typeof raw.updated_at === 'string' ? raw.updated_at as string : null,\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 occurredAt: typeof activity.occurredAt === 'string' ? activity.occurredAt : null,\n durationMinutes: durationValue,\n priority: typeof raw.priority === 'number' ? raw.priority as number : null,\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 customValues: raw.customValues && typeof raw.customValues === 'object'\n ? raw.customValues as Record<string, unknown>\n : null,\n phoneNumber: typeof raw.phoneNumber === 'string' ? raw.phoneNumber as string : null,\n } as ScheduleActivityEditData & { customValues?: Record<string, unknown> | null; phoneNumber?: string | null }\n setScheduleEditData(editPayload)\n setScheduleDialogOpen(true)\n }, [])\n\n const { injectedTabs, injectedTabMap, loading: injectedTabsLoading } = useCustomerInjectedTabs({\n spotId: extensionPoints.hosts.personTabs.spotId,\n context: injectionContext,\n data,\n onDataChange: setData,\n nativeTabIds: PERSON_DETAIL_TAB_IDS,\n })\n\n const injectedTabIds = React.useMemo(() => injectedTabs.map((tab) => tab.id), [injectedTabs])\n const initialTab = React.useMemo(\n () => resolveLegacyTab(searchParams?.get('tab'), injectedTabIds),\n [injectedTabIds, searchParams],\n )\n const [activeTab, setActiveTab] = React.useState<PersonTabId>(initialTab)\n\n React.useEffect(() => {\n setActiveTab(initialTab)\n }, [initialTab])\n\n const handleTabChange = React.useCallback(\n (tab: PersonTabId) => {\n setActiveTab(tab)\n if (!pathname) return\n const nextParams = new URLSearchParams(searchParams?.toString() ?? '')\n nextParams.set('tab', tab)\n router.replace(`${pathname}?${nextParams.toString()}`, { scroll: false })\n },\n [pathname, router, searchParams],\n )\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 React.useEffect(() => {\n setSectionAction(null)\n }, [activeTab])\n\n // Deals scope\n const dealsScope = React.useMemo(\n () => (currentPersonId ? ({ kind: 'person', entityId: currentPersonId } as const) : null),\n [currentPersonId],\n )\n\n const initialValues = React.useMemo(\n () => (data ? mapPersonOverviewToFormValues(data) : undefined),\n [data],\n )\n\n // Form submit/delete\n const handleFormSubmit = React.useCallback(\n async (values: PersonEditFormValues) => {\n setIsSaving(true)\n try {\n await tagsSectionControllerRef.current?.flush()\n\n let payload: Record<string, unknown>\n try {\n payload = buildPersonEditPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error && err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.people.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n throw err\n }\n\n // Attach the current optimistic-lock token directly on this write path so\n // every header-field edit (displayName/status/\u2026) carries `updatedAt`, not\n // just the fields the embedded CrudForm intercepts. Read from `dataRef` so\n // the token reflects the latest in-page reload rather than a stale closure\n // capture, and let the 409 propagate to CrudForm's surfaceRecordConflict so\n // the unified conflict bar renders (#2055, Alina A7).\n const lockedUpdatedAt = dataRef.current?.person?.updatedAt\n ?? dataRef.current?.person?.updated_at\n ?? null\n const updateResponse = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(lockedUpdatedAt),\n () => updateCrud<{ updatedAt?: string | null }>('customers/people', payload),\n )\n flash(t('customers.people.form.updateSuccess', 'Person updated.'), 'success')\n // Refresh the view and pin the optimistic-lock token to the write's OWN\n // authoritative `updatedAt` in a single reload (see loadData) so a\n // concurrent third-party bump stays stale on the next save (#2055, Alina A7).\n const savedUpdatedAt = typeof updateResponse.result?.updatedAt === 'string'\n ? updateResponse.result.updatedAt\n : null\n await loadData(savedUpdatedAt)\n } finally {\n setIsSaving(false)\n }\n },\n [loadData, organizationId, t],\n )\n\n const handleFormDelete = React.useCallback(\n async () => {\n const personId = data?.person?.id ?? ''\n if (!personId) return\n const approved = await confirm({\n title: t('customers.people.detail.deleteConfirmTitle', 'Delete person?'),\n description: t('customers.people.detail.deleteConfirmDescription', 'This action cannot be undone.'),\n confirmText: t('customers.people.detail.actions.delete', 'Delete'),\n cancelText: t('customers.people.detail.actions.cancel', 'Cancel'),\n variant: 'destructive',\n })\n if (!approved) return\n try {\n await runMutationWithContext(\n () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(data?.person?.updatedAt ?? data?.person?.updated_at ?? null),\n () => deleteCrud('customers/people', { id: personId }),\n ),\n { id: personId, operation: 'deletePerson' },\n )\n } catch (err) {\n // The guarded mutation routes a 409 to the unified conflict bar; surface\n // any other server error (e.g. a linked-records delete guard) as a flash\n // instead of letting it crash the page.\n if (!surfaceRecordConflict(err, t)) {\n flash(\n err instanceof Error && err.message.trim().length > 0\n ? err.message\n : t('customers.people.detail.deleteError', 'Failed to delete person.'),\n 'error',\n )\n }\n return\n }\n flash(t('customers.people.list.deleteSuccess', 'Person deleted.'), 'success')\n router.push('/backend/customers/people')\n },\n [confirm, data?.person?.id, router, runMutationWithContext, t],\n )\n\n const handleHeaderSave = React.useCallback(() => {\n const form = formWrapperRef.current?.querySelector('form')\n if (form) form.requestSubmit()\n }, [])\n\n // Counts for tab badges\n const interactionCount = data?.counts?.activities ?? 0\n const todoCount = data?.counts?.todos ?? 0\n const companyCount = data?.counts?.companies ?? (data?.companies?.length ?? (data?.company ? 1 : 0))\n\n // Loading / error states\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.people.detail.loading', 'Loading person\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.people.detail.error.notFound', 'Person not found.')}\n backHref=\"/backend/customers/people\"\n backLabel={t('customers.people.detail.actions.backToList', 'Back to people')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data?.person?.id || !initialValues) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.people.detail.error.load', 'Failed to load person.')}\n action={(\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/customers/people\">\n {t('customers.people.detail.actions.backToList', 'Back to people')}\n </Link>\n </Button>\n )}\n />\n </PageBody>\n </Page>\n )\n }\n\n const personId = data.person.id\n const useCanonicalInteractions = data.interactionMode === 'canonical'\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n {/* UMES header injection (third-party extensions) */}\n <InjectionSpot spotId={extensionPoints.hosts.personHeader.spotId} context={injectionContext} data={data} />\n <InjectionSpot spotId={extensionPoints.hosts.personStatusBadges.spotId} context={injectionContext} data={data} />\n\n {/* Persistent person header */}\n <PersonDetailHeader\n actions={<InjectionSpot spotId={extensionPoints.hosts.personHeaderActions.spotId} context={injectionContext} data={data} disabled={isSaving} />}\n data={data}\n onTagsChange={handleTagsChange}\n tagsSectionControllerRef={tagsSectionControllerRef}\n onSave={handleHeaderSave}\n onDelete={handleFormDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n onOpenCompaniesTab={() => handleTabChange('companies')}\n onDataReload={() => { loadData().catch((err) => logger.warn('onDataReload failed', { component: 'people-v2', err })) }}\n onFocusField={(fieldName) => {\n const selectorMap: Record<string, string> = {\n primaryEmail: 'input[type=\"email\"]',\n primaryPhone: 'input[type=\"tel\"]',\n }\n const selector = selectorMap[fieldName]\n const input = selector ? formWrapperRef.current?.querySelector<HTMLInputElement>(selector) : null\n if (input) {\n input.scrollIntoView({ behavior: 'smooth', block: 'center' })\n requestAnimationFrame(() => input.focus())\n }\n }}\n />\n\n {/* Zone content shared between desktop (CollapsibleZoneLayout) and mobile (MobilePersonDetail). */}\n <CustomerDetailSidebar spotId={extensionPoints.hosts.personSidebar.spotId} context={injectionContext} data={data} onDataChange={setData} disabled={isSaving}>\n {(() => {\n const zone1Content = (\n <div ref={formWrapperRef}>\n <CrudForm<PersonEditFormValues>\n embedded\n trackDirtyWhenEmbedded\n injectionSpotId={extensionPoints.hosts.personForm.spotId}\n entityId=\"customers.person\"\n resourceKind=\"customers.person\"\n resourceId={personId}\n injectionGroupAliases={{ details: 'personalData' }}\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n schema={formSchema}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n optimisticLockUpdatedAt={data.person.updatedAt ?? data.person.updated_at ?? null}\n onSubmit={handleFormSubmit}\n onDelete={handleFormDelete}\n hideFooterActions\n collapsibleGroups={{ pageType: 'person-v2', chevronPosition: 'right' }}\n sortableGroups={{ pageType: 'person-v2' }}\n onDirtyChange={setIsDirty}\n />\n </div>\n )\n const zone2Content = (\n <PersonDetailTabs\n activeTab={activeTab}\n onTabChange={handleTabChange}\n isLoadingInjectedTabs={injectedTabsLoading}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n activitiesCount={interactionCount}\n dealsCount={dealCount}\n companiesCount={companyCount}\n addressesCount={data?.counts?.addresses ?? 0}\n tasksCount={todoCount}\n sectionAction={sectionAction}\n >\n <div className=\"min-w-0\">\n {(() => {\n // Injected tab content\n\n if (activeTab === 'activities') {\n return (\n <div className=\"space-y-4\">\n <ActivitiesCard\n entityId={personId}\n plannedActivities={plannedActivities}\n refreshKey={activityRefreshKey}\n onAddNew={handleAddActivity}\n onEditActivity={handleEditActivity}\n entityCompanyName={data.company?.displayName ?? data.companies?.[0]?.displayName ?? null}\n />\n <ActivitiesSection\n entityId={personId}\n entityName={personName}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={handleActivityCreated}\n refreshKey={activityRefreshKey}\n addActionLabel={t('customers.people.detail.activities.add', 'Log activity')}\n emptyState={{\n title: t('customers.people.detail.emptyState.activities.title', 'No activities logged yet'),\n actionLabel: t('customers.people.detail.emptyState.activities.action', 'Log activity'),\n }}\n onActionChange={handleSectionActionChange}\n onEditActivity={handleEditActivity}\n />\n </div>\n )\n }\n\n if (activeTab === 'emails') {\n return (\n <PersonEmailThreadsTab\n personId={personId}\n defaultRecipient={data.person?.primaryEmail ?? null}\n />\n )\n }\n\n if (activeTab === 'deals') {\n return (\n <DealsSection\n scope={dealsScope}\n emptyLabel={t('customers.people.detail.empty.deals', 'No deals linked to this person.')}\n addActionLabel={t('customers.people.detail.actions.addDeal', 'Add deal')}\n emptyState={{\n title: t('customers.people.detail.emptyState.deals.title', 'No deals yet'),\n actionLabel: t('customers.people.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\n if (activeTab === 'companies') {\n return (\n <PersonCompaniesSection\n personId={personId}\n personName={personName}\n initialLinkedCompanies={data?.companies ?? []}\n onChanged={loadData}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n\n if (activeTab === 'addresses') {\n return (\n <AddressesSection\n entityId={personId}\n emptyLabel={t('customers.people.detail.empty.addresses', 'No addresses linked to this person.')}\n addActionLabel={t('customers.people.detail.addresses.add', 'Add address')}\n emptyState={{\n title: t('customers.people.detail.emptyState.addresses.title', 'No addresses yet'),\n actionLabel: t('customers.people.detail.emptyState.addresses.action', 'Add address'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n />\n )\n }\n\n if (activeTab === 'tasks') {\n return (\n <TasksSection\n entityId={personId}\n initialTasks={[]}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={loadData}\n emptyLabel={t('customers.people.detail.empty.todos', 'No tasks linked to this person.')}\n addActionLabel={t('customers.people.detail.tasks.add', 'Add task')}\n emptyState={{\n title: t('customers.people.detail.emptyState.tasks.title', 'Plan what happens next'),\n actionLabel: t('customers.people.detail.emptyState.tasks.action', 'Create task'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n entityName={personName}\n dialogContextKey=\"customers.people.detail.tasks.dialog.context\"\n dialogContextFallback=\"This task will be linked to {{name}}\"\n />\n )\n }\n\n if (activeTab === 'files') {\n return (\n <AttachmentsSection\n entityId={E.customers.customer_entity}\n recordId={personId}\n title={t('customers.people.detail.tabs.files', 'Files')}\n description={t('customers.people.detail.files.subtitle', 'Upload and manage files linked to this person.')}\n />\n )\n }\n\n if (activeTab === 'changelog') {\n return <ChangelogTab entityId={personId} entityType=\"person\" />\n }\n\n return null\n })()}\n {injectedTabMap.get(activeTab)?.()}\n </div>\n </PersonDetailTabs>\n )\n // Render only the layout variant that matches the viewport. Mounting\n // both the mobile and desktop layouts at once would create two\n // CrudForm instances bound to one `formWrapperRef`, so header Save\n // could submit the hidden instance's stale values and silently\n // discard the edit (#2453). `useIsMobile` is SSR-safe.\n return isMobile ? (\n <MobilePersonDetail zone1={zone1Content} zone2={zone2Content} />\n ) : (\n <CollapsibleZoneLayout\n pageType=\"person-v2\"\n entityName={personName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1={zone1Content}\n zone2={zone2Content}\n />\n )\n })()}\n </CustomerDetailSidebar>\n\n {/* UMES footer injection */}\n <InjectionSpot spotId={extensionPoints.hosts.personFooter.spotId} context={injectionContext} data={data} />\n\n {/* Schedule Activity Dialog \u2014 opened from PlannedActivities \"+ Schedule\" or other triggers */}\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={() => { setScheduleDialogOpen(false); setScheduleEditData(null) }}\n entityId={personId}\n entityName={personName}\n companyName={scheduleDialogCompanyName}\n entityType=\"person\"\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 { extensionPoints } from '@open-mercato/core/modules/customers/extension-points'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams, usePathname } from 'next/navigation'\nimport { User, Hash, Users, Building2 } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { CollapsibleZoneLayout, type ZoneSectionDescriptor } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { useIsMobile } from '@open-mercato/ui/hooks/useIsMobile'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, RecordNotFoundState, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useCustomerInjectedTabs } from '../../../../components/detail/useCustomerInjectedTabs'\nimport { CustomerDetailSidebar } from '../../../../components/detail/CustomerDetailSidebar'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { buildRecordInjectionContext, useSetCurrentRecordInjectionContext } from '@open-mercato/ui/backend/injection/recordContext'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\nimport { PersonEmailThreadsTab } from '../../../../components/detail/PersonEmailThreadsTab'\nimport { ActivitiesCard } from '../../../../components/detail/ActivitiesCard'\nimport type { ActivityKind } from '../../../../components/detail/ActivitiesAddNewMenu'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { TasksSection } from '../../../../components/detail/TasksSection'\nimport type { TagSummary } from '../../../../components/detail/types'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { PersonDetailHeader } from '../../../../components/detail/PersonDetailHeader'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { PersonDetailTabs, PERSON_DETAIL_TAB_IDS, resolveLegacyTab, type PersonTabId } from '../../../../components/detail/PersonDetailTabs'\nimport { AddressesSection } from '../../../../components/detail/AddressesSection'\nimport { PersonCompaniesSection } from '../../../../components/detail/PersonCompaniesSection'\nimport { MobilePersonDetail } from '../../../../components/detail/MobilePersonDetail'\nimport type { TagsSectionController } from '@open-mercato/ui/backend/detail'\nimport {\n buildPersonEditPayload,\n createPersonEditFields,\n createPersonPersonalDataGroups,\n createPersonEditSchema,\n mapPersonOverviewToFormValues,\n type PersonEditFormValues,\n type PersonOverview,\n} from '../../../../components/formConfig'\nimport { coerceDisplayName, coerceDisplayNameOrNull } from '../../../../lib/displayName'\nimport { isDetailNotFoundStatus } from '@open-mercato/core/modules/customers/lib/detailHelpers'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customers')\n\nexport default function PersonDetailV2Page({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const pathname = usePathname()\n const { organizationId } = useOrganizationScopeDetail()\n const isMobile = useIsMobile()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n\n\n const formSchema = React.useMemo(() => createPersonEditSchema(), [])\n const fields = React.useMemo(() => createPersonEditFields(t), [t])\n\n const [data, setData] = React.useState<PersonOverview | null>(null)\n // Mirror the latest `data` into a ref so save handlers always read the current\n // optimistic-lock token (`person.updatedAt`) instead of the value captured in\n // their `useCallback` closure. Without this, a header-field save issued after a\n // prior in-page reload would send a stale token (or none), letting a concurrent\n // two-tab overwrite slip through without the 409 + conflict bar (#2055, Alina A7).\n const dataRef = React.useRef<PersonOverview | null>(null)\n React.useEffect(() => {\n dataRef.current = data\n }, [data])\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n\n // Form state lifted for header Save button\n const [isDirty, setIsDirty] = React.useState(false)\n const [isSaving, setIsSaving] = React.useState(false)\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\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 currentPersonId = data?.person?.id ?? null\n const mutationContextId = React.useMemo(\n () => (currentPersonId ? `customer-person:${currentPersonId}` : `customer-person:${id ?? 'pending'}`),\n [currentPersonId, id],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n personId?: string | null\n resourceKind: string\n resourceId?: string\n data: PersonOverview | null\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const personDisplayName = coerceDisplayName(data?.person?.displayName)\n const personName = personDisplayName.trim().length\n ? personDisplayName\n : t('customers.people.list.deleteFallbackName', 'this person')\n\n const personDisplayNameForGroups = personDisplayName.trim().length\n ? personDisplayName.trim()\n : null\n\n const scheduleDialogCompanyName = coerceDisplayNameOrNull(\n data?.company?.displayName ?? data?.companies?.[0]?.displayName ?? null,\n )\n\n const groups = React.useMemo(\n () => createPersonPersonalDataGroups(t, { entityName: personDisplayNameForGroups }),\n [t, personDisplayNameForGroups],\n )\n\n const zoneSections = React.useMemo<ZoneSectionDescriptor[]>(() => [\n { id: 'personalData', icon: User, label: t('customers.people.form.groups.personalData', 'Personal data') },\n { id: 'companyRole', icon: Building2, label: t('customers.people.form.groups.companyRole', 'Company & role') },\n { id: 'customFields', icon: Hash, label: t('customers.people.form.groups.customAttributes', 'Custom attributes') },\n { id: 'roles', icon: Users, label: t('customers.people.form.groups.roles', 'My roles') },\n ], [t])\n\n // Data loading\n const initialLoadDoneRef = React.useRef(false)\n const loadData = React.useCallback(async (lockTokenOverride?: string | null) => {\n if (!id) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n setIsNotFound(false)\n try {\n const payload = await readApiResultOrThrow<PersonOverview>(\n `/api/customers/people/${encodeURIComponent(id)}`,\n undefined,\n { errorMessage: t('customers.people.detail.error.load', 'Failed to load person.') },\n )\n // When the caller is the save handler, pin the optimistic-lock token to the\n // value the write itself returned rather than the one this GET observed \u2014 a\n // concurrent third-party bump between save and reload must stay stale so the\n // next in-page save 409s (#2055, Alina A7). Applied in the same state update\n // as the refresh to avoid a redundant second re-render.\n const next = lockTokenOverride && payload?.person\n ? { ...payload, person: { ...payload.person, updatedAt: lockTokenOverride, updated_at: lockTokenOverride } }\n : payload\n setData(next as PersonOverview)\n } catch (err) {\n if (isDetailNotFoundStatus((err as { status?: number }).status)) {\n setIsNotFound(true)\n } else {\n const message = err instanceof Error ? err.message : t('customers.people.detail.error.load', 'Failed to load person.')\n setError(message)\n }\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch((err) => logger.warn('loadData failed', { component: 'people-v2', 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) => logger.warn('reload after activity failed', { component: 'people-v2', err }))\n }, [loadData])\n\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 personId: currentPersonId,\n resourceKind: 'customers.person',\n resourceId: currentPersonId ?? (id ?? undefined),\n data,\n isDirty,\n isSaving,\n retryLastMutation,\n }),\n [currentPersonId, data, isDirty, isSaving, 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 // Publish page-load record context to the AppShell-owned `backend:record:current`\n // mount so the enterprise record_locks widget resolves `customers.person` + id\n // explicitly (the hardcoded path allowlist misses the `people-v2` route).\n // Presence/acquire/heartbeat run on load; the hook clears on unmount/record switch.\n useSetCurrentRecordInjectionContext(\n buildRecordInjectionContext({\n resourceKind: 'customers.person',\n resourceId: currentPersonId,\n updatedAt: data?.person?.updatedAt ?? data?.person?.updated_at ?? null,\n data: data as Record<string, unknown> | null,\n path: pathname,\n }),\n )\n\n const handleAddActivity = React.useCallback((kind: ActivityKind) => {\n setScheduleEditData({\n id: '',\n interactionType: kind,\n title: null,\n body: null,\n scheduledAt: null,\n durationMinutes: null,\n location: null,\n allDay: null,\n recurrenceRule: null,\n recurrenceEnd: null,\n participants: null,\n reminderMinutes: null,\n visibility: null,\n linkedEntities: null,\n guestPermissions: null,\n })\n setScheduleDialogOpen(true)\n }, [])\n\n const handleEditActivity = React.useCallback((activity: { id: string; interactionType?: string; title?: string | null; body?: string | null; scheduledAt?: string | null; occurredAt?: 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 // Forward `customValues` so per-type chip state (callPhoneNumber, callDirection,\n // taskPriority, \u2026) round-trips on edit (#1808 phone persistence).\n // Forward `occurredAt` so historical activity edits prefill from the original\n // moment instead of \"today\" (#1807 prefill).\n const editPayload = {\n id: activity.id,\n updatedAt: typeof raw.updatedAt === 'string' ? raw.updatedAt as string : typeof raw.updated_at === 'string' ? raw.updated_at as string : null,\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 occurredAt: typeof activity.occurredAt === 'string' ? activity.occurredAt : null,\n durationMinutes: durationValue,\n priority: typeof raw.priority === 'number' ? raw.priority as number : null,\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 customValues: raw.customValues && typeof raw.customValues === 'object'\n ? raw.customValues as Record<string, unknown>\n : null,\n phoneNumber: typeof raw.phoneNumber === 'string' ? raw.phoneNumber as string : null,\n } as ScheduleActivityEditData & { customValues?: Record<string, unknown> | null; phoneNumber?: string | null }\n setScheduleEditData(editPayload)\n setScheduleDialogOpen(true)\n }, [])\n\n const { injectedTabs, injectedTabMap, loading: injectedTabsLoading } = useCustomerInjectedTabs({\n spotId: extensionPoints.hosts.personTabs.spotId,\n context: injectionContext,\n data,\n onDataChange: setData,\n nativeTabIds: PERSON_DETAIL_TAB_IDS,\n })\n\n const injectedTabIds = React.useMemo(() => injectedTabs.map((tab) => tab.id), [injectedTabs])\n const initialTab = React.useMemo(\n () => resolveLegacyTab(searchParams?.get('tab'), injectedTabIds),\n [injectedTabIds, searchParams],\n )\n const [activeTab, setActiveTab] = React.useState<PersonTabId>(initialTab)\n\n React.useEffect(() => {\n setActiveTab(initialTab)\n }, [initialTab])\n\n const handleTabChange = React.useCallback(\n (tab: PersonTabId) => {\n setActiveTab(tab)\n if (!pathname) return\n const nextParams = new URLSearchParams(searchParams?.toString() ?? '')\n nextParams.set('tab', tab)\n router.replace(`${pathname}?${nextParams.toString()}`, { scroll: false })\n },\n [pathname, router, searchParams],\n )\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 React.useEffect(() => {\n setSectionAction(null)\n }, [activeTab])\n\n // Deals scope\n const dealsScope = React.useMemo(\n () => (currentPersonId ? ({ kind: 'person', entityId: currentPersonId } as const) : null),\n [currentPersonId],\n )\n\n const initialValues = React.useMemo(\n () => (data ? mapPersonOverviewToFormValues(data) : undefined),\n [data],\n )\n\n // Form submit/delete\n const handleFormSubmit = React.useCallback(\n async (values: PersonEditFormValues) => {\n setIsSaving(true)\n try {\n await tagsSectionControllerRef.current?.flush()\n\n let payload: Record<string, unknown>\n try {\n payload = buildPersonEditPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error && err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.people.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n throw err\n }\n\n // Attach the current optimistic-lock token directly on this write path so\n // every header-field edit (displayName/status/\u2026) carries `updatedAt`, not\n // just the fields the embedded CrudForm intercepts. Read from `dataRef` so\n // the token reflects the latest in-page reload rather than a stale closure\n // capture, and let the 409 propagate to CrudForm's surfaceRecordConflict so\n // the unified conflict bar renders (#2055, Alina A7).\n const lockedUpdatedAt = dataRef.current?.person?.updatedAt\n ?? dataRef.current?.person?.updated_at\n ?? null\n const updateResponse = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(lockedUpdatedAt),\n () => updateCrud<{ updatedAt?: string | null }>('customers/people', payload),\n )\n flash(t('customers.people.form.updateSuccess', 'Person updated.'), 'success')\n // Refresh the view and pin the optimistic-lock token to the write's OWN\n // authoritative `updatedAt` in a single reload (see loadData) so a\n // concurrent third-party bump stays stale on the next save (#2055, Alina A7).\n const savedUpdatedAt = typeof updateResponse.result?.updatedAt === 'string'\n ? updateResponse.result.updatedAt\n : null\n await loadData(savedUpdatedAt)\n } finally {\n setIsSaving(false)\n }\n },\n [loadData, organizationId, t],\n )\n\n const handleFormDelete = React.useCallback(\n async () => {\n const personId = data?.person?.id ?? ''\n if (!personId) return\n const approved = await confirm({\n title: t('customers.people.detail.deleteConfirmTitle', 'Delete person?'),\n description: t('customers.people.detail.deleteConfirmDescription', 'This action cannot be undone.'),\n confirmText: t('customers.people.detail.actions.delete', 'Delete'),\n cancelText: t('customers.people.detail.actions.cancel', 'Cancel'),\n variant: 'destructive',\n })\n if (!approved) return\n try {\n await runMutationWithContext(\n () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(data?.person?.updatedAt ?? data?.person?.updated_at ?? null),\n () => deleteCrud('customers/people', { id: personId }),\n ),\n { id: personId, operation: 'deletePerson' },\n )\n } catch (err) {\n // The guarded mutation routes a 409 to the unified conflict bar; surface\n // any other server error (e.g. a linked-records delete guard) as a flash\n // instead of letting it crash the page.\n if (!surfaceRecordConflict(err, t)) {\n flash(\n err instanceof Error && err.message.trim().length > 0\n ? err.message\n : t('customers.people.detail.deleteError', 'Failed to delete person.'),\n 'error',\n )\n }\n return\n }\n flash(t('customers.people.list.deleteSuccess', 'Person deleted.'), 'success')\n router.push('/backend/customers/people')\n },\n [confirm, data?.person?.id, router, runMutationWithContext, t],\n )\n\n const handleHeaderSave = React.useCallback(() => {\n const form = formWrapperRef.current?.querySelector('form')\n if (form) form.requestSubmit()\n }, [])\n\n // Counts for tab badges\n const interactionCount = data?.counts?.activities ?? 0\n const todoCount = data?.counts?.todos ?? 0\n const companyCount = data?.counts?.companies ?? (data?.companies?.length ?? (data?.company ? 1 : 0))\n\n // Loading / error states\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.people.detail.loading', 'Loading person\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.people.detail.error.notFound', 'Person not found.')}\n backHref=\"/backend/customers/people\"\n backLabel={t('customers.people.detail.actions.backToList', 'Back to people')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data?.person?.id || !initialValues) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.people.detail.error.load', 'Failed to load person.')}\n action={(\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/customers/people\">\n {t('customers.people.detail.actions.backToList', 'Back to people')}\n </Link>\n </Button>\n )}\n />\n </PageBody>\n </Page>\n )\n }\n\n const personId = data.person.id\n const useCanonicalInteractions = data.interactionMode === 'canonical'\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n {/* UMES header injection (third-party extensions) */}\n <InjectionSpot spotId={extensionPoints.hosts.personHeader.spotId} context={injectionContext} data={data} />\n <InjectionSpot spotId={extensionPoints.hosts.personStatusBadges.spotId} context={injectionContext} data={data} />\n\n {/* Persistent person header */}\n <PersonDetailHeader\n actions={<InjectionSpot spotId={extensionPoints.hosts.personHeaderActions.spotId} context={injectionContext} data={data} disabled={isSaving} />}\n data={data}\n onTagsChange={handleTagsChange}\n tagsSectionControllerRef={tagsSectionControllerRef}\n onSave={handleHeaderSave}\n onDelete={handleFormDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n onOpenCompaniesTab={() => handleTabChange('companies')}\n onDataReload={() => { loadData().catch((err) => logger.warn('onDataReload failed', { component: 'people-v2', err })) }}\n onFocusField={(fieldName) => {\n const selectorMap: Record<string, string> = {\n primaryEmail: 'input[type=\"email\"]',\n primaryPhone: 'input[type=\"tel\"]',\n }\n const selector = selectorMap[fieldName]\n const input = selector ? formWrapperRef.current?.querySelector<HTMLInputElement>(selector) : null\n if (input) {\n input.scrollIntoView({ behavior: 'smooth', block: 'center' })\n requestAnimationFrame(() => input.focus())\n }\n }}\n />\n\n {/* Zone content shared between desktop (CollapsibleZoneLayout) and mobile (MobilePersonDetail). */}\n <CustomerDetailSidebar spotId={extensionPoints.hosts.personSidebar.spotId} context={injectionContext} data={data} onDataChange={setData} disabled={isSaving}>\n {(() => {\n const zone1Content = (\n <div ref={formWrapperRef}>\n <CrudForm<PersonEditFormValues>\n embedded\n trackDirtyWhenEmbedded\n injectionSpotId={extensionPoints.hosts.personForm.spotId}\n entityId=\"customers.person\"\n resourceKind=\"customers.person\"\n resourceId={personId}\n injectionGroupAliases={{ details: 'personalData' }}\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n schema={formSchema}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n optimisticLockUpdatedAt={data.person.updatedAt ?? data.person.updated_at ?? null}\n onSubmit={handleFormSubmit}\n onDelete={handleFormDelete}\n hideFooterActions\n collapsibleGroups={{ pageType: 'person-v2', chevronPosition: 'right' }}\n sortableGroups={{ pageType: 'person-v2' }}\n onDirtyChange={setIsDirty}\n />\n </div>\n )\n const zone2Content = (\n <PersonDetailTabs\n activeTab={activeTab}\n onTabChange={handleTabChange}\n isLoadingInjectedTabs={injectedTabsLoading}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label, priority: tab.priority }))}\n activitiesCount={interactionCount}\n dealsCount={dealCount}\n companiesCount={companyCount}\n addressesCount={data?.counts?.addresses ?? 0}\n tasksCount={todoCount}\n sectionAction={sectionAction}\n >\n <div className=\"min-w-0\">\n {(() => {\n // Injected tab content\n\n if (activeTab === 'activities') {\n return (\n <div className=\"space-y-4\">\n <ActivitiesCard\n entityId={personId}\n plannedActivities={plannedActivities}\n refreshKey={activityRefreshKey}\n onAddNew={handleAddActivity}\n onEditActivity={handleEditActivity}\n entityCompanyName={data.company?.displayName ?? data.companies?.[0]?.displayName ?? null}\n />\n <ActivitiesSection\n entityId={personId}\n entityName={personName}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={handleActivityCreated}\n refreshKey={activityRefreshKey}\n addActionLabel={t('customers.people.detail.activities.add', 'Log activity')}\n emptyState={{\n title: t('customers.people.detail.emptyState.activities.title', 'No activities logged yet'),\n actionLabel: t('customers.people.detail.emptyState.activities.action', 'Log activity'),\n }}\n onActionChange={handleSectionActionChange}\n onEditActivity={handleEditActivity}\n />\n </div>\n )\n }\n\n if (activeTab === 'emails') {\n return (\n <PersonEmailThreadsTab\n personId={personId}\n defaultRecipient={data.person?.primaryEmail ?? null}\n />\n )\n }\n\n if (activeTab === 'deals') {\n return (\n <DealsSection\n scope={dealsScope}\n emptyLabel={t('customers.people.detail.empty.deals', 'No deals linked to this person.')}\n addActionLabel={t('customers.people.detail.actions.addDeal', 'Add deal')}\n emptyState={{\n title: t('customers.people.detail.emptyState.deals.title', 'No deals yet'),\n actionLabel: t('customers.people.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\n if (activeTab === 'companies') {\n return (\n <PersonCompaniesSection\n personId={personId}\n personName={personName}\n initialLinkedCompanies={data?.companies ?? []}\n onChanged={loadData}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n\n if (activeTab === 'addresses') {\n return (\n <AddressesSection\n entityId={personId}\n emptyLabel={t('customers.people.detail.empty.addresses', 'No addresses linked to this person.')}\n addActionLabel={t('customers.people.detail.addresses.add', 'Add address')}\n emptyState={{\n title: t('customers.people.detail.emptyState.addresses.title', 'No addresses yet'),\n actionLabel: t('customers.people.detail.emptyState.addresses.action', 'Add address'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n />\n )\n }\n\n if (activeTab === 'tasks') {\n return (\n <TasksSection\n entityId={personId}\n initialTasks={[]}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={loadData}\n emptyLabel={t('customers.people.detail.empty.todos', 'No tasks linked to this person.')}\n addActionLabel={t('customers.people.detail.tasks.add', 'Add task')}\n emptyState={{\n title: t('customers.people.detail.emptyState.tasks.title', 'Plan what happens next'),\n actionLabel: t('customers.people.detail.emptyState.tasks.action', 'Create task'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n entityName={personName}\n dialogContextKey=\"customers.people.detail.tasks.dialog.context\"\n dialogContextFallback=\"This task will be linked to {{name}}\"\n />\n )\n }\n\n if (activeTab === 'files') {\n return (\n <AttachmentsSection\n entityId={E.customers.customer_entity}\n recordId={personId}\n title={t('customers.people.detail.tabs.files', 'Files')}\n description={t('customers.people.detail.files.subtitle', 'Upload and manage files linked to this person.')}\n />\n )\n }\n\n if (activeTab === 'changelog') {\n return <ChangelogTab entityId={personId} entityType=\"person\" />\n }\n\n return null\n })()}\n {injectedTabMap.get(activeTab)?.()}\n </div>\n </PersonDetailTabs>\n )\n // Render only the layout variant that matches the viewport. Mounting\n // both the mobile and desktop layouts at once would create two\n // CrudForm instances bound to one `formWrapperRef`, so header Save\n // could submit the hidden instance's stale values and silently\n // discard the edit (#2453). `useIsMobile` is SSR-safe.\n return isMobile ? (\n <MobilePersonDetail zone1={zone1Content} zone2={zone2Content} />\n ) : (\n <CollapsibleZoneLayout\n pageType=\"person-v2\"\n entityName={personName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1={zone1Content}\n zone2={zone2Content}\n />\n )\n })()}\n </CustomerDetailSidebar>\n\n {/* UMES footer injection */}\n <InjectionSpot spotId={extensionPoints.hosts.personFooter.spotId} context={injectionContext} data={data} />\n\n {/* Schedule Activity Dialog \u2014 opened from PlannedActivities \"+ Schedule\" or other triggers */}\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={() => { setScheduleDialogOpen(false); setScheduleEditData(null) }}\n entityId={personId}\n entityName={personName}\n companyName={scheduleDialogCompanyName}\n entityType=\"person\"\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": ["personId"]
7
7
  }
@@ -94,9 +94,10 @@ function DefaultCompanyDetailTabs({
94
94
  ...builtInTabs,
95
95
  ...injectedTabs.filter((tab, index) => !builtInTabs.some((native) => native.id === tab.id) && injectedTabs.findIndex((candidate) => candidate.id === tab.id) === index).map((tab) => ({
96
96
  id: tab.id,
97
- label: tab.label
97
+ label: tab.label,
98
+ priority: tab.priority
98
99
  }))
99
- ].filter((tab) => !hidden.has(tab.id));
100
+ ].sort((left, right) => (right.priority ?? 0) - (left.priority ?? 0)).filter((tab) => !hidden.has(tab.id));
100
101
  }, [builtInTabs, hiddenTabIds, injectedTabs]);
101
102
  React.useEffect(() => {
102
103
  if (isLoadingInjectedTabs || !isDealsAccessReady || allTabs.some((tab) => tab.id === activeTab)) return;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/components/detail/CompanyDetailTabs.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'\nimport {\n Users,\n Handshake,\n Clock,\n History,\n Paperclip,\n Plus,\n} from 'lucide-react'\nimport type { SectionAction } from '@open-mercato/ui/backend/detail'\nimport { registerComponent } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { useRegisteredComponent } from '@open-mercato/ui/backend/injection/useRegisteredComponent'\nimport { useDealsAccess } from './useDealsAccess'\n\nexport const COMPANY_DETAIL_TAB_IDS = ['people', 'deals', 'activity-log', 'changelog', 'files'] as const\n\nexport type CompanyTabId =\n | 'people'\n | 'deals'\n | 'activity-log'\n | 'changelog'\n | 'files'\n | string\n\ntype TabDef = {\n id: CompanyTabId\n label: string\n icon?: React.ReactNode\n count?: React.ReactNode\n}\n\nexport const COMPANY_DETAIL_TABS_COMPONENT_ID = 'section:customers.companies.detailTabs'\n\nexport type CompanyDetailTabsProps = {\n activeTab: CompanyTabId\n onTabChange: (tab: CompanyTabId) => void\n injectedTabs?: Array<{ id: string; label: string; priority?: number }>\n isLoadingInjectedTabs?: boolean\n hiddenTabIds?: string[]\n peopleCount?: number\n dealsCount?: number\n activitiesCount?: number\n filesCount?: number\n sectionAction?: SectionAction | null\n children: React.ReactNode\n}\n\nconst LEGACY_TAB_MAP: Record<string, CompanyTabId> = {\n notes: 'people',\n activities: 'activity-log',\n addresses: 'people',\n tasks: 'people',\n dashboard: 'people',\n 'dane-firmy': 'people',\n analysis: 'people',\n}\n\nexport function resolveLegacyTab(tab: string | null | undefined, knownTabIds?: Iterable<string>): CompanyTabId {\n if (!tab) return 'people'\n if (LEGACY_TAB_MAP[tab]) return LEGACY_TAB_MAP[tab]\n if ((COMPANY_DETAIL_TAB_IDS as readonly string[]).includes(tab) || (knownTabIds && new Set(knownTabIds).has(tab))) return tab\n return 'people'\n}\n\nfunction formatTabCount(count: number): string | number | undefined {\n if (count <= 0) return undefined\n return count > 999 ? '999+' : count\n}\n\nfunction DefaultCompanyDetailTabs({\n activeTab,\n onTabChange,\n injectedTabs = [],\n isLoadingInjectedTabs = false,\n hiddenTabIds = [],\n peopleCount = 0,\n dealsCount = 0,\n activitiesCount = 0,\n filesCount = 0,\n sectionAction = null,\n children,\n}: CompanyDetailTabsProps) {\n const t = useT()\n const { canViewDeals, isReady: isDealsAccessReady } = useDealsAccess()\n\n const builtInTabs: TabDef[] = React.useMemo(\n () => [\n {\n id: 'people',\n label: t('customers.companies.detail.tabs.people', 'People'),\n icon: <Users className=\"size-4\" />,\n count: formatTabCount(peopleCount),\n },\n ...(canViewDeals\n ? [\n {\n id: 'deals' as CompanyTabId,\n label: t('customers.companies.detail.tabs.deals', 'Deals'),\n icon: <Handshake className=\"size-4\" />,\n count: formatTabCount(dealsCount),\n },\n ]\n : []),\n {\n id: 'activity-log',\n label: t('customers.companies.detail.tabs.activityLog', 'Activity log'),\n icon: <Clock className=\"size-4\" />,\n count: formatTabCount(activitiesCount),\n },\n {\n id: 'changelog',\n label: t('customers.companies.detail.tabs.changelog', 'Changelog'),\n icon: <History className=\"size-4\" />,\n count: 'NEW',\n },\n {\n id: 'files',\n label: t('customers.companies.detail.tabs.files', 'Files'),\n icon: <Paperclip className=\"size-4\" />,\n count: formatTabCount(filesCount),\n },\n ],\n [t, canViewDeals, peopleCount, dealsCount, activitiesCount, filesCount],\n )\n\n const allTabs: TabDef[] = React.useMemo(() => {\n const hidden = new Set(hiddenTabIds)\n return [\n ...builtInTabs,\n ...injectedTabs.filter((tab, index) => !builtInTabs.some((native) => native.id === tab.id) && injectedTabs.findIndex((candidate) => candidate.id === tab.id) === index).map((tab) => ({\n id: tab.id as CompanyTabId,\n label: tab.label,\n })),\n ].filter((tab) => !hidden.has(tab.id))\n }, [builtInTabs, hiddenTabIds, injectedTabs])\n\n React.useEffect(() => {\n if (isLoadingInjectedTabs || !isDealsAccessReady || allTabs.some((tab) => tab.id === activeTab)) return\n const fallback = allTabs[0]?.id\n if (fallback) onTabChange(fallback)\n }, [activeTab, allTabs, isLoadingInjectedTabs, onTabChange, isDealsAccessReady])\n\n return (\n <div>\n {/* Tab navigation */}\n <div className=\"flex items-end justify-between gap-2 border-b\">\n <Tabs\n value={activeTab}\n onValueChange={(value) => onTabChange(value as CompanyTabId)}\n variant=\"underline\"\n className=\"min-w-0 flex-1\"\n >\n <TabsList\n aria-label={t('customers.companies.detail.tabs.label', 'Company detail sections')}\n className=\"-mb-px w-full overflow-x-auto border-b-0 px-1\"\n >\n {allTabs.map((tab) => (\n <TabsTrigger key={tab.id} value={tab.id} leading={tab.icon} count={tab.count}>\n {tab.label}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n {sectionAction ? (\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={sectionAction.onClick}\n disabled={sectionAction.disabled}\n className=\"mb-1.5 mr-1 shrink-0\"\n >\n <Plus className=\"mr-1.5 h-4 w-4\" />\n {sectionAction.label}\n </Button>\n ) : null}\n </div>\n\n {/* Tab content */}\n <div className=\"pt-6\" role=\"tabpanel\">\n {children}\n </div>\n </div>\n )\n}\n\nregisterComponent<CompanyDetailTabsProps>({\n id: COMPANY_DETAIL_TABS_COMPONENT_ID,\n component: DefaultCompanyDetailTabs,\n metadata: {\n module: 'customers',\n description: 'Company detail tab navigation and content.',\n },\n})\n\nexport function CompanyDetailTabs(props: CompanyDetailTabsProps) {\n const ResolvedTabs = useRegisteredComponent<CompanyDetailTabsProps>(\n COMPANY_DETAIL_TABS_COMPONENT_ID,\n DefaultCompanyDetailTabs,\n )\n return <ResolvedTabs {...props} />\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'\nimport {\n Users,\n Handshake,\n Clock,\n History,\n Paperclip,\n Plus,\n} from 'lucide-react'\nimport type { SectionAction } from '@open-mercato/ui/backend/detail'\nimport { registerComponent } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { useRegisteredComponent } from '@open-mercato/ui/backend/injection/useRegisteredComponent'\nimport { useDealsAccess } from './useDealsAccess'\n\nexport const COMPANY_DETAIL_TAB_IDS = ['people', 'deals', 'activity-log', 'changelog', 'files'] as const\n\nexport type CompanyTabId =\n | 'people'\n | 'deals'\n | 'activity-log'\n | 'changelog'\n | 'files'\n | string\n\ntype TabDef = {\n id: CompanyTabId\n label: string\n icon?: React.ReactNode\n count?: React.ReactNode\n priority?: number\n}\n\nexport const COMPANY_DETAIL_TABS_COMPONENT_ID = 'section:customers.companies.detailTabs'\n\nexport type CompanyDetailTabsProps = {\n activeTab: CompanyTabId\n onTabChange: (tab: CompanyTabId) => void\n injectedTabs?: Array<{ id: string; label: string; priority?: number }>\n isLoadingInjectedTabs?: boolean\n hiddenTabIds?: string[]\n peopleCount?: number\n dealsCount?: number\n activitiesCount?: number\n filesCount?: number\n sectionAction?: SectionAction | null\n children: React.ReactNode\n}\n\nconst LEGACY_TAB_MAP: Record<string, CompanyTabId> = {\n notes: 'people',\n activities: 'activity-log',\n addresses: 'people',\n tasks: 'people',\n dashboard: 'people',\n 'dane-firmy': 'people',\n analysis: 'people',\n}\n\nexport function resolveLegacyTab(tab: string | null | undefined, knownTabIds?: Iterable<string>): CompanyTabId {\n if (!tab) return 'people'\n if (LEGACY_TAB_MAP[tab]) return LEGACY_TAB_MAP[tab]\n if ((COMPANY_DETAIL_TAB_IDS as readonly string[]).includes(tab) || (knownTabIds && new Set(knownTabIds).has(tab))) return tab\n return 'people'\n}\n\nfunction formatTabCount(count: number): string | number | undefined {\n if (count <= 0) return undefined\n return count > 999 ? '999+' : count\n}\n\nfunction DefaultCompanyDetailTabs({\n activeTab,\n onTabChange,\n injectedTabs = [],\n isLoadingInjectedTabs = false,\n hiddenTabIds = [],\n peopleCount = 0,\n dealsCount = 0,\n activitiesCount = 0,\n filesCount = 0,\n sectionAction = null,\n children,\n}: CompanyDetailTabsProps) {\n const t = useT()\n const { canViewDeals, isReady: isDealsAccessReady } = useDealsAccess()\n\n const builtInTabs: TabDef[] = React.useMemo(\n () => [\n {\n id: 'people',\n label: t('customers.companies.detail.tabs.people', 'People'),\n icon: <Users className=\"size-4\" />,\n count: formatTabCount(peopleCount),\n },\n ...(canViewDeals\n ? [\n {\n id: 'deals' as CompanyTabId,\n label: t('customers.companies.detail.tabs.deals', 'Deals'),\n icon: <Handshake className=\"size-4\" />,\n count: formatTabCount(dealsCount),\n },\n ]\n : []),\n {\n id: 'activity-log',\n label: t('customers.companies.detail.tabs.activityLog', 'Activity log'),\n icon: <Clock className=\"size-4\" />,\n count: formatTabCount(activitiesCount),\n },\n {\n id: 'changelog',\n label: t('customers.companies.detail.tabs.changelog', 'Changelog'),\n icon: <History className=\"size-4\" />,\n count: 'NEW',\n },\n {\n id: 'files',\n label: t('customers.companies.detail.tabs.files', 'Files'),\n icon: <Paperclip className=\"size-4\" />,\n count: formatTabCount(filesCount),\n },\n ],\n [t, canViewDeals, peopleCount, dealsCount, activitiesCount, filesCount],\n )\n\n const allTabs: TabDef[] = React.useMemo(() => {\n const hidden = new Set(hiddenTabIds)\n return [\n ...builtInTabs,\n ...injectedTabs.filter((tab, index) => !builtInTabs.some((native) => native.id === tab.id) && injectedTabs.findIndex((candidate) => candidate.id === tab.id) === index).map((tab) => ({\n id: tab.id as CompanyTabId,\n label: tab.label,\n priority: tab.priority,\n })),\n ]\n .sort((left, right) => (right.priority ?? 0) - (left.priority ?? 0))\n .filter((tab) => !hidden.has(tab.id))\n }, [builtInTabs, hiddenTabIds, injectedTabs])\n\n React.useEffect(() => {\n if (isLoadingInjectedTabs || !isDealsAccessReady || allTabs.some((tab) => tab.id === activeTab)) return\n const fallback = allTabs[0]?.id\n if (fallback) onTabChange(fallback)\n }, [activeTab, allTabs, isLoadingInjectedTabs, onTabChange, isDealsAccessReady])\n\n return (\n <div>\n {/* Tab navigation */}\n <div className=\"flex items-end justify-between gap-2 border-b\">\n <Tabs\n value={activeTab}\n onValueChange={(value) => onTabChange(value as CompanyTabId)}\n variant=\"underline\"\n className=\"min-w-0 flex-1\"\n >\n <TabsList\n aria-label={t('customers.companies.detail.tabs.label', 'Company detail sections')}\n className=\"-mb-px w-full overflow-x-auto border-b-0 px-1\"\n >\n {allTabs.map((tab) => (\n <TabsTrigger key={tab.id} value={tab.id} leading={tab.icon} count={tab.count}>\n {tab.label}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n {sectionAction ? (\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={sectionAction.onClick}\n disabled={sectionAction.disabled}\n className=\"mb-1.5 mr-1 shrink-0\"\n >\n <Plus className=\"mr-1.5 h-4 w-4\" />\n {sectionAction.label}\n </Button>\n ) : null}\n </div>\n\n {/* Tab content */}\n <div className=\"pt-6\" role=\"tabpanel\">\n {children}\n </div>\n </div>\n )\n}\n\nregisterComponent<CompanyDetailTabsProps>({\n id: COMPANY_DETAIL_TABS_COMPONENT_ID,\n component: DefaultCompanyDetailTabs,\n metadata: {\n module: 'customers',\n description: 'Company detail tab navigation and content.',\n },\n})\n\nexport function CompanyDetailTabs(props: CompanyDetailTabsProps) {\n const ResolvedTabs = useRegisteredComponent<CompanyDetailTabsProps>(\n COMPANY_DETAIL_TABS_COMPONENT_ID,\n DefaultCompanyDetailTabs,\n )\n return <ResolvedTabs {...props} />\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -74,9 +74,10 @@ function DefaultDealDetailTabs({
74
74
  ...builtInTabs,
75
75
  ...injectedTabs.filter((tab, index) => !builtInTabs.some((native) => native.id === tab.id) && injectedTabs.findIndex((candidate) => candidate.id === tab.id) === index).map((tab) => ({
76
76
  id: tab.id,
77
- label: tab.label
77
+ label: tab.label,
78
+ priority: tab.priority
78
79
  }))
79
- ].filter((tab) => !hidden.has(tab.id));
80
+ ].sort((left, right) => (right.priority ?? 0) - (left.priority ?? 0)).filter((tab) => !hidden.has(tab.id));
80
81
  }, [builtInTabs, hiddenTabIds, injectedTabs]);
81
82
  React.useEffect(() => {
82
83
  if (isLoadingInjectedTabs || allTabs.some((tab) => tab.id === activeTab)) return;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/components/detail/DealDetailTabs.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Activity, Building2, History, NotebookPen, Paperclip, Users } from 'lucide-react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { registerComponent } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { useRegisteredComponent } from '@open-mercato/ui/backend/injection/useRegisteredComponent'\nimport { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'\n\nexport const DEAL_DETAIL_TAB_IDS = ['activities', 'people', 'companies', 'notes', 'files', 'changelog'] as const\n\nexport type DealTabId =\n | 'activities'\n | 'people'\n | 'companies'\n | 'notes'\n | 'files'\n | 'changelog'\n | string\n\ntype TabDef = {\n id: DealTabId\n label: string\n icon?: React.ReactNode\n count?: React.ReactNode\n}\n\nexport const DEAL_DETAIL_TABS_COMPONENT_ID = 'section:customers.deals.detailTabs'\n\nexport type DealDetailTabsProps = {\n activeTab: DealTabId\n onTabChange: (tab: DealTabId) => void\n injectedTabs?: Array<{ id: string; label: string }>\n isLoadingInjectedTabs?: boolean\n hiddenTabIds?: string[]\n peopleCount?: number\n companiesCount?: number\n children: React.ReactNode\n}\n\nconst SUPPORTED_TAB_IDS = new Set<DealTabId>(['activities', 'people', 'companies', 'notes', 'files', 'changelog'])\n\nexport function resolveLegacyTab(tab: string | null | undefined, knownTabIds?: Iterable<string>): DealTabId {\n if (!tab) return 'activities'\n if (SUPPORTED_TAB_IDS.has(tab as DealTabId)) return tab as DealTabId\n if (knownTabIds && new Set(knownTabIds).has(tab)) return tab\n return 'activities'\n}\n\nfunction formatTabCount(count: number): string | number | undefined {\n if (count <= 0) return undefined\n return count > 999 ? '999+' : count\n}\n\nfunction DefaultDealDetailTabs({\n activeTab,\n onTabChange,\n injectedTabs = [],\n isLoadingInjectedTabs = false,\n hiddenTabIds = [],\n peopleCount = 0,\n companiesCount = 0,\n children,\n}: DealDetailTabsProps) {\n const t = useT()\n\n const builtInTabs = React.useMemo<TabDef[]>(\n () => [\n {\n id: 'activities',\n label: t('customers.deals.detail.tabs.activities', 'Activities'),\n icon: <Activity className=\"size-4\" />,\n },\n {\n id: 'people',\n label: t('customers.deals.detail.tabs.people', 'People'),\n icon: <Users className=\"size-4\" />,\n count: formatTabCount(peopleCount),\n },\n {\n id: 'companies',\n label: t('customers.deals.detail.tabs.companies', 'Companies'),\n icon: <Building2 className=\"size-4\" />,\n count: formatTabCount(companiesCount),\n },\n {\n id: 'notes',\n label: t('customers.deals.detail.tabs.notes', 'Notes'),\n icon: <NotebookPen className=\"size-4\" />,\n },\n {\n id: 'files',\n label: t('customers.deals.detail.tabs.files', 'Files'),\n icon: <Paperclip className=\"size-4\" />,\n },\n {\n id: 'changelog',\n label: t('customers.deals.detail.tabs.changelog', 'Changelog'),\n icon: <History className=\"size-4\" />,\n count: 'NEW',\n },\n ],\n [companiesCount, peopleCount, t],\n )\n\n const allTabs = React.useMemo<TabDef[]>(() => {\n const hidden = new Set(hiddenTabIds)\n return [\n ...builtInTabs,\n ...injectedTabs.filter((tab, index) => !builtInTabs.some((native) => native.id === tab.id) && injectedTabs.findIndex((candidate) => candidate.id === tab.id) === index).map((tab) => ({\n id: tab.id as DealTabId,\n label: tab.label,\n })),\n ].filter((tab) => !hidden.has(tab.id))\n }, [builtInTabs, hiddenTabIds, injectedTabs])\n\n React.useEffect(() => {\n if (isLoadingInjectedTabs || allTabs.some((tab) => tab.id === activeTab)) return\n const fallback = allTabs[0]?.id\n if (fallback) onTabChange(fallback)\n }, [activeTab, allTabs, isLoadingInjectedTabs, onTabChange])\n\n return (\n <div>\n <Tabs\n value={activeTab}\n onValueChange={(value) => onTabChange(value as DealTabId)}\n variant=\"underline\"\n >\n <TabsList\n aria-label={t('customers.deals.detail.tabs.label', 'Deal detail sections')}\n className=\"w-full overflow-x-auto\"\n >\n {allTabs.map((tab) => (\n <TabsTrigger key={tab.id} value={tab.id} leading={tab.icon} count={tab.count}>\n {tab.label}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n\n <div className=\"pt-5\" role=\"tabpanel\">\n {children}\n </div>\n </div>\n )\n}\n\nregisterComponent<DealDetailTabsProps>({\n id: DEAL_DETAIL_TABS_COMPONENT_ID,\n component: DefaultDealDetailTabs,\n metadata: {\n module: 'customers',\n description: 'Deal detail tab navigation and content.',\n },\n})\n\nexport function DealDetailTabs(props: DealDetailTabsProps) {\n const ResolvedTabs = useRegisteredComponent<DealDetailTabsProps>(\n DEAL_DETAIL_TABS_COMPONENT_ID,\n DefaultDealDetailTabs,\n )\n return <ResolvedTabs {...props} />\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Activity, Building2, History, NotebookPen, Paperclip, Users } from 'lucide-react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { registerComponent } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { useRegisteredComponent } from '@open-mercato/ui/backend/injection/useRegisteredComponent'\nimport { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'\n\nexport const DEAL_DETAIL_TAB_IDS = ['activities', 'people', 'companies', 'notes', 'files', 'changelog'] as const\n\nexport type DealTabId =\n | 'activities'\n | 'people'\n | 'companies'\n | 'notes'\n | 'files'\n | 'changelog'\n | string\n\ntype TabDef = {\n id: DealTabId\n label: string\n icon?: React.ReactNode\n count?: React.ReactNode\n priority?: number\n}\n\nexport const DEAL_DETAIL_TABS_COMPONENT_ID = 'section:customers.deals.detailTabs'\n\nexport type DealDetailTabsProps = {\n activeTab: DealTabId\n onTabChange: (tab: DealTabId) => void\n injectedTabs?: Array<{ id: string; label: string; priority?: number }>\n isLoadingInjectedTabs?: boolean\n hiddenTabIds?: string[]\n peopleCount?: number\n companiesCount?: number\n children: React.ReactNode\n}\n\nconst SUPPORTED_TAB_IDS = new Set<DealTabId>(['activities', 'people', 'companies', 'notes', 'files', 'changelog'])\n\nexport function resolveLegacyTab(tab: string | null | undefined, knownTabIds?: Iterable<string>): DealTabId {\n if (!tab) return 'activities'\n if (SUPPORTED_TAB_IDS.has(tab as DealTabId)) return tab as DealTabId\n if (knownTabIds && new Set(knownTabIds).has(tab)) return tab\n return 'activities'\n}\n\nfunction formatTabCount(count: number): string | number | undefined {\n if (count <= 0) return undefined\n return count > 999 ? '999+' : count\n}\n\nfunction DefaultDealDetailTabs({\n activeTab,\n onTabChange,\n injectedTabs = [],\n isLoadingInjectedTabs = false,\n hiddenTabIds = [],\n peopleCount = 0,\n companiesCount = 0,\n children,\n}: DealDetailTabsProps) {\n const t = useT()\n\n const builtInTabs = React.useMemo<TabDef[]>(\n () => [\n {\n id: 'activities',\n label: t('customers.deals.detail.tabs.activities', 'Activities'),\n icon: <Activity className=\"size-4\" />,\n },\n {\n id: 'people',\n label: t('customers.deals.detail.tabs.people', 'People'),\n icon: <Users className=\"size-4\" />,\n count: formatTabCount(peopleCount),\n },\n {\n id: 'companies',\n label: t('customers.deals.detail.tabs.companies', 'Companies'),\n icon: <Building2 className=\"size-4\" />,\n count: formatTabCount(companiesCount),\n },\n {\n id: 'notes',\n label: t('customers.deals.detail.tabs.notes', 'Notes'),\n icon: <NotebookPen className=\"size-4\" />,\n },\n {\n id: 'files',\n label: t('customers.deals.detail.tabs.files', 'Files'),\n icon: <Paperclip className=\"size-4\" />,\n },\n {\n id: 'changelog',\n label: t('customers.deals.detail.tabs.changelog', 'Changelog'),\n icon: <History className=\"size-4\" />,\n count: 'NEW',\n },\n ],\n [companiesCount, peopleCount, t],\n )\n\n const allTabs = React.useMemo<TabDef[]>(() => {\n const hidden = new Set(hiddenTabIds)\n return [\n ...builtInTabs,\n ...injectedTabs.filter((tab, index) => !builtInTabs.some((native) => native.id === tab.id) && injectedTabs.findIndex((candidate) => candidate.id === tab.id) === index).map((tab) => ({\n id: tab.id as DealTabId,\n label: tab.label,\n priority: tab.priority,\n })),\n ]\n .sort((left, right) => (right.priority ?? 0) - (left.priority ?? 0))\n .filter((tab) => !hidden.has(tab.id))\n }, [builtInTabs, hiddenTabIds, injectedTabs])\n\n React.useEffect(() => {\n if (isLoadingInjectedTabs || allTabs.some((tab) => tab.id === activeTab)) return\n const fallback = allTabs[0]?.id\n if (fallback) onTabChange(fallback)\n }, [activeTab, allTabs, isLoadingInjectedTabs, onTabChange])\n\n return (\n <div>\n <Tabs\n value={activeTab}\n onValueChange={(value) => onTabChange(value as DealTabId)}\n variant=\"underline\"\n >\n <TabsList\n aria-label={t('customers.deals.detail.tabs.label', 'Deal detail sections')}\n className=\"w-full overflow-x-auto\"\n >\n {allTabs.map((tab) => (\n <TabsTrigger key={tab.id} value={tab.id} leading={tab.icon} count={tab.count}>\n {tab.label}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n\n <div className=\"pt-5\" role=\"tabpanel\">\n {children}\n </div>\n </div>\n )\n}\n\nregisterComponent<DealDetailTabsProps>({\n id: DEAL_DETAIL_TABS_COMPONENT_ID,\n component: DefaultDealDetailTabs,\n metadata: {\n module: 'customers',\n description: 'Deal detail tab navigation and content.',\n },\n})\n\nexport function DealDetailTabs(props: DealDetailTabsProps) {\n const ResolvedTabs = useRegisteredComponent<DealDetailTabsProps>(\n DEAL_DETAIL_TABS_COMPONENT_ID,\n DefaultDealDetailTabs,\n )\n return <ResolvedTabs {...props} />\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -104,9 +104,10 @@ function DefaultPersonDetailTabs({
104
104
  ...builtInTabs,
105
105
  ...injectedTabs.filter((tab, index) => !builtInTabs.some((native) => native.id === tab.id) && injectedTabs.findIndex((candidate) => candidate.id === tab.id) === index).map((tab) => ({
106
106
  id: tab.id,
107
- label: tab.label
107
+ label: tab.label,
108
+ priority: tab.priority
108
109
  }))
109
- ].filter((tab) => !hidden.has(tab.id));
110
+ ].sort((left, right) => (right.priority ?? 0) - (left.priority ?? 0)).filter((tab) => !hidden.has(tab.id));
110
111
  }, [builtInTabs, hiddenTabIds, injectedTabs]);
111
112
  React.useEffect(() => {
112
113
  if (isLoadingInjectedTabs || allTabs.some((tab) => tab.id === activeTab)) return;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/components/detail/PersonDetailTabs.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'\nimport {\n SquareCheckBig,\n Mail,\n Briefcase,\n Building2,\n Check,\n History,\n Paperclip,\n Plus,\n MapPin,\n} from 'lucide-react'\nimport type { SectionAction } from '@open-mercato/ui/backend/detail'\nimport { registerComponent } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { useRegisteredComponent } from '@open-mercato/ui/backend/injection/useRegisteredComponent'\n\nexport const PERSON_DETAIL_TAB_IDS = ['activities', 'emails', 'deals', 'companies', 'addresses', 'tasks', 'changelog', 'files'] as const\n\nexport type PersonTabId =\n | 'activities'\n | 'emails'\n | 'deals'\n | 'companies'\n | 'addresses'\n | 'tasks'\n | 'changelog'\n | 'files'\n | string\n\ntype TabDef = {\n id: PersonTabId\n label: string\n icon?: React.ReactNode\n count?: React.ReactNode\n}\n\nexport const PERSON_DETAIL_TABS_COMPONENT_ID = 'section:customers.people.detailTabs'\n\nexport type PersonDetailTabsProps = {\n activeTab: PersonTabId\n onTabChange: (tab: PersonTabId) => void\n injectedTabs?: Array<{ id: string; label: string }>\n isLoadingInjectedTabs?: boolean\n hiddenTabIds?: string[]\n activitiesCount?: number\n dealsCount?: number\n companiesCount?: number\n addressesCount?: number\n tasksCount?: number\n filesCount?: number\n sectionAction?: SectionAction | null\n children: React.ReactNode\n}\n\nconst SUPPORTED_TAB_IDS = new Set<PersonTabId>(['activities', 'emails', 'deals', 'companies', 'addresses', 'tasks', 'changelog', 'files'])\n\nexport function resolveLegacyTab(tab: string | null | undefined, knownTabIds?: Iterable<string>): PersonTabId {\n if (!tab) return 'activities'\n if (SUPPORTED_TAB_IDS.has(tab as PersonTabId)) return tab as PersonTabId\n if (knownTabIds && new Set(knownTabIds).has(tab)) return tab\n return 'activities'\n}\n\nfunction formatTabCount(count: number): string | number | undefined {\n if (count <= 0) return undefined\n return count > 999 ? '999+' : count\n}\n\nfunction DefaultPersonDetailTabs({\n activeTab,\n onTabChange,\n injectedTabs = [],\n isLoadingInjectedTabs = false,\n hiddenTabIds = [],\n activitiesCount = 0,\n dealsCount = 0,\n companiesCount = 0,\n addressesCount = 0,\n tasksCount = 0,\n filesCount = 0,\n sectionAction = null,\n children,\n}: PersonDetailTabsProps) {\n const t = useT()\n\n const builtInTabs: TabDef[] = React.useMemo(\n () => [\n {\n id: 'activities',\n label: t('customers.people.detail.tabs.activities', 'Activities'),\n icon: <SquareCheckBig className=\"size-4\" />,\n count: formatTabCount(activitiesCount),\n },\n {\n id: 'emails',\n label: t('customers.people.detail.tabs.emails', 'Emails'),\n icon: <Mail className=\"size-4\" />,\n },\n {\n id: 'deals',\n label: t('customers.people.detail.tabs.deals', 'Deals'),\n icon: <Briefcase className=\"size-4\" />,\n count: formatTabCount(dealsCount),\n },\n {\n id: 'companies',\n label: t('customers.people.detail.tabs.companies', 'Companies'),\n icon: <Building2 className=\"size-4\" />,\n count: formatTabCount(companiesCount),\n },\n {\n id: 'addresses',\n label: t('customers.people.detail.tabs.addresses', 'Addresses'),\n icon: <MapPin className=\"size-4\" />,\n count: formatTabCount(addressesCount),\n },\n {\n id: 'tasks',\n label: t('customers.people.detail.tabs.tasks', 'Tasks'),\n icon: <Check className=\"size-4\" />,\n count: formatTabCount(tasksCount),\n },\n {\n id: 'changelog',\n label: t('customers.people.detail.tabs.changelog', 'Change log'),\n icon: <History className=\"size-4\" />,\n count: 'NEW',\n },\n {\n id: 'files',\n label: t('customers.people.detail.tabs.files', 'Files'),\n icon: <Paperclip className=\"size-4\" />,\n count: formatTabCount(filesCount),\n },\n ],\n [t, activitiesCount, dealsCount, companiesCount, addressesCount, tasksCount, filesCount],\n )\n\n const allTabs: TabDef[] = React.useMemo(() => {\n const hidden = new Set(hiddenTabIds)\n return [\n ...builtInTabs,\n ...injectedTabs.filter((tab, index) => !builtInTabs.some((native) => native.id === tab.id) && injectedTabs.findIndex((candidate) => candidate.id === tab.id) === index).map((tab) => ({\n id: tab.id as PersonTabId,\n label: tab.label,\n })),\n ].filter((tab) => !hidden.has(tab.id))\n }, [builtInTabs, hiddenTabIds, injectedTabs])\n\n React.useEffect(() => {\n if (isLoadingInjectedTabs || allTabs.some((tab) => tab.id === activeTab)) return\n const fallback = allTabs[0]?.id\n if (fallback) onTabChange(fallback)\n }, [activeTab, allTabs, isLoadingInjectedTabs, onTabChange])\n\n return (\n <div>\n {/* Tab navigation \u2014 full width above both zones */}\n <div className=\"flex items-end justify-between gap-2 border-b\">\n <Tabs\n value={activeTab}\n onValueChange={(value) => onTabChange(value as PersonTabId)}\n variant=\"underline\"\n className=\"min-w-0 flex-1\"\n >\n <TabsList\n aria-label={t('customers.people.detail.tabs.label', 'Person detail sections')}\n className=\"-mb-px w-full overflow-x-auto border-b-0 px-1\"\n >\n {allTabs.map((tab) => (\n <TabsTrigger key={tab.id} value={tab.id} leading={tab.icon} count={tab.count}>\n {tab.label}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n {sectionAction ? (\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={sectionAction.onClick}\n disabled={sectionAction.disabled}\n className=\"mb-1.5 mr-1 shrink-0\"\n >\n <Plus className=\"mr-1.5 h-4 w-4\" />\n {sectionAction.label}\n </Button>\n ) : null}\n </div>\n\n {/* Two-column content below tabs */}\n <div className=\"pt-6\">\n {children}\n </div>\n </div>\n )\n}\n\nregisterComponent<PersonDetailTabsProps>({\n id: PERSON_DETAIL_TABS_COMPONENT_ID,\n component: DefaultPersonDetailTabs,\n metadata: {\n module: 'customers',\n description: 'Person detail tab navigation and content.',\n },\n})\n\nexport function PersonDetailTabs(props: PersonDetailTabsProps) {\n const ResolvedTabs = useRegisteredComponent<PersonDetailTabsProps>(\n PERSON_DETAIL_TABS_COMPONENT_ID,\n DefaultPersonDetailTabs,\n )\n return <ResolvedTabs {...props} />\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'\nimport {\n SquareCheckBig,\n Mail,\n Briefcase,\n Building2,\n Check,\n History,\n Paperclip,\n Plus,\n MapPin,\n} from 'lucide-react'\nimport type { SectionAction } from '@open-mercato/ui/backend/detail'\nimport { registerComponent } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { useRegisteredComponent } from '@open-mercato/ui/backend/injection/useRegisteredComponent'\n\nexport const PERSON_DETAIL_TAB_IDS = ['activities', 'emails', 'deals', 'companies', 'addresses', 'tasks', 'changelog', 'files'] as const\n\nexport type PersonTabId =\n | 'activities'\n | 'emails'\n | 'deals'\n | 'companies'\n | 'addresses'\n | 'tasks'\n | 'changelog'\n | 'files'\n | string\n\ntype TabDef = {\n id: PersonTabId\n label: string\n icon?: React.ReactNode\n count?: React.ReactNode\n priority?: number\n}\n\nexport const PERSON_DETAIL_TABS_COMPONENT_ID = 'section:customers.people.detailTabs'\n\nexport type PersonDetailTabsProps = {\n activeTab: PersonTabId\n onTabChange: (tab: PersonTabId) => void\n injectedTabs?: Array<{ id: string; label: string; priority?: number }>\n isLoadingInjectedTabs?: boolean\n hiddenTabIds?: string[]\n activitiesCount?: number\n dealsCount?: number\n companiesCount?: number\n addressesCount?: number\n tasksCount?: number\n filesCount?: number\n sectionAction?: SectionAction | null\n children: React.ReactNode\n}\n\nconst SUPPORTED_TAB_IDS = new Set<PersonTabId>(['activities', 'emails', 'deals', 'companies', 'addresses', 'tasks', 'changelog', 'files'])\n\nexport function resolveLegacyTab(tab: string | null | undefined, knownTabIds?: Iterable<string>): PersonTabId {\n if (!tab) return 'activities'\n if (SUPPORTED_TAB_IDS.has(tab as PersonTabId)) return tab as PersonTabId\n if (knownTabIds && new Set(knownTabIds).has(tab)) return tab\n return 'activities'\n}\n\nfunction formatTabCount(count: number): string | number | undefined {\n if (count <= 0) return undefined\n return count > 999 ? '999+' : count\n}\n\nfunction DefaultPersonDetailTabs({\n activeTab,\n onTabChange,\n injectedTabs = [],\n isLoadingInjectedTabs = false,\n hiddenTabIds = [],\n activitiesCount = 0,\n dealsCount = 0,\n companiesCount = 0,\n addressesCount = 0,\n tasksCount = 0,\n filesCount = 0,\n sectionAction = null,\n children,\n}: PersonDetailTabsProps) {\n const t = useT()\n\n const builtInTabs: TabDef[] = React.useMemo(\n () => [\n {\n id: 'activities',\n label: t('customers.people.detail.tabs.activities', 'Activities'),\n icon: <SquareCheckBig className=\"size-4\" />,\n count: formatTabCount(activitiesCount),\n },\n {\n id: 'emails',\n label: t('customers.people.detail.tabs.emails', 'Emails'),\n icon: <Mail className=\"size-4\" />,\n },\n {\n id: 'deals',\n label: t('customers.people.detail.tabs.deals', 'Deals'),\n icon: <Briefcase className=\"size-4\" />,\n count: formatTabCount(dealsCount),\n },\n {\n id: 'companies',\n label: t('customers.people.detail.tabs.companies', 'Companies'),\n icon: <Building2 className=\"size-4\" />,\n count: formatTabCount(companiesCount),\n },\n {\n id: 'addresses',\n label: t('customers.people.detail.tabs.addresses', 'Addresses'),\n icon: <MapPin className=\"size-4\" />,\n count: formatTabCount(addressesCount),\n },\n {\n id: 'tasks',\n label: t('customers.people.detail.tabs.tasks', 'Tasks'),\n icon: <Check className=\"size-4\" />,\n count: formatTabCount(tasksCount),\n },\n {\n id: 'changelog',\n label: t('customers.people.detail.tabs.changelog', 'Change log'),\n icon: <History className=\"size-4\" />,\n count: 'NEW',\n },\n {\n id: 'files',\n label: t('customers.people.detail.tabs.files', 'Files'),\n icon: <Paperclip className=\"size-4\" />,\n count: formatTabCount(filesCount),\n },\n ],\n [t, activitiesCount, dealsCount, companiesCount, addressesCount, tasksCount, filesCount],\n )\n\n const allTabs: TabDef[] = React.useMemo(() => {\n const hidden = new Set(hiddenTabIds)\n return [\n ...builtInTabs,\n ...injectedTabs.filter((tab, index) => !builtInTabs.some((native) => native.id === tab.id) && injectedTabs.findIndex((candidate) => candidate.id === tab.id) === index).map((tab) => ({\n id: tab.id as PersonTabId,\n label: tab.label,\n priority: tab.priority,\n })),\n ]\n .sort((left, right) => (right.priority ?? 0) - (left.priority ?? 0))\n .filter((tab) => !hidden.has(tab.id))\n }, [builtInTabs, hiddenTabIds, injectedTabs])\n\n React.useEffect(() => {\n if (isLoadingInjectedTabs || allTabs.some((tab) => tab.id === activeTab)) return\n const fallback = allTabs[0]?.id\n if (fallback) onTabChange(fallback)\n }, [activeTab, allTabs, isLoadingInjectedTabs, onTabChange])\n\n return (\n <div>\n {/* Tab navigation \u2014 full width above both zones */}\n <div className=\"flex items-end justify-between gap-2 border-b\">\n <Tabs\n value={activeTab}\n onValueChange={(value) => onTabChange(value as PersonTabId)}\n variant=\"underline\"\n className=\"min-w-0 flex-1\"\n >\n <TabsList\n aria-label={t('customers.people.detail.tabs.label', 'Person detail sections')}\n className=\"-mb-px w-full overflow-x-auto border-b-0 px-1\"\n >\n {allTabs.map((tab) => (\n <TabsTrigger key={tab.id} value={tab.id} leading={tab.icon} count={tab.count}>\n {tab.label}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n {sectionAction ? (\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={sectionAction.onClick}\n disabled={sectionAction.disabled}\n className=\"mb-1.5 mr-1 shrink-0\"\n >\n <Plus className=\"mr-1.5 h-4 w-4\" />\n {sectionAction.label}\n </Button>\n ) : null}\n </div>\n\n {/* Two-column content below tabs */}\n <div className=\"pt-6\">\n {children}\n </div>\n </div>\n )\n}\n\nregisterComponent<PersonDetailTabsProps>({\n id: PERSON_DETAIL_TABS_COMPONENT_ID,\n component: DefaultPersonDetailTabs,\n metadata: {\n module: 'customers',\n description: 'Person detail tab navigation and content.',\n },\n})\n\nexport function PersonDetailTabs(props: PersonDetailTabsProps) {\n const ResolvedTabs = useRegisteredComponent<PersonDetailTabsProps>(\n PERSON_DETAIL_TABS_COMPONENT_ID,\n DefaultPersonDetailTabs,\n )\n return <ResolvedTabs {...props} />\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -360,7 +360,7 @@ function buildDocumentCrudOptions(binding) {
360
360
  indexer: {
361
361
  entityType: binding.entityId
362
362
  },
363
- enrichers: binding.kind === "order" ? { entityId: binding.entityId } : void 0,
363
+ enrichers: { entityId: binding.entityId },
364
364
  list: {
365
365
  schema: listSchema,
366
366
  entityId: binding.entityId,