@open-mercato/core 0.5.1-develop.3045.b4b3320cc2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/AGENTS.md +21 -1
- package/dist/modules/api_keys/api/keys/route.js +9 -0
- package/dist/modules/api_keys/api/keys/route.js.map +2 -2
- package/dist/modules/audit_logs/services/accessLogService.js +13 -0
- package/dist/modules/audit_logs/services/accessLogService.js.map +3 -3
- package/dist/modules/audit_logs/services/actionLogService.js +6 -5
- package/dist/modules/audit_logs/services/actionLogService.js.map +2 -2
- package/dist/modules/auth/api/roles/acl/route.js +27 -37
- package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +41 -28
- package/dist/modules/auth/api/users/route.js.map +3 -3
- package/dist/modules/auth/lib/grantChecks.js +160 -0
- package/dist/modules/auth/lib/grantChecks.js.map +7 -0
- package/dist/modules/configs/cli.js +11 -0
- package/dist/modules/configs/cli.js.map +2 -2
- package/dist/modules/configs/lib/touchGeneratedBarrels.js +46 -0
- package/dist/modules/configs/lib/touchGeneratedBarrels.js.map +7 -0
- package/dist/modules/customers/api/activities/route.js +1 -52
- package/dist/modules/customers/api/activities/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/counts/route.js +2 -1
- package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +21 -1
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +7 -3
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +5 -1
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +7 -3
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivitiesCard.js +62 -6
- package/dist/modules/customers/components/detail/ActivitiesCard.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivitiesDayStrip.js +21 -6
- package/dist/modules/customers/components/detail/ActivitiesDayStrip.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivitiesSection.js +37 -5
- package/dist/modules/customers/components/detail/ActivitiesSection.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityCard.js +69 -17
- package/dist/modules/customers/components/detail/ActivityCard.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityHistorySection.js +94 -34
- package/dist/modules/customers/components/detail/ActivityHistorySection.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityLogTab.js +3 -1
- package/dist/modules/customers/components/detail/ActivityLogTab.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityTimeline.js +41 -8
- package/dist/modules/customers/components/detail/ActivityTimeline.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityTimelineFilters.js +19 -6
- package/dist/modules/customers/components/detail/ActivityTimelineFilters.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityTypeSelector.js +4 -3
- package/dist/modules/customers/components/detail/ActivityTypeSelector.js.map +2 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +80 -12
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/DateTimeFields.js +65 -10
- package/dist/modules/customers/components/detail/schedule/DateTimeFields.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +10 -5
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
- package/dist/modules/customers/data/validators.js +74 -2
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/lib/legacyActivityBridge.js +61 -0
- package/dist/modules/customers/lib/legacyActivityBridge.js.map +7 -0
- package/dist/modules/integrations/data/validators.js +2 -2
- package/dist/modules/integrations/data/validators.js.map +2 -2
- package/dist/modules/integrations/lib/credentials-service.js +12 -1
- package/dist/modules/integrations/lib/credentials-service.js.map +2 -2
- package/dist/modules/messages/commands/actions.js +29 -14
- package/dist/modules/messages/commands/actions.js.map +2 -2
- package/dist/modules/messages/lib/actions.js +24 -4
- package/dist/modules/messages/lib/actions.js.map +2 -2
- package/dist/modules/sales/api/documents/factory.js +49 -36
- package/dist/modules/sales/api/documents/factory.js.map +2 -2
- package/package.json +9 -10
- package/src/modules/api_keys/api/keys/route.ts +9 -0
- package/src/modules/audit_logs/services/accessLogService.ts +20 -0
- package/src/modules/audit_logs/services/actionLogService.ts +13 -5
- package/src/modules/auth/api/roles/acl/route.ts +32 -46
- package/src/modules/auth/api/users/route.ts +48 -33
- package/src/modules/auth/lib/grantChecks.ts +234 -0
- package/src/modules/configs/cli.ts +11 -0
- package/src/modules/configs/lib/touchGeneratedBarrels.ts +61 -0
- package/src/modules/customers/api/activities/route.ts +1 -76
- package/src/modules/customers/api/interactions/counts/route.ts +2 -1
- package/src/modules/customers/api/interactions/route.ts +28 -1
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +13 -3
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +14 -2
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +13 -3
- package/src/modules/customers/components/detail/ActivitiesCard.tsx +92 -5
- package/src/modules/customers/components/detail/ActivitiesDayStrip.tsx +38 -6
- package/src/modules/customers/components/detail/ActivitiesSection.tsx +37 -3
- package/src/modules/customers/components/detail/ActivityCard.tsx +79 -14
- package/src/modules/customers/components/detail/ActivityHistorySection.tsx +102 -33
- package/src/modules/customers/components/detail/ActivityLogTab.tsx +7 -1
- package/src/modules/customers/components/detail/ActivityTimeline.tsx +39 -5
- package/src/modules/customers/components/detail/ActivityTimelineFilters.tsx +29 -7
- package/src/modules/customers/components/detail/ActivityTypeSelector.tsx +3 -2
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +96 -13
- package/src/modules/customers/components/detail/schedule/DateTimeFields.tsx +50 -4
- package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +21 -5
- package/src/modules/customers/data/validators.ts +85 -2
- package/src/modules/customers/i18n/de.json +11 -0
- package/src/modules/customers/i18n/en.json +11 -0
- package/src/modules/customers/i18n/es.json +11 -0
- package/src/modules/customers/i18n/pl.json +11 -0
- package/src/modules/customers/lib/legacyActivityBridge.ts +106 -0
- package/src/modules/integrations/data/validators.ts +8 -6
- package/src/modules/integrations/lib/credentials-service.ts +15 -1
- package/src/modules/messages/commands/actions.ts +28 -13
- package/src/modules/messages/lib/actions.ts +34 -3
- package/src/modules/sales/api/documents/factory.ts +55 -38
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/customers/backend/customers/deals/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Building2, Users } from 'lucide-react'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, NotesSection } from '@open-mercato/ui/backend/detail'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { CollapsibleZoneLayout } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { E } from '#generated/entities.ids.generated'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { DealClosureActionBar } from '../../../../components/detail/DealClosureActionBar'\nimport { DealDetailHeader } from '../../../../components/detail/DealDetailHeader'\nimport { DealDetailTabs, resolveLegacyTab, type DealTabId } from '../../../../components/detail/DealDetailTabs'\nimport { DealForm, useDealAssociationLookups } from '../../../../components/detail/DealForm'\nimport { DealLinkedEntitiesTab } from '../../../../components/detail/DealLinkedEntitiesTab'\nimport { ConfirmDealLostDialog } from '../../../../components/detail/ConfirmDealLostDialog'\nimport { DealLostSummaryDialog } from '../../../../components/detail/DealLostSummaryDialog'\nimport { DealWonPopup } from '../../../../components/detail/DealWonPopup'\nimport { InlineActivityComposer } from '../../../../components/detail/InlineActivityComposer'\nimport { PipelineStepper } from '../../../../components/detail/PipelineStepper'\nimport { PlannedActivitiesSection } from '../../../../components/detail/PlannedActivitiesSection'\nimport { ScheduleActivityDialog } from '../../../../components/detail/ScheduleActivityDialog'\nimport { createCustomerNotesAdapter } from '../../../../components/detail/notesAdapter'\nimport type { InteractionSummary } from '../../../../components/detail/types'\nimport { readMarkdownPreferenceCookie, writeMarkdownPreferenceCookie } from '../../../../lib/markdownPreference'\nimport { ICON_SUGGESTIONS } from '../../../../lib/dictionaries'\nimport { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\n\nimport { formatCurrency, startOfNextQuarter } from './hooks/formatters'\nimport type { DealDetailPayload } from './hooks/types'\nimport { useDealActivities } from './hooks/useDealActivities'\nimport { useDealAssociations } from './hooks/useDealAssociations'\nimport { useDealClosure } from './hooks/useDealClosure'\nimport { useDealData } from './hooks/useDealData'\nimport { useDealFormHandlers } from './hooks/useDealFormHandlers'\nimport { useDealInjectedTabs } from './hooks/useDealInjectedTabs'\nimport { useDealMutationContext } from './hooks/useDealMutationContext'\nimport { useDealPipeline } from './hooks/useDealPipeline'\nimport { useScheduleDialog } from './hooks/useScheduleDialog'\n\nexport default function DealDetailPage({ params }: { params?: { id?: string } }) {\n const id = params?.id ?? ''\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n\n const { data, setData, isLoading, error, loadData } = useDealData(id)\n const [isDirty, setIsDirty] = React.useState(false)\n const {\n scheduleDialogOpen,\n scheduleEditData,\n openSchedule,\n openEdit: openScheduleEdit,\n closeSchedule,\n } = useScheduleDialog()\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n\n const initialTab = React.useMemo(() => resolveLegacyTab(searchParams?.get('tab')), [searchParams])\n const [activeTab, setActiveTab] = React.useState<DealTabId>(initialTab)\n\n React.useEffect(() => {\n setActiveTab(initialTab)\n }, [initialTab])\n\n const currentDealId = data?.deal.id ?? id\n const { injectionContext, runMutationWithContext } = useDealMutationContext({\n currentDealId,\n fallbackId: id,\n data,\n })\n\n const notesAdapter = React.useMemo(\n () => createCustomerNotesAdapter(detailTranslator, { runMutation: runMutationWithContext }),\n [detailTranslator, runMutationWithContext],\n )\n\n const { injectedTabs, injectedTabMap } = useDealInjectedTabs({\n injectionContext,\n data,\n setData,\n })\n\n const { searchPeoplePage, fetchPeopleByIds, searchCompaniesPage, fetchCompaniesByIds } = useDealAssociationLookups({\n excludeLinkedDealId: data?.deal.id ?? null,\n })\n\n const {\n plannedActivities,\n activityRefreshKey,\n loadPlannedActivities,\n handleActivityCreated,\n handleMarkDone,\n handleCancelActivity,\n } = useDealActivities({ dealId: id, runMutationWithContext })\n\n React.useEffect(() => {\n void Promise.all([loadData(), loadPlannedActivities()])\n }, [loadData, loadPlannedActivities])\n\n const activityEntities = React.useMemo(\n () => (data\n ? [...data.people, ...data.companies].map((entry) => ({\n id: entry.id,\n label: entry.subtitle ? `${entry.label} \u00B7 ${entry.subtitle}` : entry.label,\n kind: entry.kind,\n }))\n : []),\n [data],\n )\n const [selectedActivityEntityId, setSelectedActivityEntityId] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n setSelectedActivityEntityId((current) => {\n if (activityEntities.length === 1) return activityEntities[0].id\n if (current && activityEntities.some((entry) => entry.id === current)) return current\n return null\n })\n }, [activityEntities])\n\n const selectedActivityEntity = React.useMemo(\n () => activityEntities.find((entry) => entry.id === selectedActivityEntityId) ?? null,\n [activityEntities, selectedActivityEntityId],\n )\n\n const dealOptions = React.useMemo(\n () => data ? [{ id: data.deal.id, label: data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal') }] : [],\n [data, t],\n )\n\n const entityOptions = React.useMemo(\n () => activityEntities.map(({ id, label }) => ({ id, label })),\n [activityEntities],\n )\n\n const confirmDiscardIfDirty = React.useCallback(async () => {\n if (!isDirty) return true\n return confirm({\n title: t('customers.deals.detail.unsavedTitle', 'Discard unsaved changes?'),\n description: t(\n 'customers.deals.detail.unsavedDescription',\n 'You have unsaved edits in this deal. Save them first or continue to discard them.',\n ),\n confirmText: t('customers.deals.detail.unsavedConfirm', 'Discard changes'),\n cancelText: t('customers.deals.detail.unsavedCancel', 'Keep editing'),\n variant: 'destructive',\n })\n }, [confirm, isDirty, t])\n\n const {\n peopleEditorIds,\n companiesEditorIds,\n peopleSaving,\n companiesSaving,\n handlePeopleAssociationsChange,\n handleCompaniesAssociationsChange,\n loadLinkedPeoplePage,\n loadLinkedCompaniesPage,\n } = useDealAssociations({\n currentDealId,\n data,\n setData,\n runMutationWithContext,\n })\n\n const { isStageSaving, handleStageChange } = useDealPipeline({\n currentDealId,\n data,\n runMutationWithContext,\n confirmDiscardIfDirty,\n onStageChanged: loadData,\n })\n\n const {\n lostDialogOpen,\n wonPopupOpen,\n lostPopupOpen,\n wonStats,\n lostStats,\n openLostDialog,\n closeLostDialog,\n closeWonPopup,\n closeLostPopup,\n handleWon,\n handleLostConfirm,\n } = useDealClosure({\n currentDealId,\n runMutationWithContext,\n confirmDiscardIfDirty,\n onClosed: loadData,\n })\n\n const handleTabChange = React.useCallback(async (tab: DealTabId) => {\n if (!(await confirmDiscardIfDirty())) return\n setActiveTab(tab)\n const nextParams = new URLSearchParams(searchParams?.toString() ?? '')\n nextParams.set('tab', tab)\n router.replace(`/backend/customers/deals/${encodeURIComponent(id)}?${nextParams.toString()}`, { scroll: false })\n }, [confirmDiscardIfDirty, id, router, searchParams])\n\n const { isSaving, handleFormSubmit, handleDelete, handleHeaderSave } = useDealFormHandlers({\n data,\n currentDealId,\n loadData,\n runMutationWithContext,\n formWrapperRef,\n confirm,\n })\n\n const handleEditActivity = React.useCallback((activity: InteractionSummary) => {\n if (activity.entityId && activityEntities.some((entry) => entry.id === activity.entityId)) {\n setSelectedActivityEntityId(activity.entityId)\n }\n openScheduleEdit({\n id: activity.id,\n interactionType: activity.interactionType,\n title: activity.title ?? null,\n body: activity.body ?? null,\n scheduledAt: activity.scheduledAt ?? null,\n durationMinutes: activity.duration ?? null,\n location: activity.location ?? null,\n allDay: activity.allDay ?? null,\n recurrenceRule: activity.recurrenceRule ?? null,\n recurrenceEnd: activity.recurrenceEnd ?? null,\n participants: activity.participants ?? null,\n reminderMinutes: activity.reminderMinutes ?? null,\n visibility: activity.visibility ?? null,\n linkedEntities: activity.linkedEntities ?? null,\n guestPermissions: activity.guestPermissions ?? null,\n })\n }, [activityEntities, openScheduleEdit])\n\n const handleViewDashboard = React.useCallback(() => {\n closeWonPopup()\n router.push('/backend')\n }, [closeWonPopup, router])\n\n const handleBackToPipeline = React.useCallback(() => {\n closeWonPopup()\n closeLostPopup()\n router.push('/backend/customers/deals/pipeline')\n }, [closeLostPopup, closeWonPopup, router])\n\n const handleScheduleLostFollowUp = React.useCallback(() => {\n if (!data || !selectedActivityEntity) return\n const nextQuarterDate = startOfNextQuarter(new Date())\n closeLostPopup()\n openScheduleEdit({\n id: '',\n interactionType: 'task',\n title: data.deal.title\n ? t('customers.deals.detail.lost.followUpTitle', 'Revisit {{title}}', { title: data.deal.title })\n : t('customers.deals.detail.lost.followUpFallbackTitle', 'Revisit closed deal'),\n body: data.deal.lossNotes ?? null,\n scheduledAt: nextQuarterDate.toISOString(),\n durationMinutes: 30,\n location: null,\n allDay: false,\n recurrenceRule: null,\n recurrenceEnd: null,\n participants: null,\n reminderMinutes: 1440,\n visibility: 'team',\n linkedEntities: [\n {\n id: data.deal.id,\n type: 'deal',\n label: data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal'),\n },\n ],\n })\n }, [closeLostPopup, data, openScheduleEdit, selectedActivityEntity, t])\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.deals.detail.loading', 'Loading deal\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error || t('customers.deals.detail.error.notFound', 'Deal not found.')}\n action={(\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/customers/deals\">\n {t('customers.deals.detail.actions.backToList', 'Back to deals')}\n </Link>\n </Button>\n )}\n />\n </PageBody>\n </Page>\n )\n }\n\n const amountLabel = formatCurrency(data.deal.valueAmount, data.deal.valueCurrency)\n const currentPipelineName = data.pipelineName ?? wonStats?.pipelineName ?? lostStats?.pipelineName ?? null\n const dealName = data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')\n\n const zone1Content = (\n <div ref={formWrapperRef}>\n <DealForm\n mode=\"edit\"\n embedded\n trackDirtyWhenEmbedded\n hideFooterActions\n singleColumnGroups\n showAssociationsGroup={false}\n showVersionHistory={false}\n showCancelAction={false}\n onDirtyChange={setIsDirty}\n collapsibleGroups={{ pageType: 'deal-detail-v3', chevronPosition: 'left' }}\n sortableGroups={{ pageType: 'deal-detail-v3' }}\n initialValues={{\n ...data.deal,\n valueAmount:\n typeof data.deal.valueAmount === 'string' && data.deal.valueAmount.trim().length\n ? Number(data.deal.valueAmount)\n : null,\n personIds: data.linkedPersonIds,\n companyIds: data.linkedCompanyIds,\n customFields: data.customFields,\n ...Object.fromEntries(Object.entries(data.customFields ?? {}).map(([key, value]) => [`cf_${key}`, value])),\n }}\n onSubmit={handleFormSubmit}\n onCancel={() => { void loadData() }}\n onDelete={handleDelete}\n />\n </div>\n )\n\n const zone2Content = (\n <div className=\"rounded-[10px] border border-border bg-card px-5 py-5\">\n {(() => {\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n\n if (activeTab === 'activities') {\n const activityEntitySelection = activityEntities.length > 1 ? (\n <div className=\"rounded-[10px] border border-border bg-muted/20 px-5 py-5\">\n <label htmlFor=\"deal-activity-entity\" className=\"text-sm font-semibold text-foreground\">\n {t('customers.deals.detail.activities.selectEntityLabel', 'Choose customer record')}\n </label>\n <div className=\"mt-1 text-sm text-muted-foreground\">\n {t(\n 'customers.deals.detail.activities.selectEntityDescription',\n 'Pick the person or company that should own new deal activities and follow-ups.',\n )}\n </div>\n <select\n id=\"deal-activity-entity\"\n aria-label={t('customers.deals.detail.activities.selectEntityLabel', 'Choose customer record')}\n className=\"mt-4 h-9 w-full rounded border border-muted-foreground/40 bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n value={selectedActivityEntityId ?? ''}\n onChange={(event) => setSelectedActivityEntityId(event.target.value || null)}\n >\n <option value=\"\">\n {t('customers.deals.detail.activities.selectEntityPlaceholder', 'Select a person or company')}\n </option>\n {activityEntities.map((entry) => (\n <option key={entry.id} value={entry.id}>\n {entry.label}\n </option>\n ))}\n </select>\n </div>\n ) : null\n\n return (\n <div className=\"space-y-4\">\n {activityEntities.length > 1 ? activityEntitySelection : null}\n {activityEntities.length === 0 ? (\n <div className=\"rounded-[10px] border border-border bg-muted/20 px-5 py-5\">\n <div className=\"text-sm font-semibold text-foreground\">\n {t('customers.deals.detail.activities.linkEntityTitle', 'Link a person or company first')}\n </div>\n <div className=\"mt-1 text-sm text-muted-foreground\">\n {t('customers.deals.detail.activities.linkEntityDescription', 'Activities on a deal still need a customer record for timeline ownership.')}\n </div>\n <div className=\"mt-4 flex gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => handleTabChange('people')}>\n {t('customers.deals.detail.tabs.people', 'People')}\n </Button>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => handleTabChange('companies')}>\n {t('customers.deals.detail.tabs.companies', 'Companies')}\n </Button>\n </div>\n </div>\n ) : selectedActivityEntity ? (\n <InlineActivityComposer\n entityType={selectedActivityEntity.kind}\n entityId={selectedActivityEntity.id}\n dealId={data.deal.id}\n onActivityCreated={() => { void handleActivityCreated() }}\n runGuardedMutation={runMutationWithContext}\n onScheduleRequested={openSchedule}\n />\n ) : (\n <div className=\"rounded-[10px] border border-dashed border-border bg-muted/10 px-5 py-5\">\n <div className=\"text-sm font-semibold text-foreground\">\n {t('customers.deals.detail.activities.selectEntityRequiredTitle', 'Choose a person or company to continue')}\n </div>\n <div className=\"mt-1 text-sm text-muted-foreground\">\n {t(\n 'customers.deals.detail.activities.selectEntityRequiredDescription',\n 'Select the customer record that should receive new deal activities before logging or scheduling anything.',\n )}\n </div>\n </div>\n )}\n <PlannedActivitiesSection\n activities={plannedActivities}\n onComplete={(interactionId) => { void handleMarkDone(interactionId) }}\n onSchedule={selectedActivityEntity ? openSchedule : undefined}\n onEdit={handleEditActivity}\n onCancel={(interactionId) => { void handleCancelActivity(interactionId) }}\n />\n {selectedActivityEntity ? (\n <ActivitiesSection\n entityId={selectedActivityEntity.id}\n entityName={selectedActivityEntity.label}\n dealId={data.deal.id}\n dealOptions={dealOptions}\n entityOptions={entityOptions}\n defaultEntityId={selectedActivityEntity.id}\n addActionLabel={t('customers.deals.detail.activitiesAdd', 'Log activity')}\n emptyState={{\n title: t('customers.deals.detail.activitiesEmptyTitle', 'No activities yet'),\n actionLabel: t('customers.deals.detail.activitiesEmptyAction', 'Log activity'),\n }}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={() => { void handleActivityCreated() }}\n refreshKey={activityRefreshKey}\n onEditActivity={handleEditActivity}\n />\n ) : null}\n </div>\n )\n }\n\n if (activeTab === 'people') {\n return (\n <DealLinkedEntitiesTab\n entityLabel={t('customers.deals.detail.tabs.peopleSingular', 'Person')}\n entityLabelPlural={t('customers.deals.detail.tabs.people', 'People')}\n manageLabel={t('customers.deals.detail.peopleEditorTitle', 'Manage linked people')}\n searchPlaceholder={t('customers.deals.detail.peopleSearch', 'Search linked people\u2026')}\n linkedItems={data.people}\n linkedCount={data.counts.people}\n selectedIds={peopleEditorIds}\n disabled={peopleSaving || isSaving}\n savePending={peopleSaving}\n hrefBuilder={(personId) => `/backend/customers/people-v2/${encodeURIComponent(personId)}`}\n onSaveSelection={(next) => handlePeopleAssociationsChange(next)}\n loadLinkedPage={loadLinkedPeoplePage}\n searchEntities={searchPeoplePage}\n fetchEntitiesByIds={fetchPeopleByIds}\n icon={<Users className=\"size-4\" />}\n />\n )\n }\n\n if (activeTab === 'companies') {\n return (\n <DealLinkedEntitiesTab\n entityLabel={t('customers.deals.detail.tabs.companySingular', 'Company')}\n entityLabelPlural={t('customers.deals.detail.tabs.companies', 'Companies')}\n manageLabel={t('customers.deals.detail.companiesEditorTitle', 'Manage linked companies')}\n searchPlaceholder={t('customers.deals.detail.companiesSearch', 'Search linked companies\u2026')}\n linkedItems={data.companies}\n linkedCount={data.counts.companies}\n selectedIds={companiesEditorIds}\n disabled={companiesSaving || isSaving}\n savePending={companiesSaving}\n hrefBuilder={(companyId) => `/backend/customers/companies-v2/${encodeURIComponent(companyId)}`}\n onSaveSelection={(next) => handleCompaniesAssociationsChange(next)}\n loadLinkedPage={loadLinkedCompaniesPage}\n searchEntities={searchCompaniesPage}\n fetchEntitiesByIds={fetchCompaniesByIds}\n icon={<Building2 className=\"size-4\" />}\n />\n )\n }\n\n if (activeTab === 'notes') {\n return (\n <NotesSection\n entityId={null}\n dealId={data.deal.id}\n dealOptions={dealOptions}\n entityOptions={entityOptions}\n emptyLabel={t('customers.deals.detail.notesEmpty', 'No notes yet.')}\n viewerUserId={data.viewer?.userId ?? null}\n viewerName={data.viewer?.name ?? null}\n viewerEmail={data.viewer?.email ?? null}\n addActionLabel={t('customers.deals.detail.notesAdd', 'Add note')}\n emptyState={{\n title: t('customers.deals.detail.notesEmptyTitle', 'Keep everyone in the loop'),\n actionLabel: t('customers.deals.detail.notesEmptyAction', 'Add a note'),\n }}\n translator={detailTranslator}\n dataAdapter={notesAdapter}\n renderIcon={renderDictionaryIcon}\n renderColor={renderDictionaryColor}\n iconSuggestions={ICON_SUGGESTIONS}\n readMarkdownPreference={readMarkdownPreferenceCookie}\n writeMarkdownPreference={writeMarkdownPreferenceCookie}\n />\n )\n }\n\n if (activeTab === 'files') {\n return (\n <AttachmentsSection\n entityId={E.customers.customer_deal}\n recordId={data.deal.id}\n title={t('customers.deals.detail.tabs.files', 'Files')}\n description={t('customers.deals.detail.files.subtitle', 'Upload and manage files linked to this deal.')}\n />\n )\n }\n\n if (activeTab === 'changelog') {\n return <ChangelogTab entityId={data.deal.id} entityType=\"deal\" />\n }\n\n return null\n })()}\n </div>\n )\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <InjectionSpot spotId=\"detail:customers.deal:header\" context={injectionContext} data={data} />\n\n <DealDetailHeader\n deal={data.deal}\n owner={data.owner}\n people={data.people}\n companies={data.companies}\n pipelineName={currentPipelineName}\n stageOptions={data.pipelineStages}\n currentStageId={data.deal.pipelineStageId}\n onStageChange={handleStageChange}\n isStageSaving={isStageSaving}\n onSave={handleHeaderSave}\n onDelete={handleDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n />\n\n <InjectionSpot spotId=\"detail:customers.deal:status-badges\" context={injectionContext} data={data} />\n\n <PipelineStepper\n stages={data.pipelineStages}\n transitions={data.stageTransitions}\n currentStageId={data.deal.pipelineStageId}\n pipelineName={currentPipelineName}\n closureOutcome={data.deal.closureOutcome}\n footer={data.deal.closureOutcome ? null : (\n <DealClosureActionBar\n embedded\n closureOutcome={data.deal.closureOutcome}\n onWon={() => { void handleWon() }}\n onLost={openLostDialog}\n />\n )}\n />\n\n <DealDetailTabs\n activeTab={activeTab}\n onTabChange={handleTabChange}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n peopleCount={data.counts.people}\n companiesCount={data.counts.companies}\n >\n <CollapsibleZoneLayout\n pageType=\"deal-detail-v3\"\n entityName={dealName}\n isDirty={isDirty}\n zone1DefaultWidth=\"540px\"\n zone1={zone1Content}\n zone2={zone2Content}\n />\n </DealDetailTabs>\n\n <InjectionSpot spotId=\"detail:customers.deal:footer\" context={injectionContext} data={data} />\n </div>\n\n {ConfirmDialogElement}\n\n {selectedActivityEntity ? (\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={closeSchedule}\n entityId={selectedActivityEntity.id}\n dealId={data.deal.id}\n entityType={selectedActivityEntity.kind}\n entityName={selectedActivityEntity.label}\n companyName={selectedActivityEntity.kind === 'company' ? selectedActivityEntity.label : data.companies[0]?.label ?? null}\n onActivityCreated={() => { void handleActivityCreated() }}\n editData={scheduleEditData}\n />\n ) : null}\n\n <ConfirmDealLostDialog\n open={lostDialogOpen}\n onClose={closeLostDialog}\n dealTitle={data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')}\n dealValue={amountLabel}\n companyName={data.companies[0]?.label ?? null}\n onConfirm={handleLostConfirm}\n />\n\n <DealWonPopup\n open={wonPopupOpen}\n onClose={closeWonPopup}\n dealTitle={data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')}\n stats={wonStats}\n onViewDashboard={handleViewDashboard}\n onBackToPipeline={handleBackToPipeline}\n />\n\n <DealLostSummaryDialog\n open={lostPopupOpen}\n onClose={closeLostPopup}\n dealTitle={data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')}\n lossNotes={data.deal.lossNotes}\n stats={lostStats}\n onBackToPipeline={handleBackToPipeline}\n onScheduleFollowUp={selectedActivityEntity ? handleScheduleLostFollowUp : undefined}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Building2, Users } from 'lucide-react'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, NotesSection } from '@open-mercato/ui/backend/detail'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { CollapsibleZoneLayout } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { E } from '#generated/entities.ids.generated'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { DealClosureActionBar } from '../../../../components/detail/DealClosureActionBar'\nimport { DealDetailHeader } from '../../../../components/detail/DealDetailHeader'\nimport { DealDetailTabs, resolveLegacyTab, type DealTabId } from '../../../../components/detail/DealDetailTabs'\nimport { DealForm, useDealAssociationLookups } from '../../../../components/detail/DealForm'\nimport { DealLinkedEntitiesTab } from '../../../../components/detail/DealLinkedEntitiesTab'\nimport { ConfirmDealLostDialog } from '../../../../components/detail/ConfirmDealLostDialog'\nimport { DealLostSummaryDialog } from '../../../../components/detail/DealLostSummaryDialog'\nimport { DealWonPopup } from '../../../../components/detail/DealWonPopup'\nimport { InlineActivityComposer } from '../../../../components/detail/InlineActivityComposer'\nimport { PipelineStepper } from '../../../../components/detail/PipelineStepper'\nimport { PlannedActivitiesSection } from '../../../../components/detail/PlannedActivitiesSection'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { createCustomerNotesAdapter } from '../../../../components/detail/notesAdapter'\nimport type { InteractionSummary } from '../../../../components/detail/types'\nimport { readMarkdownPreferenceCookie, writeMarkdownPreferenceCookie } from '../../../../lib/markdownPreference'\nimport { ICON_SUGGESTIONS } from '../../../../lib/dictionaries'\nimport { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\n\nimport { formatCurrency, startOfNextQuarter } from './hooks/formatters'\nimport type { DealDetailPayload } from './hooks/types'\nimport { useDealActivities } from './hooks/useDealActivities'\nimport { useDealAssociations } from './hooks/useDealAssociations'\nimport { useDealClosure } from './hooks/useDealClosure'\nimport { useDealData } from './hooks/useDealData'\nimport { useDealFormHandlers } from './hooks/useDealFormHandlers'\nimport { useDealInjectedTabs } from './hooks/useDealInjectedTabs'\nimport { useDealMutationContext } from './hooks/useDealMutationContext'\nimport { useDealPipeline } from './hooks/useDealPipeline'\nimport { useScheduleDialog } from './hooks/useScheduleDialog'\n\nexport default function DealDetailPage({ params }: { params?: { id?: string } }) {\n const id = params?.id ?? ''\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n\n const { data, setData, isLoading, error, loadData } = useDealData(id)\n const [isDirty, setIsDirty] = React.useState(false)\n const {\n scheduleDialogOpen,\n scheduleEditData,\n openSchedule,\n openEdit: openScheduleEdit,\n closeSchedule,\n } = useScheduleDialog()\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n\n const initialTab = React.useMemo(() => resolveLegacyTab(searchParams?.get('tab')), [searchParams])\n const [activeTab, setActiveTab] = React.useState<DealTabId>(initialTab)\n\n React.useEffect(() => {\n setActiveTab(initialTab)\n }, [initialTab])\n\n const currentDealId = data?.deal.id ?? id\n const { injectionContext, runMutationWithContext } = useDealMutationContext({\n currentDealId,\n fallbackId: id,\n data,\n })\n\n const notesAdapter = React.useMemo(\n () => createCustomerNotesAdapter(detailTranslator, { runMutation: runMutationWithContext }),\n [detailTranslator, runMutationWithContext],\n )\n\n const { injectedTabs, injectedTabMap } = useDealInjectedTabs({\n injectionContext,\n data,\n setData,\n })\n\n const { searchPeoplePage, fetchPeopleByIds, searchCompaniesPage, fetchCompaniesByIds } = useDealAssociationLookups({\n excludeLinkedDealId: data?.deal.id ?? null,\n })\n\n const {\n plannedActivities,\n activityRefreshKey,\n loadPlannedActivities,\n handleActivityCreated,\n handleMarkDone,\n handleCancelActivity,\n } = useDealActivities({ dealId: id, runMutationWithContext })\n\n React.useEffect(() => {\n void Promise.all([loadData(), loadPlannedActivities()])\n }, [loadData, loadPlannedActivities])\n\n const activityEntities = React.useMemo(\n () => (data\n ? [...data.people, ...data.companies].map((entry) => ({\n id: entry.id,\n label: entry.subtitle ? `${entry.label} \u00B7 ${entry.subtitle}` : entry.label,\n kind: entry.kind,\n }))\n : []),\n [data],\n )\n const [selectedActivityEntityId, setSelectedActivityEntityId] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n setSelectedActivityEntityId((current) => {\n if (activityEntities.length === 1) return activityEntities[0].id\n if (current && activityEntities.some((entry) => entry.id === current)) return current\n return null\n })\n }, [activityEntities])\n\n const selectedActivityEntity = React.useMemo(\n () => activityEntities.find((entry) => entry.id === selectedActivityEntityId) ?? null,\n [activityEntities, selectedActivityEntityId],\n )\n\n const dealOptions = React.useMemo(\n () => data ? [{ id: data.deal.id, label: data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal') }] : [],\n [data, t],\n )\n\n const entityOptions = React.useMemo(\n () => activityEntities.map(({ id, label }) => ({ id, label })),\n [activityEntities],\n )\n\n const confirmDiscardIfDirty = React.useCallback(async () => {\n if (!isDirty) return true\n return confirm({\n title: t('customers.deals.detail.unsavedTitle', 'Discard unsaved changes?'),\n description: t(\n 'customers.deals.detail.unsavedDescription',\n 'You have unsaved edits in this deal. Save them first or continue to discard them.',\n ),\n confirmText: t('customers.deals.detail.unsavedConfirm', 'Discard changes'),\n cancelText: t('customers.deals.detail.unsavedCancel', 'Keep editing'),\n variant: 'destructive',\n })\n }, [confirm, isDirty, t])\n\n const {\n peopleEditorIds,\n companiesEditorIds,\n peopleSaving,\n companiesSaving,\n handlePeopleAssociationsChange,\n handleCompaniesAssociationsChange,\n loadLinkedPeoplePage,\n loadLinkedCompaniesPage,\n } = useDealAssociations({\n currentDealId,\n data,\n setData,\n runMutationWithContext,\n })\n\n const { isStageSaving, handleStageChange } = useDealPipeline({\n currentDealId,\n data,\n runMutationWithContext,\n confirmDiscardIfDirty,\n onStageChanged: loadData,\n })\n\n const {\n lostDialogOpen,\n wonPopupOpen,\n lostPopupOpen,\n wonStats,\n lostStats,\n openLostDialog,\n closeLostDialog,\n closeWonPopup,\n closeLostPopup,\n handleWon,\n handleLostConfirm,\n } = useDealClosure({\n currentDealId,\n runMutationWithContext,\n confirmDiscardIfDirty,\n onClosed: loadData,\n })\n\n const handleTabChange = React.useCallback(async (tab: DealTabId) => {\n if (!(await confirmDiscardIfDirty())) return\n setActiveTab(tab)\n const nextParams = new URLSearchParams(searchParams?.toString() ?? '')\n nextParams.set('tab', tab)\n router.replace(`/backend/customers/deals/${encodeURIComponent(id)}?${nextParams.toString()}`, { scroll: false })\n }, [confirmDiscardIfDirty, id, router, searchParams])\n\n const { isSaving, handleFormSubmit, handleDelete, handleHeaderSave } = useDealFormHandlers({\n data,\n currentDealId,\n loadData,\n runMutationWithContext,\n formWrapperRef,\n confirm,\n })\n\n const handleEditActivity = React.useCallback((activity: InteractionSummary) => {\n if (activity.entityId && activityEntities.some((entry) => entry.id === activity.entityId)) {\n setSelectedActivityEntityId(activity.entityId)\n }\n // Forward `customValues` so per-type chip state (callPhoneNumber,\n // callDirection, taskPriority) round-trips on edit (#1808 phone persistence).\n // Forward `occurredAt` so historical activity edits prefill from the\n // original moment instead of \"today\" (#1807 prefill).\n const rawActivity = activity as unknown as Record<string, unknown>\n openScheduleEdit({\n id: activity.id,\n interactionType: activity.interactionType,\n title: activity.title ?? null,\n body: activity.body ?? null,\n scheduledAt: activity.scheduledAt ?? null,\n occurredAt: activity.occurredAt ?? null,\n durationMinutes: activity.duration ?? null,\n location: activity.location ?? null,\n allDay: activity.allDay ?? null,\n recurrenceRule: activity.recurrenceRule ?? null,\n recurrenceEnd: activity.recurrenceEnd ?? null,\n participants: activity.participants ?? null,\n reminderMinutes: activity.reminderMinutes ?? null,\n visibility: activity.visibility ?? null,\n linkedEntities: activity.linkedEntities ?? null,\n guestPermissions: activity.guestPermissions ?? null,\n ...(rawActivity.customValues && typeof rawActivity.customValues === 'object'\n ? { customValues: rawActivity.customValues as Record<string, unknown> }\n : {}),\n ...(typeof rawActivity.phoneNumber === 'string'\n ? { phoneNumber: rawActivity.phoneNumber as string }\n : {}),\n } as ScheduleActivityEditData & { customValues?: Record<string, unknown> | null; phoneNumber?: string | null })\n }, [activityEntities, openScheduleEdit])\n\n const handleViewDashboard = React.useCallback(() => {\n closeWonPopup()\n router.push('/backend')\n }, [closeWonPopup, router])\n\n const handleBackToPipeline = React.useCallback(() => {\n closeWonPopup()\n closeLostPopup()\n router.push('/backend/customers/deals/pipeline')\n }, [closeLostPopup, closeWonPopup, router])\n\n const handleScheduleLostFollowUp = React.useCallback(() => {\n if (!data || !selectedActivityEntity) return\n const nextQuarterDate = startOfNextQuarter(new Date())\n closeLostPopup()\n openScheduleEdit({\n id: '',\n interactionType: 'task',\n title: data.deal.title\n ? t('customers.deals.detail.lost.followUpTitle', 'Revisit {{title}}', { title: data.deal.title })\n : t('customers.deals.detail.lost.followUpFallbackTitle', 'Revisit closed deal'),\n body: data.deal.lossNotes ?? null,\n scheduledAt: nextQuarterDate.toISOString(),\n durationMinutes: 30,\n location: null,\n allDay: false,\n recurrenceRule: null,\n recurrenceEnd: null,\n participants: null,\n reminderMinutes: 1440,\n visibility: 'team',\n linkedEntities: [\n {\n id: data.deal.id,\n type: 'deal',\n label: data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal'),\n },\n ],\n })\n }, [closeLostPopup, data, openScheduleEdit, selectedActivityEntity, t])\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.deals.detail.loading', 'Loading deal\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error || t('customers.deals.detail.error.notFound', 'Deal not found.')}\n action={(\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/customers/deals\">\n {t('customers.deals.detail.actions.backToList', 'Back to deals')}\n </Link>\n </Button>\n )}\n />\n </PageBody>\n </Page>\n )\n }\n\n const amountLabel = formatCurrency(data.deal.valueAmount, data.deal.valueCurrency)\n const currentPipelineName = data.pipelineName ?? wonStats?.pipelineName ?? lostStats?.pipelineName ?? null\n const dealName = data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')\n\n const zone1Content = (\n <div ref={formWrapperRef}>\n <DealForm\n mode=\"edit\"\n embedded\n trackDirtyWhenEmbedded\n hideFooterActions\n singleColumnGroups\n showAssociationsGroup={false}\n showVersionHistory={false}\n showCancelAction={false}\n onDirtyChange={setIsDirty}\n collapsibleGroups={{ pageType: 'deal-detail-v3', chevronPosition: 'left' }}\n sortableGroups={{ pageType: 'deal-detail-v3' }}\n initialValues={{\n ...data.deal,\n valueAmount:\n typeof data.deal.valueAmount === 'string' && data.deal.valueAmount.trim().length\n ? Number(data.deal.valueAmount)\n : null,\n personIds: data.linkedPersonIds,\n companyIds: data.linkedCompanyIds,\n customFields: data.customFields,\n ...Object.fromEntries(Object.entries(data.customFields ?? {}).map(([key, value]) => [`cf_${key}`, value])),\n }}\n onSubmit={handleFormSubmit}\n onCancel={() => { void loadData() }}\n onDelete={handleDelete}\n />\n </div>\n )\n\n const zone2Content = (\n <div className=\"rounded-[10px] border border-border bg-card px-5 py-5\">\n {(() => {\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n\n if (activeTab === 'activities') {\n const activityEntitySelection = activityEntities.length > 1 ? (\n <div className=\"rounded-[10px] border border-border bg-muted/20 px-5 py-5\">\n <label htmlFor=\"deal-activity-entity\" className=\"text-sm font-semibold text-foreground\">\n {t('customers.deals.detail.activities.selectEntityLabel', 'Choose customer record')}\n </label>\n <div className=\"mt-1 text-sm text-muted-foreground\">\n {t(\n 'customers.deals.detail.activities.selectEntityDescription',\n 'Pick the person or company that should own new deal activities and follow-ups.',\n )}\n </div>\n <select\n id=\"deal-activity-entity\"\n aria-label={t('customers.deals.detail.activities.selectEntityLabel', 'Choose customer record')}\n className=\"mt-4 h-9 w-full rounded border border-muted-foreground/40 bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n value={selectedActivityEntityId ?? ''}\n onChange={(event) => setSelectedActivityEntityId(event.target.value || null)}\n >\n <option value=\"\">\n {t('customers.deals.detail.activities.selectEntityPlaceholder', 'Select a person or company')}\n </option>\n {activityEntities.map((entry) => (\n <option key={entry.id} value={entry.id}>\n {entry.label}\n </option>\n ))}\n </select>\n </div>\n ) : null\n\n return (\n <div className=\"space-y-4\">\n {activityEntities.length > 1 ? activityEntitySelection : null}\n {activityEntities.length === 0 ? (\n <div className=\"rounded-[10px] border border-border bg-muted/20 px-5 py-5\">\n <div className=\"text-sm font-semibold text-foreground\">\n {t('customers.deals.detail.activities.linkEntityTitle', 'Link a person or company first')}\n </div>\n <div className=\"mt-1 text-sm text-muted-foreground\">\n {t('customers.deals.detail.activities.linkEntityDescription', 'Activities on a deal still need a customer record for timeline ownership.')}\n </div>\n <div className=\"mt-4 flex gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => handleTabChange('people')}>\n {t('customers.deals.detail.tabs.people', 'People')}\n </Button>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => handleTabChange('companies')}>\n {t('customers.deals.detail.tabs.companies', 'Companies')}\n </Button>\n </div>\n </div>\n ) : selectedActivityEntity ? (\n <InlineActivityComposer\n entityType={selectedActivityEntity.kind}\n entityId={selectedActivityEntity.id}\n dealId={data.deal.id}\n onActivityCreated={() => { void handleActivityCreated() }}\n runGuardedMutation={runMutationWithContext}\n onScheduleRequested={openSchedule}\n />\n ) : (\n <div className=\"rounded-[10px] border border-dashed border-border bg-muted/10 px-5 py-5\">\n <div className=\"text-sm font-semibold text-foreground\">\n {t('customers.deals.detail.activities.selectEntityRequiredTitle', 'Choose a person or company to continue')}\n </div>\n <div className=\"mt-1 text-sm text-muted-foreground\">\n {t(\n 'customers.deals.detail.activities.selectEntityRequiredDescription',\n 'Select the customer record that should receive new deal activities before logging or scheduling anything.',\n )}\n </div>\n </div>\n )}\n <PlannedActivitiesSection\n activities={plannedActivities}\n onComplete={(interactionId) => { void handleMarkDone(interactionId) }}\n onSchedule={selectedActivityEntity ? openSchedule : undefined}\n onEdit={handleEditActivity}\n onCancel={(interactionId) => { void handleCancelActivity(interactionId) }}\n />\n {selectedActivityEntity ? (\n <ActivitiesSection\n entityId={selectedActivityEntity.id}\n entityName={selectedActivityEntity.label}\n dealId={data.deal.id}\n dealOptions={dealOptions}\n entityOptions={entityOptions}\n defaultEntityId={selectedActivityEntity.id}\n addActionLabel={t('customers.deals.detail.activitiesAdd', 'Log activity')}\n emptyState={{\n title: t('customers.deals.detail.activitiesEmptyTitle', 'No activities yet'),\n actionLabel: t('customers.deals.detail.activitiesEmptyAction', 'Log activity'),\n }}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={() => { void handleActivityCreated() }}\n refreshKey={activityRefreshKey}\n onEditActivity={handleEditActivity}\n />\n ) : null}\n </div>\n )\n }\n\n if (activeTab === 'people') {\n return (\n <DealLinkedEntitiesTab\n entityLabel={t('customers.deals.detail.tabs.peopleSingular', 'Person')}\n entityLabelPlural={t('customers.deals.detail.tabs.people', 'People')}\n manageLabel={t('customers.deals.detail.peopleEditorTitle', 'Manage linked people')}\n searchPlaceholder={t('customers.deals.detail.peopleSearch', 'Search linked people\u2026')}\n linkedItems={data.people}\n linkedCount={data.counts.people}\n selectedIds={peopleEditorIds}\n disabled={peopleSaving || isSaving}\n savePending={peopleSaving}\n hrefBuilder={(personId) => `/backend/customers/people-v2/${encodeURIComponent(personId)}`}\n onSaveSelection={(next) => handlePeopleAssociationsChange(next)}\n loadLinkedPage={loadLinkedPeoplePage}\n searchEntities={searchPeoplePage}\n fetchEntitiesByIds={fetchPeopleByIds}\n icon={<Users className=\"size-4\" />}\n />\n )\n }\n\n if (activeTab === 'companies') {\n return (\n <DealLinkedEntitiesTab\n entityLabel={t('customers.deals.detail.tabs.companySingular', 'Company')}\n entityLabelPlural={t('customers.deals.detail.tabs.companies', 'Companies')}\n manageLabel={t('customers.deals.detail.companiesEditorTitle', 'Manage linked companies')}\n searchPlaceholder={t('customers.deals.detail.companiesSearch', 'Search linked companies\u2026')}\n linkedItems={data.companies}\n linkedCount={data.counts.companies}\n selectedIds={companiesEditorIds}\n disabled={companiesSaving || isSaving}\n savePending={companiesSaving}\n hrefBuilder={(companyId) => `/backend/customers/companies-v2/${encodeURIComponent(companyId)}`}\n onSaveSelection={(next) => handleCompaniesAssociationsChange(next)}\n loadLinkedPage={loadLinkedCompaniesPage}\n searchEntities={searchCompaniesPage}\n fetchEntitiesByIds={fetchCompaniesByIds}\n icon={<Building2 className=\"size-4\" />}\n />\n )\n }\n\n if (activeTab === 'notes') {\n return (\n <NotesSection\n entityId={null}\n dealId={data.deal.id}\n dealOptions={dealOptions}\n entityOptions={entityOptions}\n emptyLabel={t('customers.deals.detail.notesEmpty', 'No notes yet.')}\n viewerUserId={data.viewer?.userId ?? null}\n viewerName={data.viewer?.name ?? null}\n viewerEmail={data.viewer?.email ?? null}\n addActionLabel={t('customers.deals.detail.notesAdd', 'Add note')}\n emptyState={{\n title: t('customers.deals.detail.notesEmptyTitle', 'Keep everyone in the loop'),\n actionLabel: t('customers.deals.detail.notesEmptyAction', 'Add a note'),\n }}\n translator={detailTranslator}\n dataAdapter={notesAdapter}\n renderIcon={renderDictionaryIcon}\n renderColor={renderDictionaryColor}\n iconSuggestions={ICON_SUGGESTIONS}\n readMarkdownPreference={readMarkdownPreferenceCookie}\n writeMarkdownPreference={writeMarkdownPreferenceCookie}\n />\n )\n }\n\n if (activeTab === 'files') {\n return (\n <AttachmentsSection\n entityId={E.customers.customer_deal}\n recordId={data.deal.id}\n title={t('customers.deals.detail.tabs.files', 'Files')}\n description={t('customers.deals.detail.files.subtitle', 'Upload and manage files linked to this deal.')}\n />\n )\n }\n\n if (activeTab === 'changelog') {\n return <ChangelogTab entityId={data.deal.id} entityType=\"deal\" />\n }\n\n return null\n })()}\n </div>\n )\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <InjectionSpot spotId=\"detail:customers.deal:header\" context={injectionContext} data={data} />\n\n <DealDetailHeader\n deal={data.deal}\n owner={data.owner}\n people={data.people}\n companies={data.companies}\n pipelineName={currentPipelineName}\n stageOptions={data.pipelineStages}\n currentStageId={data.deal.pipelineStageId}\n onStageChange={handleStageChange}\n isStageSaving={isStageSaving}\n onSave={handleHeaderSave}\n onDelete={handleDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n />\n\n <InjectionSpot spotId=\"detail:customers.deal:status-badges\" context={injectionContext} data={data} />\n\n <PipelineStepper\n stages={data.pipelineStages}\n transitions={data.stageTransitions}\n currentStageId={data.deal.pipelineStageId}\n pipelineName={currentPipelineName}\n closureOutcome={data.deal.closureOutcome}\n footer={data.deal.closureOutcome ? null : (\n <DealClosureActionBar\n embedded\n closureOutcome={data.deal.closureOutcome}\n onWon={() => { void handleWon() }}\n onLost={openLostDialog}\n />\n )}\n />\n\n <DealDetailTabs\n activeTab={activeTab}\n onTabChange={handleTabChange}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n peopleCount={data.counts.people}\n companiesCount={data.counts.companies}\n >\n <CollapsibleZoneLayout\n pageType=\"deal-detail-v3\"\n entityName={dealName}\n isDirty={isDirty}\n zone1DefaultWidth=\"540px\"\n zone1={zone1Content}\n zone2={zone2Content}\n />\n </DealDetailTabs>\n\n <InjectionSpot spotId=\"detail:customers.deal:footer\" context={injectionContext} data={data} />\n </div>\n\n {ConfirmDialogElement}\n\n {selectedActivityEntity ? (\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={closeSchedule}\n entityId={selectedActivityEntity.id}\n dealId={data.deal.id}\n entityType={selectedActivityEntity.kind}\n entityName={selectedActivityEntity.label}\n companyName={selectedActivityEntity.kind === 'company' ? selectedActivityEntity.label : data.companies[0]?.label ?? null}\n onActivityCreated={() => { void handleActivityCreated() }}\n editData={scheduleEditData}\n />\n ) : null}\n\n <ConfirmDealLostDialog\n open={lostDialogOpen}\n onClose={closeLostDialog}\n dealTitle={data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')}\n dealValue={amountLabel}\n companyName={data.companies[0]?.label ?? null}\n onConfirm={handleLostConfirm}\n />\n\n <DealWonPopup\n open={wonPopupOpen}\n onClose={closeWonPopup}\n dealTitle={data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')}\n stats={wonStats}\n onViewDashboard={handleViewDashboard}\n onBackToPipeline={handleBackToPipeline}\n />\n\n <DealLostSummaryDialog\n open={lostPopupOpen}\n onClose={closeLostPopup}\n dealTitle={data.deal.title || t('customers.deals.detail.untitled', 'Untitled deal')}\n lossNotes={data.deal.lossNotes}\n stats={lostStats}\n onBackToPipeline={handleBackToPipeline}\n onScheduleFollowUp={selectedActivityEntity ? handleScheduleLostFollowUp : undefined}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["id"]
|
|
7
7
|
}
|
|
@@ -172,12 +172,13 @@ function PersonDetailV2Page({ params }) {
|
|
|
172
172
|
const handleEditActivity = React.useCallback((activity) => {
|
|
173
173
|
const raw = activity;
|
|
174
174
|
const durationValue = typeof raw.duration === "number" ? raw.duration : typeof raw.durationMinutes === "number" ? raw.durationMinutes : null;
|
|
175
|
-
|
|
175
|
+
const editPayload = {
|
|
176
176
|
id: activity.id,
|
|
177
177
|
interactionType: typeof activity.interactionType === "string" ? activity.interactionType : void 0,
|
|
178
178
|
title: typeof activity.title === "string" ? activity.title : null,
|
|
179
179
|
body: typeof activity.body === "string" ? activity.body : null,
|
|
180
180
|
scheduledAt: typeof activity.scheduledAt === "string" ? activity.scheduledAt : null,
|
|
181
|
+
occurredAt: typeof activity.occurredAt === "string" ? activity.occurredAt : null,
|
|
181
182
|
durationMinutes: durationValue,
|
|
182
183
|
location: typeof raw.location === "string" ? raw.location : null,
|
|
183
184
|
allDay: typeof raw.allDay === "boolean" ? raw.allDay : null,
|
|
@@ -187,8 +188,11 @@ function PersonDetailV2Page({ params }) {
|
|
|
187
188
|
reminderMinutes: typeof raw.reminderMinutes === "number" ? raw.reminderMinutes : null,
|
|
188
189
|
visibility: typeof raw.visibility === "string" ? raw.visibility : null,
|
|
189
190
|
linkedEntities: Array.isArray(raw.linkedEntities) ? raw.linkedEntities : null,
|
|
190
|
-
guestPermissions: raw.guestPermissions && typeof raw.guestPermissions === "object" ? raw.guestPermissions : null
|
|
191
|
-
|
|
191
|
+
guestPermissions: raw.guestPermissions && typeof raw.guestPermissions === "object" ? raw.guestPermissions : null,
|
|
192
|
+
customValues: raw.customValues && typeof raw.customValues === "object" ? raw.customValues : null,
|
|
193
|
+
phoneNumber: typeof raw.phoneNumber === "string" ? raw.phoneNumber : null
|
|
194
|
+
};
|
|
195
|
+
setScheduleEditData(editPayload);
|
|
192
196
|
setScheduleDialogOpen(true);
|
|
193
197
|
}, []);
|
|
194
198
|
const { widgets: injectedTabWidgets } = useInjectionWidgets("detail:customers.person:tabs", {
|
|
@@ -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 Link from 'next/link'\nimport { useRouter, useSearchParams } 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 { 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 { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\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, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\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, resolveLegacyTab, type PersonTabId } from '../../../../components/detail/PersonDetailTabs'\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'\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 { organizationId } = useOrganizationScopeDetail()\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 const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\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 initialTab = React.useMemo(() => {\n return resolveLegacyTab(searchParams?.get('tab'))\n }, [searchParams])\n const [activeTab, setActiveTab] = React.useState<PersonTabId>(initialTab)\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 () => {\n if (!id) {\n setError(t('customers.people.detail.error.notFound', 'Person not found.'))\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n try {\n const payload = await readApiResultOrThrow<PersonOverview>(\n `/api/customers/people/${encodeURIComponent(id)}`,\n undefined,\n { errorMessage: t('customers.people.detail.error.load', 'Failed to load person.') },\n )\n setData(payload as PersonOverview)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.people.detail.error.load', 'Failed to load person.')\n setError(message)\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch((err) => console.warn('[people-v2] loadData failed', err))\n }, [loadData])\n\n React.useEffect(() => {\n setDealCount(data?.counts?.deals ?? 0)\n }, [data?.counts?.deals])\n\n const handleActivityCreated = React.useCallback(() => {\n setActivityRefreshKey((k) => k + 1)\n loadData().catch((err) => console.warn('[people-v2] reload after activity failed', 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 retryLastMutation,\n }),\n [currentPersonId, data, id, mutationContextId, retryLastMutation],\n )\n const runMutationWithContext = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: injectionContext,\n })\n },\n [injectionContext, runMutation],\n )\n\n const 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; [key: string]: unknown }) => {\n const raw = activity as Record<string, unknown>\n const durationValue = typeof raw.duration === 'number'\n ? raw.duration\n : typeof raw.durationMinutes === 'number'\n ? raw.durationMinutes as number\n : null\n setScheduleEditData({\n id: activity.id,\n interactionType: typeof activity.interactionType === 'string' ? activity.interactionType : undefined,\n title: typeof activity.title === 'string' ? activity.title : null,\n body: typeof activity.body === 'string' ? activity.body : null,\n scheduledAt: typeof activity.scheduledAt === 'string' ? activity.scheduledAt : null,\n durationMinutes: durationValue,\n location: typeof raw.location === 'string' ? raw.location as string : null,\n allDay: typeof raw.allDay === 'boolean' ? raw.allDay as boolean : null,\n recurrenceRule: typeof raw.recurrenceRule === 'string' ? raw.recurrenceRule as string : null,\n recurrenceEnd: typeof raw.recurrenceEnd === 'string' ? raw.recurrenceEnd as string : null,\n participants: Array.isArray(raw.participants) ? raw.participants as ScheduleActivityEditData['participants'] : null,\n reminderMinutes: typeof raw.reminderMinutes === 'number' ? raw.reminderMinutes as number : null,\n visibility: typeof raw.visibility === 'string' ? raw.visibility as string : null,\n linkedEntities: Array.isArray(raw.linkedEntities) ? raw.linkedEntities as ScheduleActivityEditData['linkedEntities'] : null,\n guestPermissions: raw.guestPermissions && typeof raw.guestPermissions === 'object'\n ? raw.guestPermissions as ScheduleActivityEditData['guestPermissions']\n : null,\n })\n setScheduleDialogOpen(true)\n }, [])\n\n // Injected tabs from UMES\n const { widgets: injectedTabWidgets } = useInjectionWidgets('detail:customers.person:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const tabId = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel ?? widget.module.metadata.title ?? tabId\n const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0\n const render = () => (\n <widget.module.Widget\n context={injectionContext}\n data={data}\n onDataChange={(next: unknown) => setData(next as PersonOverview)}\n />\n )\n return { id: tabId, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext],\n )\n\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n // Tags\n const handleTagsChange = React.useCallback((nextTags: TagSummary[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n const tagsSectionControllerRef = React.useRef<TagsSectionController | null>(null)\n\n // Section action (for tabs that expose add/create buttons)\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction((prev) => (action !== null ? action : prev))\n }, [])\n\n 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 await updateCrud('customers/people', payload)\n flash(t('customers.people.form.updateSuccess', 'Person updated.'), 'success')\n await loadData()\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 await runMutationWithContext(\n () => deleteCrud('customers/people', { id: personId }),\n { id: personId, operation: 'deletePerson' },\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 (error || !data?.person?.id || !initialValues) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error || t('customers.people.detail.error.notFound', 'Person not found.')}\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 */}\n <InjectionSpot spotId=\"detail:customers.person:header\" context={injectionContext} data={data} />\n <InjectionSpot spotId=\"detail:customers.person:status-badges\" context={injectionContext} data={data} />\n\n {/* Persistent person header */}\n <PersonDetailHeader\n data={data}\n onTagsChange={handleTagsChange}\n tagsSectionControllerRef={tagsSectionControllerRef}\n onSave={handleHeaderSave}\n onDelete={handleFormDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n onOpenCompaniesTab={() => setActiveTab('companies')}\n onDataReload={() => { loadData().catch((err) => console.warn('[people-v2] onDataReload failed', 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 {(() => {\n const zone1Content = (\n <div ref={formWrapperRef}>\n <CrudForm<PersonEditFormValues>\n embedded\n trackDirtyWhenEmbedded\n injectionSpotId=\"customers.person\"\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n schema={formSchema}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n onSubmit={handleFormSubmit}\n onDelete={handleFormDelete}\n hideFooterActions\n collapsibleGroups={{ pageType: 'person-v2', chevronPosition: 'left' }}\n sortableGroups={{ pageType: 'person-v2' }}\n onDirtyChange={setIsDirty}\n />\n </div>\n )\n const zone2Content = (\n <PersonDetailTabs\n activeTab={activeTab}\n onTabChange={setActiveTab}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n activitiesCount={interactionCount}\n dealsCount={dealCount}\n companiesCount={companyCount}\n tasksCount={todoCount}\n sectionAction={sectionAction}\n >\n <div className=\"min-w-0\">\n {(() => {\n // Injected tab content\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\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 === '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 === '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 </div>\n </PersonDetailTabs>\n )\n return (\n <>\n <div className=\"md:hidden\">\n <MobilePersonDetail zone1={zone1Content} zone2={zone2Content} />\n </div>\n <div className=\"hidden md:block\">\n <CollapsibleZoneLayout\n pageType=\"person-v2\"\n entityName={personName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1={zone1Content}\n zone2={zone2Content}\n />\n </div>\n </>\n )\n })()}\n\n {/* UMES footer injection */}\n <InjectionSpot spotId=\"detail:customers.person:footer\" 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 Link from 'next/link'\nimport { useRouter, useSearchParams } 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 { 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 { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\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, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\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, resolveLegacyTab, type PersonTabId } from '../../../../components/detail/PersonDetailTabs'\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'\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 { organizationId } = useOrganizationScopeDetail()\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 const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\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 initialTab = React.useMemo(() => {\n return resolveLegacyTab(searchParams?.get('tab'))\n }, [searchParams])\n const [activeTab, setActiveTab] = React.useState<PersonTabId>(initialTab)\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 () => {\n if (!id) {\n setError(t('customers.people.detail.error.notFound', 'Person not found.'))\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n try {\n const payload = await readApiResultOrThrow<PersonOverview>(\n `/api/customers/people/${encodeURIComponent(id)}`,\n undefined,\n { errorMessage: t('customers.people.detail.error.load', 'Failed to load person.') },\n )\n setData(payload as PersonOverview)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.people.detail.error.load', 'Failed to load person.')\n setError(message)\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch((err) => console.warn('[people-v2] loadData failed', err))\n }, [loadData])\n\n React.useEffect(() => {\n setDealCount(data?.counts?.deals ?? 0)\n }, [data?.counts?.deals])\n\n const handleActivityCreated = React.useCallback(() => {\n setActivityRefreshKey((k) => k + 1)\n loadData().catch((err) => console.warn('[people-v2] reload after activity failed', 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 retryLastMutation,\n }),\n [currentPersonId, data, id, mutationContextId, retryLastMutation],\n )\n const runMutationWithContext = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: injectionContext,\n })\n },\n [injectionContext, runMutation],\n )\n\n const 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 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 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 // Injected tabs from UMES\n const { widgets: injectedTabWidgets } = useInjectionWidgets('detail:customers.person:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const tabId = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel ?? widget.module.metadata.title ?? tabId\n const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0\n const render = () => (\n <widget.module.Widget\n context={injectionContext}\n data={data}\n onDataChange={(next: unknown) => setData(next as PersonOverview)}\n />\n )\n return { id: tabId, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext],\n )\n\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n // Tags\n const handleTagsChange = React.useCallback((nextTags: TagSummary[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n const tagsSectionControllerRef = React.useRef<TagsSectionController | null>(null)\n\n // Section action (for tabs that expose add/create buttons)\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction((prev) => (action !== null ? action : prev))\n }, [])\n\n 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 await updateCrud('customers/people', payload)\n flash(t('customers.people.form.updateSuccess', 'Person updated.'), 'success')\n await loadData()\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 await runMutationWithContext(\n () => deleteCrud('customers/people', { id: personId }),\n { id: personId, operation: 'deletePerson' },\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 (error || !data?.person?.id || !initialValues) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error || t('customers.people.detail.error.notFound', 'Person not found.')}\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 */}\n <InjectionSpot spotId=\"detail:customers.person:header\" context={injectionContext} data={data} />\n <InjectionSpot spotId=\"detail:customers.person:status-badges\" context={injectionContext} data={data} />\n\n {/* Persistent person header */}\n <PersonDetailHeader\n data={data}\n onTagsChange={handleTagsChange}\n tagsSectionControllerRef={tagsSectionControllerRef}\n onSave={handleHeaderSave}\n onDelete={handleFormDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n onOpenCompaniesTab={() => setActiveTab('companies')}\n onDataReload={() => { loadData().catch((err) => console.warn('[people-v2] onDataReload failed', 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 {(() => {\n const zone1Content = (\n <div ref={formWrapperRef}>\n <CrudForm<PersonEditFormValues>\n embedded\n trackDirtyWhenEmbedded\n injectionSpotId=\"customers.person\"\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n schema={formSchema}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n onSubmit={handleFormSubmit}\n onDelete={handleFormDelete}\n hideFooterActions\n collapsibleGroups={{ pageType: 'person-v2', chevronPosition: 'left' }}\n sortableGroups={{ pageType: 'person-v2' }}\n onDirtyChange={setIsDirty}\n />\n </div>\n )\n const zone2Content = (\n <PersonDetailTabs\n activeTab={activeTab}\n onTabChange={setActiveTab}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n activitiesCount={interactionCount}\n dealsCount={dealCount}\n companiesCount={companyCount}\n tasksCount={todoCount}\n sectionAction={sectionAction}\n >\n <div className=\"min-w-0\">\n {(() => {\n // Injected tab content\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\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 === '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 === '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 </div>\n </PersonDetailTabs>\n )\n return (\n <>\n <div className=\"md:hidden\">\n <MobilePersonDetail zone1={zone1Content} zone2={zone2Content} />\n </div>\n <div className=\"hidden md:block\">\n <CollapsibleZoneLayout\n pageType=\"person-v2\"\n entityName={personName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1={zone1Content}\n zone2={zone2Content}\n />\n </div>\n </>\n )\n })()}\n\n {/* UMES footer injection */}\n <InjectionSpot spotId=\"detail:customers.person:footer\" 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": ";AA0QY,SAqTE,UArTF,KA+MU,YA/MV;AAxQZ,YAAY,WAAW;AACvB,OAAO,UAAU;AACjB,SAAS,WAAW,uBAAuB;AAC3C,SAAS,MAAM,MAAM,OAAO,iBAAiB;AAC7C,SAAS,MAAM,gBAAgB;AAC/B,SAAS,gBAAgB;AACzB,SAAS,6BAAyD;AAClE,SAAS,YAAY,kBAAkB;AAEvC,SAAS,4BAA4B;AACrC,SAAS,2BAA2B;AACpC,SAAS,SAAS;AAClB,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,kCAAkC;AAC3C,SAAS,cAAc;AACvB,SAAS,oBAAoB,cAAc,sBAA0C;AACrF,SAAS,wBAAwB;AACjC,SAAS,eAAe,2BAA2B;AACnD,SAAS,0BAA0B;AACnC,SAAS,oCAAoC;AAE7C,SAAS,yBAAyB;AAClC,SAAS,sBAAsB;AAE/B,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAE7B,SAAS,8BAA6D;AACtE,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB,wBAA0C;AACrE,SAAS,8BAA8B;AACvC,SAAS,0BAA0B;AAEnC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,SAAS,mBAAmB,+BAA+B;AAE5C,SAAR,mBAAoC,EAAE,OAAO,GAAiC;AACnF,QAAM,KAAK,QAAQ;AACnB,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,UAAU;AACzB,QAAM,eAAe,gBAAgB;AACrC,QAAM,EAAE,eAAe,IAAI,2BAA2B;AACtD,QAAM,EAAE,SAAS,qBAAqB,IAAI,iBAAiB;AAE3D,QAAM,mBAAmB,MAAM,QAAQ,MAAM,6BAA6B,CAAC,GAAG,CAAC,CAAC,CAAC;AAGjF,QAAM,aAAa,MAAM,QAAQ,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACnE,QAAM,SAAS,MAAM,QAAQ,MAAM,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC;AAEjE,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAgC,IAAI;AAClE,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,IAAI;AACrD,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAwB,IAAI;AAG5D,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAS,KAAK;AAClD,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAAS,KAAK;AACpD,QAAM,iBAAiB,MAAM,OAAuB,IAAI;AAExD,QAAM,aAAa,MAAM,QAAQ,MAAM;AACrC,WAAO,iBAAiB,cAAc,IAAI,KAAK,CAAC;AAAA,EAClD,GAAG,CAAC,YAAY,CAAC;AACjB,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAsB,UAAU;AACxE,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAA+B,IAAI;AACnF,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,MAAM,SAAS,KAAK;AACxE,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,MAAM,SAA0C,IAAI;AACpG,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,MAAM,SAAS,CAAC;AACpE,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,CAAC;AAElD,QAAM,kBAAkB,MAAM,QAAQ,MAAM;AAC5C,QAAM,oBAAoB,MAAM;AAAA,IAC9B,MAAO,kBAAkB,mBAAmB,eAAe,KAAK,mBAAmB,MAAM,SAAS;AAAA,IAClG,CAAC,iBAAiB,EAAE;AAAA,EACtB;AACA,QAAM,EAAE,aAAa,kBAAkB,IAAI,mBAOxC;AAAA,IACD,WAAW;AAAA,IACX,gBAAgB,EAAE,8BAA8B,4BAA4B;AAAA,EAC9E,CAAC;AACD,QAAM,oBAAoB,kBAAkB,MAAM,QAAQ,WAAW;AACrE,QAAM,aAAa,kBAAkB,KAAK,EAAE,SACxC,oBACA,EAAE,4CAA4C,aAAa;AAE/D,QAAM,6BAA6B,kBAAkB,KAAK,EAAE,SACxD,kBAAkB,KAAK,IACvB;AAEJ,QAAM,4BAA4B;AAAA,IAChC,MAAM,SAAS,eAAe,MAAM,YAAY,CAAC,GAAG,eAAe;AAAA,EACrE;AAEA,QAAM,SAAS,MAAM;AAAA,IACnB,MAAM,+BAA+B,GAAG,EAAE,YAAY,2BAA2B,CAAC;AAAA,IAClF,CAAC,GAAG,0BAA0B;AAAA,EAChC;AAEA,QAAM,eAAe,MAAM,QAAiC,MAAM;AAAA,IAChE,EAAE,IAAI,gBAAgB,MAAM,MAAM,OAAO,EAAE,6CAA6C,eAAe,EAAE;AAAA,IACzG,EAAE,IAAI,eAAe,MAAM,WAAW,OAAO,EAAE,4CAA4C,gBAAgB,EAAE;AAAA,IAC7G,EAAE,IAAI,gBAAgB,MAAM,MAAM,OAAO,EAAE,iDAAiD,mBAAmB,EAAE;AAAA,IACjH,EAAE,IAAI,SAAS,MAAM,OAAO,OAAO,EAAE,sCAAsC,UAAU,EAAE;AAAA,EACzF,GAAG,CAAC,CAAC,CAAC;AAGN,QAAM,qBAAqB,MAAM,OAAO,KAAK;AAC7C,QAAM,WAAW,MAAM,YAAY,YAAY;AAC7C,QAAI,CAAC,IAAI;AACP,eAAS,EAAE,0CAA0C,mBAAmB,CAAC;AACzE,mBAAa,KAAK;AAClB;AAAA,IACF;AACA,QAAI,CAAC,mBAAmB,SAAS;AAC/B,mBAAa,IAAI;AAAA,IACnB;AACA,aAAS,IAAI;AACb,QAAI;AACF,YAAM,UAAU,MAAM;AAAA,QACpB,yBAAyB,mBAAmB,EAAE,CAAC;AAAA,QAC/C;AAAA,QACA,EAAE,cAAc,EAAE,sCAAsC,wBAAwB,EAAE;AAAA,MACpF;AACA,cAAQ,OAAyB;AAAA,IACnC,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,EAAE,sCAAsC,wBAAwB;AACrH,eAAS,OAAO;AAChB,UAAI,CAAC,mBAAmB,QAAS,SAAQ,IAAI;AAAA,IAC/C,UAAE;AACA,mBAAa,KAAK;AAClB,yBAAmB,UAAU;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,IAAI,CAAC,CAAC;AAEV,QAAM,UAAU,MAAM;AACpB,aAAS,EAAE,MAAM,CAAC,QAAQ,QAAQ,KAAK,+BAA+B,GAAG,CAAC;AAAA,EAC5E,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,UAAU,MAAM;AACpB,iBAAa,MAAM,QAAQ,SAAS,CAAC;AAAA,EACvC,GAAG,CAAC,MAAM,QAAQ,KAAK,CAAC;AAExB,QAAM,wBAAwB,MAAM,YAAY,MAAM;AACpD,0BAAsB,CAAC,MAAM,IAAI,CAAC;AAClC,aAAS,EAAE,MAAM,CAAC,QAAQ,QAAQ,KAAK,4CAA4C,GAAG,CAAC;AAAA,EACzF,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,oBAAoB,MAAM,QAAQ,MAAM;AAC5C,WAAO,MAAM,4BAA4B,CAAC;AAAA,EAC5C,GAAG,CAAC,MAAM,wBAAwB,CAAC;AAGnC,QAAM,mBAAmB,MAAM;AAAA,IAC7B,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,cAAc;AAAA,MACd,YAAY,oBAAoB,MAAM;AAAA,MACtC;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,iBAAiB,MAAM,IAAI,mBAAmB,iBAAiB;AAAA,EAClE;AACA,QAAM,yBAAyB,MAAM;AAAA,IACnC,OAAW,WAA6B,oBAA0D;AAChG,aAAO,YAAY;AAAA,QACjB;AAAA,QACA;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,IACA,CAAC,kBAAkB,WAAW;AAAA,EAChC;AAEA,QAAM,oBAAoB,MAAM,YAAY,CAAC,SAAuB;AAClE,wBAAoB;AAAA,MAClB,IAAI;AAAA,MACJ,iBAAiB;AAAA,MACjB,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,iBAAiB;AAAA,MACjB,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,kBAAkB;AAAA,IACpB,CAAC;AACD,0BAAsB,IAAI;AAAA,EAC5B,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB,MAAM,YAAY,CAAC,aAAqL;AACjO,UAAM,MAAM;AACZ,UAAM,gBAAgB,OAAO,IAAI,aAAa,WAC1C,IAAI,WACJ,OAAO,IAAI,oBAAoB,WAC7B,IAAI,kBACJ;AAKN,UAAM,cAAc;AAAA,MAClB,IAAI,SAAS;AAAA,MACb,iBAAiB,OAAO,SAAS,oBAAoB,WAAW,SAAS,kBAAkB;AAAA,MAC3F,OAAO,OAAO,SAAS,UAAU,WAAW,SAAS,QAAQ;AAAA,MAC7D,MAAM,OAAO,SAAS,SAAS,WAAW,SAAS,OAAO;AAAA,MAC1D,aAAa,OAAO,SAAS,gBAAgB,WAAW,SAAS,cAAc;AAAA,MAC/E,YAAY,OAAO,SAAS,eAAe,WAAW,SAAS,aAAa;AAAA,MAC5E,iBAAiB;AAAA,MACjB,UAAU,OAAO,IAAI,aAAa,WAAW,IAAI,WAAqB;AAAA,MACtE,QAAQ,OAAO,IAAI,WAAW,YAAY,IAAI,SAAoB;AAAA,MAClE,gBAAgB,OAAO,IAAI,mBAAmB,WAAW,IAAI,iBAA2B;AAAA,MACxF,eAAe,OAAO,IAAI,kBAAkB,WAAW,IAAI,gBAA0B;AAAA,MACrF,cAAc,MAAM,QAAQ,IAAI,YAAY,IAAI,IAAI,eAA2D;AAAA,MAC/G,iBAAiB,OAAO,IAAI,oBAAoB,WAAW,IAAI,kBAA4B;AAAA,MAC3F,YAAY,OAAO,IAAI,eAAe,WAAW,IAAI,aAAuB;AAAA,MAC5E,gBAAgB,MAAM,QAAQ,IAAI,cAAc,IAAI,IAAI,iBAA+D;AAAA,MACvH,kBAAkB,IAAI,oBAAoB,OAAO,IAAI,qBAAqB,WACtE,IAAI,mBACJ;AAAA,MACJ,cAAc,IAAI,gBAAgB,OAAO,IAAI,iBAAiB,WAC1D,IAAI,eACJ;AAAA,MACJ,aAAa,OAAO,IAAI,gBAAgB,WAAW,IAAI,cAAwB;AAAA,IACjF;AACA,wBAAoB,WAAW;AAC/B,0BAAsB,IAAI;AAAA,EAC5B,GAAG,CAAC,CAAC;AAGL,QAAM,EAAE,SAAS,mBAAmB,IAAI,oBAAoB,gCAAgC;AAAA,IAC1F,SAAS;AAAA,IACT,eAAe;AAAA,EACjB,CAAC;AAED,QAAM,eAAe,MAAM;AAAA,IACzB,OACG,sBAAsB,CAAC,GACrB,OAAO,CAAC,YAAY,OAAO,WAAW,QAAQ,WAAW,KAAK,EAC9D,IAAI,CAAC,WAAW;AACf,YAAM,QAAQ,OAAO,WAAW,WAAW,OAAO;AAClD,YAAM,QAAQ,OAAO,WAAW,cAAc,OAAO,OAAO,SAAS,SAAS;AAC9E,YAAM,WAAW,OAAO,OAAO,WAAW,aAAa,WAAW,OAAO,UAAU,WAAW;AAC9F,YAAM,SAAS,MACb;AAAA,QAAC,OAAO,OAAO;AAAA,QAAd;AAAA,UACC,SAAS;AAAA,UACT;AAAA,UACA,cAAc,CAAC,SAAkB,QAAQ,IAAsB;AAAA;AAAA,MACjE;AAEF,aAAO,EAAE,IAAI,OAAO,OAAO,UAAU,OAAO;AAAA,IAC9C,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAAA,IAC3C,CAAC,MAAM,oBAAoB,gBAAgB;AAAA,EAC7C;AAEA,QAAM,iBAAiB,MAAM,QAAQ,MAAM,IAAI,IAAI,aAAa,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC;AAGnH,QAAM,mBAAmB,MAAM,YAAY,CAAC,aAA2B;AACrE,YAAQ,CAAC,SAAU,OAAO,EAAE,GAAG,MAAM,MAAM,SAAS,IAAI,IAAK;AAAA,EAC/D,GAAG,CAAC,CAAC;AACL,QAAM,2BAA2B,MAAM,OAAqC,IAAI;AAGhF,QAAM,4BAA4B,MAAM,YAAY,CAAC,WAAiC;AACpF,qBAAiB,CAAC,SAAU,WAAW,OAAO,SAAS,IAAK;AAAA,EAC9D,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,MAAM;AACpB,qBAAiB,IAAI;AAAA,EACvB,GAAG,CAAC,SAAS,CAAC;AAGd,QAAM,aAAa,MAAM;AAAA,IACvB,MAAO,kBAAmB,EAAE,MAAM,UAAU,UAAU,gBAAgB,IAAc;AAAA,IACpF,CAAC,eAAe;AAAA,EAClB;AAEA,QAAM,gBAAgB,MAAM;AAAA,IAC1B,MAAO,OAAO,8BAA8B,IAAI,IAAI;AAAA,IACpD,CAAC,IAAI;AAAA,EACP;AAGA,QAAM,mBAAmB,MAAM;AAAA,IAC7B,OAAO,WAAiC;AACtC,kBAAY,IAAI;AAChB,UAAI;AACF,cAAM,yBAAyB,SAAS,MAAM;AAE9C,YAAI;AACJ,YAAI;AACF,oBAAU,uBAAuB,QAAQ,cAAc;AAAA,QACzD,SAAS,KAAK;AACZ,cAAI,eAAe,SAAS,IAAI,YAAY,yBAAyB;AACnE,kBAAM,UAAU,EAAE,yCAAyC;AAC3D,kBAAM,oBAAoB,SAAS,EAAE,aAAa,QAAQ,CAAC;AAAA,UAC7D;AACA,gBAAM;AAAA,QACR;AAEA,cAAM,WAAW,oBAAoB,OAAO;AAC5C,cAAM,EAAE,uCAAuC,iBAAiB,GAAG,SAAS;AAC5E,cAAM,SAAS;AAAA,MACjB,UAAE;AACA,oBAAY,KAAK;AAAA,MACnB;AAAA,IACF;AAAA,IACA,CAAC,UAAU,gBAAgB,CAAC;AAAA,EAC9B;AAEA,QAAM,mBAAmB,MAAM;AAAA,IAC7B,YAAY;AACV,YAAMA,YAAW,MAAM,QAAQ,MAAM;AACrC,UAAI,CAACA,UAAU;AACf,YAAM,WAAW,MAAM,QAAQ;AAAA,QAC7B,OAAO,EAAE,8CAA8C,gBAAgB;AAAA,QACvE,aAAa,EAAE,oDAAoD,+BAA+B;AAAA,QAClG,aAAa,EAAE,0CAA0C,QAAQ;AAAA,QACjE,YAAY,EAAE,0CAA0C,QAAQ;AAAA,QAChE,SAAS;AAAA,MACX,CAAC;AACD,UAAI,CAAC,SAAU;AACf,YAAM;AAAA,QACJ,MAAM,WAAW,oBAAoB,EAAE,IAAIA,UAAS,CAAC;AAAA,QACrD,EAAE,IAAIA,WAAU,WAAW,eAAe;AAAA,MAC5C;AACA,YAAM,EAAE,uCAAuC,iBAAiB,GAAG,SAAS;AAC5E,aAAO,KAAK,2BAA2B;AAAA,IACzC;AAAA,IACA,CAAC,SAAS,MAAM,QAAQ,IAAI,QAAQ,wBAAwB,CAAC;AAAA,EAC/D;AAEA,QAAM,mBAAmB,MAAM,YAAY,MAAM;AAC/C,UAAM,OAAO,eAAe,SAAS,cAAc,MAAM;AACzD,QAAI,KAAM,MAAK,cAAc;AAAA,EAC/B,GAAG,CAAC,CAAC;AAGL,QAAM,mBAAmB,MAAM,QAAQ,cAAc;AACrD,QAAM,YAAY,MAAM,QAAQ,SAAS;AACzC,QAAM,eAAe,MAAM,QAAQ,cAAc,MAAM,WAAW,WAAW,MAAM,UAAU,IAAI;AAGjG,MAAI,WAAW;AACb,WACE,oBAAC,QACC,8BAAC,YACC,8BAAC,kBAAe,OAAO,EAAE,mCAAmC,sBAAiB,GAAG,GAClF,GACF;AAAA,EAEJ;AAEA,MAAI,SAAS,CAAC,MAAM,QAAQ,MAAM,CAAC,eAAe;AAChD,WACE,oBAAC,QACC,8BAAC,YACC;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,SAAS,EAAE,0CAA0C,mBAAmB;AAAA,QAC/E,QACE,oBAAC,UAAO,SAAO,MAAC,SAAQ,WACtB,8BAAC,QAAK,MAAK,6BACR,YAAE,8CAA8C,gBAAgB,GACnE,GACF;AAAA;AAAA,IAEJ,GACF,GACF;AAAA,EAEJ;AAEA,QAAM,WAAW,KAAK,OAAO;AAC7B,QAAM,2BAA2B,KAAK,oBAAoB;AAE1D,SACE,oBAAC,QACC,8BAAC,YACC,+BAAC,SAAI,WAAU,aAEb;AAAA,wBAAC,iBAAc,QAAO,kCAAiC,SAAS,kBAAkB,MAAY;AAAA,IAC9F,oBAAC,iBAAc,QAAO,yCAAwC,SAAS,kBAAkB,MAAY;AAAA,IAGrG;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,cAAc;AAAA,QACd;AAAA,QACA,QAAQ;AAAA,QACR,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA,oBAAoB,MAAM,aAAa,WAAW;AAAA,QAClD,cAAc,MAAM;AAAE,mBAAS,EAAE,MAAM,CAAC,QAAQ,QAAQ,KAAK,mCAAmC,GAAG,CAAC;AAAA,QAAE;AAAA,QACtG,cAAc,CAAC,cAAc;AAC3B,gBAAM,cAAsC;AAAA,YAC1C,cAAc;AAAA,YACd,cAAc;AAAA,UAChB;AACA,gBAAM,WAAW,YAAY,SAAS;AACtC,gBAAM,QAAQ,WAAW,eAAe,SAAS,cAAgC,QAAQ,IAAI;AAC7F,cAAI,OAAO;AACT,kBAAM,eAAe,EAAE,UAAU,UAAU,OAAO,SAAS,CAAC;AAC5D,kCAAsB,MAAM,MAAM,MAAM,CAAC;AAAA,UAC3C;AAAA,QACF;AAAA;AAAA,IACF;AAAA,KAGE,MAAM;AACN,YAAM,eACJ,oBAAC,SAAI,KAAK,gBACR;AAAA,QAAC;AAAA;AAAA,UACC,UAAQ;AAAA,UACR,wBAAsB;AAAA,UACtB,iBAAgB;AAAA,UAChB,WAAW,CAAC,EAAE,UAAU,iBAAiB,EAAE,UAAU,uBAAuB;AAAA,UAC5E,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU;AAAA,UACV,UAAU;AAAA,UACV,mBAAiB;AAAA,UACjB,mBAAmB,EAAE,UAAU,aAAa,iBAAiB,OAAO;AAAA,UACpE,gBAAgB,EAAE,UAAU,YAAY;AAAA,UACxC,eAAe;AAAA;AAAA,MACjB,GACF;AAEF,YAAM,eACJ;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,aAAa;AAAA,UACb,cAAc,aAAa,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,IAAI,OAAO,IAAI,MAAM,EAAE;AAAA,UAC1E,iBAAiB;AAAA,UACjB,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,YAAY;AAAA,UACZ;AAAA,UAEA,8BAAC,SAAI,WAAU,WACb,iBAAM;AAEN,kBAAM,WAAW,eAAe,IAAI,SAAS;AAC7C,gBAAI,SAAU,QAAO,SAAS;AAE9B,gBAAI,cAAc,cAAc;AAC9B,qBACE,qBAAC,SAAI,WAAU,aACb;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,UAAU;AAAA,oBACV;AAAA,oBACA,YAAY;AAAA,oBACZ,UAAU;AAAA,oBACV,gBAAgB;AAAA,oBAChB,mBAAmB,KAAK,SAAS,eAAe,KAAK,YAAY,CAAC,GAAG,eAAe;AAAA;AAAA,gBACtF;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,UAAU;AAAA,oBACV,YAAY;AAAA,oBACZ;AAAA,oBACA,oBAAoB;AAAA,oBACpB,eAAe;AAAA,oBACf,YAAY;AAAA,oBACZ,gBAAgB,EAAE,0CAA0C,cAAc;AAAA,oBAC1E,YAAY;AAAA,sBACV,OAAO,EAAE,uDAAuD,0BAA0B;AAAA,sBAC1F,aAAa,EAAE,wDAAwD,cAAc;AAAA,oBACvF;AAAA,oBACA,gBAAgB;AAAA,oBAChB,gBAAgB;AAAA;AAAA,gBAClB;AAAA,iBACF;AAAA,YAEJ;AAEA,gBAAI,cAAc,SAAS;AACzB,qBACE;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,kBACP,YAAY,EAAE,uCAAuC,iCAAiC;AAAA,kBACtF,gBAAgB,EAAE,2CAA2C,UAAU;AAAA,kBACvE,YAAY;AAAA,oBACV,OAAO,EAAE,kDAAkD,cAAc;AAAA,oBACzE,aAAa,EAAE,mDAAmD,eAAe;AAAA,kBACnF;AAAA,kBACA,gBAAgB;AAAA,kBAChB,YAAY;AAAA,kBACZ,oBAAoB;AAAA,kBACpB,cAAc,CAAC,UAAU,aAAa,CAAC,YAAY,KAAK,IAAI,GAAG,UAAU,KAAK,CAAC;AAAA;AAAA,cACjF;AAAA,YAEJ;AAEA,gBAAI,cAAc,aAAa;AAC7B,qBACE;AAAA,gBAAC;AAAA;AAAA,kBACC;AAAA,kBACA;AAAA,kBACA,wBAAwB,MAAM,aAAa,CAAC;AAAA,kBAC5C,WAAW;AAAA,kBACX,oBAAoB;AAAA;AAAA,cACtB;AAAA,YAEJ;AAEA,gBAAI,cAAc,SAAS;AACzB,qBACE;AAAA,gBAAC;AAAA;AAAA,kBACC,UAAU;AAAA,kBACV,cAAc,CAAC;AAAA,kBACf;AAAA,kBACA,oBAAoB;AAAA,kBACpB,eAAe;AAAA,kBACf,YAAY,EAAE,uCAAuC,iCAAiC;AAAA,kBACtF,gBAAgB,EAAE,qCAAqC,UAAU;AAAA,kBACjE,YAAY;AAAA,oBACV,OAAO,EAAE,kDAAkD,wBAAwB;AAAA,oBACnF,aAAa,EAAE,mDAAmD,aAAa;AAAA,kBACjF;AAAA,kBACA,gBAAgB;AAAA,kBAChB,YAAY;AAAA,kBACZ,YAAY;AAAA,kBACZ,kBAAiB;AAAA,kBACjB,uBAAsB;AAAA;AAAA,cACxB;AAAA,YAEJ;AAEA,gBAAI,cAAc,SAAS;AACzB,qBACE;AAAA,gBAAC;AAAA;AAAA,kBACC,UAAU,EAAE,UAAU;AAAA,kBACtB,UAAU;AAAA,kBACV,OAAO,EAAE,sCAAsC,OAAO;AAAA,kBACtD,aAAa,EAAE,0CAA0C,gDAAgD;AAAA;AAAA,cAC3G;AAAA,YAEJ;AAEA,gBAAI,cAAc,aAAa;AAC7B,qBAAO,oBAAC,gBAAa,UAAU,UAAU,YAAW,UAAS;AAAA,YAC/D;AAEA,mBAAO;AAAA,UACT,GAAG,GACH;AAAA;AAAA,MACF;AAEF,aACE,iCACE;AAAA,4BAAC,SAAI,WAAU,aACb,8BAAC,sBAAmB,OAAO,cAAc,OAAO,cAAc,GAChE;AAAA,QACA,oBAAC,SAAI,WAAU,mBACb;AAAA,UAAC;AAAA;AAAA,YACC,UAAS;AAAA,YACT,YAAY;AAAA,YACZ;AAAA,YACA,UAAU;AAAA,YACV,OAAO;AAAA,YACP,OAAO;AAAA;AAAA,QACT,GACF;AAAA,SACF;AAAA,IAEJ,GAAG;AAAA,IAGH,oBAAC,iBAAc,QAAO,kCAAiC,SAAS,kBAAkB,MAAY;AAAA,IAG9F;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,SAAS,MAAM;AAAE,gCAAsB,KAAK;AAAG,8BAAoB,IAAI;AAAA,QAAE;AAAA,QACzE,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,YAAW;AAAA,QACX,mBAAmB;AAAA,QACnB,UAAU;AAAA;AAAA,IACZ;AAAA,IACC;AAAA,KACH,GACF,GACF;AAEJ;",
|
|
6
6
|
"names": ["personId"]
|
|
7
7
|
}
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Calendar, CalendarClock, Clock, Mail, Phone, StickyNote, Users } from "lucide-react";
|
|
5
|
+
import { toZonedTime } from "date-fns-tz";
|
|
5
6
|
import { cn } from "@open-mercato/shared/lib/utils";
|
|
6
7
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
8
|
+
import { readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
|
|
7
9
|
import { ActivitiesDayStrip } from "./ActivitiesDayStrip.js";
|
|
8
10
|
import { ActivitiesAddNewMenu } from "./ActivitiesAddNewMenu.js";
|
|
9
11
|
const TYPE_ICONS = {
|
|
@@ -12,6 +14,16 @@ const TYPE_ICONS = {
|
|
|
12
14
|
meeting: Users,
|
|
13
15
|
note: StickyNote
|
|
14
16
|
};
|
|
17
|
+
const USER_TIMEZONE = (() => {
|
|
18
|
+
try {
|
|
19
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
20
|
+
} catch {
|
|
21
|
+
return "UTC";
|
|
22
|
+
}
|
|
23
|
+
})();
|
|
24
|
+
function toLocalZonedDate(value) {
|
|
25
|
+
return toZonedTime(value, USER_TIMEZONE);
|
|
26
|
+
}
|
|
15
27
|
function startOfDay(date) {
|
|
16
28
|
const next = new Date(date);
|
|
17
29
|
next.setHours(0, 0, 0, 0);
|
|
@@ -27,6 +39,7 @@ function isOverdue(activity, now) {
|
|
|
27
39
|
if (Number.isNaN(date.getTime())) return false;
|
|
28
40
|
return date.getTime() < now.getTime() && activity.status !== "done";
|
|
29
41
|
}
|
|
42
|
+
const FETCH_WINDOW_DAYS = 31;
|
|
30
43
|
function formatTime(date) {
|
|
31
44
|
return date.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit" });
|
|
32
45
|
}
|
|
@@ -57,24 +70,66 @@ function ActivitiesCard({
|
|
|
57
70
|
}) {
|
|
58
71
|
const t = useT();
|
|
59
72
|
const [selectedDate, setSelectedDate] = React.useState(() => startOfDay(/* @__PURE__ */ new Date()));
|
|
73
|
+
const [fetchedEvents, setFetchedEvents] = React.useState(null);
|
|
74
|
+
React.useEffect(() => {
|
|
75
|
+
if (!entityId) {
|
|
76
|
+
setFetchedEvents(null);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const controller = new AbortController();
|
|
80
|
+
const today = startOfDay(/* @__PURE__ */ new Date());
|
|
81
|
+
const fromDate = new Date(today);
|
|
82
|
+
fromDate.setDate(today.getDate() - FETCH_WINDOW_DAYS);
|
|
83
|
+
const toDate = new Date(today);
|
|
84
|
+
toDate.setDate(today.getDate() + FETCH_WINDOW_DAYS);
|
|
85
|
+
toDate.setHours(23, 59, 59, 999);
|
|
86
|
+
const params = new URLSearchParams({
|
|
87
|
+
entityId,
|
|
88
|
+
from: fromDate.toISOString(),
|
|
89
|
+
to: toDate.toISOString(),
|
|
90
|
+
// Server caps at 100 (interactions querySchema). 100 is well above what
|
|
91
|
+
// an active CRM record accumulates in a 31-day window of meetings/calls,
|
|
92
|
+
// and the day strip + list naturally degrade to truncation if exceeded.
|
|
93
|
+
limit: "100",
|
|
94
|
+
sortField: "scheduledAt",
|
|
95
|
+
sortDir: "asc",
|
|
96
|
+
excludeInteractionType: "task"
|
|
97
|
+
});
|
|
98
|
+
void (async () => {
|
|
99
|
+
try {
|
|
100
|
+
const payload = await readApiResultOrThrow(
|
|
101
|
+
`/api/customers/interactions?${params.toString()}`,
|
|
102
|
+
{ signal: controller.signal }
|
|
103
|
+
);
|
|
104
|
+
setFetchedEvents(Array.isArray(payload?.items) ? payload.items : []);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
if (err?.name !== "AbortError") {
|
|
107
|
+
console.warn("[ActivitiesCard] failed to load interactions", err);
|
|
108
|
+
setFetchedEvents(null);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
})();
|
|
112
|
+
return () => controller.abort();
|
|
113
|
+
}, [entityId, refreshKey]);
|
|
114
|
+
const effectiveEvents = fetchedEvents ?? plannedActivities;
|
|
60
115
|
const eventsForSelectedDay = React.useMemo(() => {
|
|
61
|
-
const items =
|
|
116
|
+
const items = effectiveEvents.filter((activity) => {
|
|
62
117
|
const scheduled = activity.scheduledAt ?? activity.occurredAt;
|
|
63
118
|
if (!scheduled) return false;
|
|
64
119
|
const date = new Date(scheduled);
|
|
65
120
|
if (Number.isNaN(date.getTime())) return false;
|
|
66
|
-
return isSameDay(
|
|
121
|
+
return isSameDay(toLocalZonedDate(scheduled), selectedDate);
|
|
67
122
|
});
|
|
68
123
|
return items.sort((left, right) => {
|
|
69
124
|
const leftTime = new Date(left.scheduledAt ?? left.occurredAt ?? left.createdAt).getTime();
|
|
70
125
|
const rightTime = new Date(right.scheduledAt ?? right.occurredAt ?? right.createdAt).getTime();
|
|
71
126
|
return leftTime - rightTime;
|
|
72
127
|
});
|
|
73
|
-
}, [
|
|
128
|
+
}, [effectiveEvents, selectedDate]);
|
|
74
129
|
const overdueCount = React.useMemo(() => {
|
|
75
130
|
const now = /* @__PURE__ */ new Date();
|
|
76
|
-
return
|
|
77
|
-
}, [
|
|
131
|
+
return effectiveEvents.filter((activity) => isOverdue(activity, now)).length;
|
|
132
|
+
}, [effectiveEvents]);
|
|
78
133
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 rounded-lg border border-border bg-card pt-4 pb-4 px-4", children: [
|
|
79
134
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
80
135
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -93,7 +148,8 @@ function ActivitiesCard({
|
|
|
93
148
|
entityId,
|
|
94
149
|
selectedDate,
|
|
95
150
|
onSelectDate: setSelectedDate,
|
|
96
|
-
refreshKey
|
|
151
|
+
refreshKey,
|
|
152
|
+
events: fetchedEvents ?? void 0
|
|
97
153
|
}
|
|
98
154
|
),
|
|
99
155
|
eventsForSelectedDay.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|