@open-mercato/core 0.5.1-develop.2912.8d7b1fef24 → 0.5.1-develop.2924.d13908516e
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/dist/modules/customers/api/companies/[id]/people/route.js +12 -7
- package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +2 -1
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +7 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/commands/companies.js +93 -19
- package/dist/modules/customers/commands/companies.js.map +2 -2
- package/dist/modules/customers/commands/people.js +9 -1
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/dist/modules/customers/commands/personCompanyLinks.js +2 -2
- package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyCard.js +32 -3
- package/dist/modules/customers/components/detail/CompanyCard.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js +37 -19
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js +7 -4
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js +63 -2
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonDetailTabs.js +37 -19
- package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/TasksSection.js +1 -11
- package/dist/modules/customers/components/detail/TasksSection.js.map +2 -2
- package/dist/modules/customers/components/formConfig.js +50 -39
- package/dist/modules/customers/components/formConfig.js.map +2 -2
- package/dist/modules/customers/events.js +3 -3
- package/dist/modules/customers/events.js.map +2 -2
- package/dist/modules/customers/lib/displayName.js +13 -1
- package/dist/modules/customers/lib/displayName.js.map +2 -2
- package/dist/modules/customers/lib/personCompanies.js +12 -7
- package/dist/modules/customers/lib/personCompanies.js.map +2 -2
- package/dist/modules/customers/lib/personCompanyLinkTable.js +5 -0
- package/dist/modules/customers/lib/personCompanyLinkTable.js.map +2 -2
- package/dist/modules/workflows/lib/activity-executor.js +21 -17
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/package.json +3 -3
- package/src/modules/customers/api/companies/[id]/people/route.ts +12 -7
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +2 -1
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +12 -2
- package/src/modules/customers/commands/companies.ts +107 -19
- package/src/modules/customers/commands/people.ts +16 -1
- package/src/modules/customers/commands/personCompanyLinks.ts +3 -2
- package/src/modules/customers/components/detail/CompanyCard.tsx +28 -4
- package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +18 -2
- package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +8 -4
- package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +66 -0
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +18 -2
- package/src/modules/customers/components/detail/TasksSection.tsx +1 -8
- package/src/modules/customers/components/formConfig.tsx +59 -40
- package/src/modules/customers/events.ts +3 -3
- package/src/modules/customers/i18n/de.json +10 -0
- package/src/modules/customers/i18n/en.json +10 -0
- package/src/modules/customers/i18n/es.json +10 -0
- package/src/modules/customers/i18n/pl.json +10 -0
- package/src/modules/customers/lib/displayName.ts +19 -0
- package/src/modules/customers/lib/personCompanies.ts +12 -7
- package/src/modules/customers/lib/personCompanyLinkTable.ts +14 -0
- package/src/modules/workflows/lib/activity-executor.ts +21 -18
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/customers/components/detail/TasksSection.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Loader2, Pencil, Trash2 } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { LoadingMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { InteractionSummary, SectionAction, TabEmptyStateConfig, TodoLinkSummary, Translator } from './types'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { formatDate, resolveTodoHref } from './utils'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\nimport { TimelineItemHeader } from './TimelineItemHeader'\nimport { TaskDialog } from './TaskDialog'\nimport { usePersonTasks, type TaskFormPayload } from './hooks/usePersonTasks'\nimport { useInteractions, type InteractionCreatePayload } from './hooks/useInteractions'\nimport { mapInteractionRecordToTodoSummary } from '../../lib/interactionCompatibility'\n\ntype GuardedMutationRunner = <T>(\n operation: () => Promise<T>,\n mutationPayload?: Record<string, unknown>,\n) => Promise<T>\n\ntype TasksSectionProps = {\n entityId: string | null\n initialTasks: TodoLinkSummary[]\n emptyLabel: string\n addActionLabel: string\n emptyState: TabEmptyStateConfig\n onActionChange?: (action: SectionAction | null) => void\n onLoadingChange?: (isLoading: boolean) => void\n onDataRefresh?: () => void\n translator?: Translator\n entityName?: string | null\n dialogContextKey?: string\n dialogContextFallback?: string\n /** When true, use the canonical interactions API instead of the legacy todos API. */\n useCanonicalInteractions?: boolean\n runGuardedMutation?: GuardedMutationRunner\n}\n\nconst RESERVED_TASK_CUSTOM_KEYS = new Set(['priority', 'description', 'due_at', 'dueAt'])\n\nfunction toTimestamp(value: string | null | undefined): number | null {\n if (!value) return null\n const timestamp = new Date(value).getTime()\n return Number.isNaN(timestamp) ? null : timestamp\n}\n\nfunction sortTaskSummaries(tasks: TodoLinkSummary[]): TodoLinkSummary[] {\n return [...tasks].sort((left, right) => {\n const leftDue = toTimestamp(left.dueAt)\n const rightDue = toTimestamp(right.dueAt)\n if (leftDue !== null || rightDue !== null) {\n if (leftDue === null) return 1\n if (rightDue === null) return -1\n if (leftDue !== rightDue) return leftDue - rightDue\n }\n const leftCreated = toTimestamp(left.createdAt) ?? 0\n const rightCreated = toTimestamp(right.createdAt) ?? 0\n if (leftCreated !== rightCreated) return rightCreated - leftCreated\n return left.id.localeCompare(right.id)\n })\n}\n\nfunction buildInitialFormValues(task: TodoLinkSummary | null): Record<string, unknown> | undefined {\n if (!task) return undefined\n const values: Record<string, unknown> = {\n title: task.title ?? '',\n is_done: task.isDone ?? false,\n description: task.description ?? '',\n priority: task.priority ?? '',\n scheduledAt: task.dueAt ?? '',\n }\n if (task.customValues) {\n for (const [key, value] of Object.entries(task.customValues)) {\n if (RESERVED_TASK_CUSTOM_KEYS.has(key)) continue\n const formKey = `cf_${key}`\n if (values[formKey] === undefined) values[formKey] = value\n }\n }\n return values\n}\n\nexport function TasksSection({\n entityId,\n initialTasks,\n emptyLabel,\n addActionLabel,\n emptyState,\n onActionChange,\n onLoadingChange,\n onDataRefresh,\n translator,\n entityName,\n dialogContextKey,\n dialogContextFallback,\n useCanonicalInteractions = false,\n runGuardedMutation,\n}: TasksSectionProps) {\n const tHook = useT()\n const fallbackTranslator = React.useMemo<Translator>(() => createTranslatorWithFallback(tHook), [tHook])\n const t: Translator = React.useMemo(() => translator ?? fallbackTranslator, [translator, fallbackTranslator])\n const runWriteMutation = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n if (!runGuardedMutation) {\n return operation()\n }\n return runGuardedMutation(operation, mutationPayload)\n },\n [runGuardedMutation],\n )\n\n // Legacy path: usePersonTasks (default)\n const legacyResult = usePersonTasks({ entityId, initialTasks })\n\n // Canonical path: useInteractions with planned-status filter\n const canonicalResult = useInteractions({\n entityId: useCanonicalInteractions ? entityId : null,\n typeFilter: 'task',\n })\n\n // Map canonical interactions to the TodoLinkSummary shape used by the rendering below\n const canonicalTasks = React.useMemo<TodoLinkSummary[]>(\n () => (useCanonicalInteractions ? canonicalResult.interactions.map(mapInteractionRecordToTodoSummary) : []),\n [useCanonicalInteractions, canonicalResult.interactions],\n )\n\n const canonicalCreateTask = React.useCallback(\n async (payload: TaskFormPayload) => {\n if (!entityId) throw new Error('Task creation requires an entity id')\n const interactionPayload: InteractionCreatePayload = {\n entityId,\n interactionType: 'task',\n title: payload.base.title,\n status: payload.base.is_done ? 'done' : 'planned',\n priority: payload.base.priority ?? null,\n body: payload.base.description ?? null,\n scheduledAt: payload.base.scheduledAt ?? null,\n customValues: payload.custom,\n }\n await canonicalResult.createInteraction(interactionPayload)\n },\n [canonicalResult, entityId],\n )\n\n const canonicalUpdateTask = React.useCallback(\n async (task: TodoLinkSummary, payload: TaskFormPayload) => {\n await canonicalResult.updateInteraction(task.todoId, {\n title: payload.base.title,\n status: payload.base.is_done ? 'done' : 'planned',\n priority: payload.base.priority ?? null,\n body: payload.base.description ?? null,\n scheduledAt: payload.base.scheduledAt ?? null,\n customValues: payload.custom,\n })\n },\n [canonicalResult],\n )\n\n const canonicalToggleTask = React.useCallback(\n async (task: TodoLinkSummary, nextIsDone: boolean) => {\n if (nextIsDone) {\n await canonicalResult.completeInteraction(task.todoId)\n } else {\n // Reopen: set status back to planned via update\n await canonicalResult.updateInteraction(task.todoId, { status: 'planned' })\n }\n },\n [canonicalResult],\n )\n\n const canonicalUnlinkTask = React.useCallback(\n async (task: TodoLinkSummary) => {\n await canonicalResult.deleteInteraction(task.todoId)\n },\n [canonicalResult],\n )\n\n // Unified interface: pick the active data source based on the flag\n const tasks = useCanonicalInteractions ? canonicalTasks : legacyResult.tasks\n const isInitialLoading = useCanonicalInteractions ? canonicalResult.isInitialLoading : legacyResult.isInitialLoading\n const isLoadingMore = useCanonicalInteractions ? canonicalResult.isLoadingMore : legacyResult.isLoadingMore\n const isMutating = useCanonicalInteractions ? canonicalResult.isMutating : legacyResult.isMutating\n const hasMore = useCanonicalInteractions ? canonicalResult.hasMore : legacyResult.hasMore\n const loadMore = useCanonicalInteractions ? canonicalResult.loadMore : legacyResult.loadMore\n const refresh = useCanonicalInteractions ? canonicalResult.refresh : legacyResult.refresh\n const createTask = useCanonicalInteractions ? canonicalCreateTask : legacyResult.createTask\n const updateTask = useCanonicalInteractions ? canonicalUpdateTask : legacyResult.updateTask\n const toggleTask = useCanonicalInteractions ? canonicalToggleTask : legacyResult.toggleTask\n const unlinkTask = useCanonicalInteractions ? canonicalUnlinkTask : legacyResult.unlinkTask\n const pendingTaskId = useCanonicalInteractions ? canonicalResult.pendingId : legacyResult.pendingTaskId\n const error = useCanonicalInteractions ? canonicalResult.error : legacyResult.error\n const sortedTasks = React.useMemo(() => sortTaskSummaries(tasks), [tasks])\n\n const [dialogOpen, setDialogOpen] = React.useState(false)\n const [dialogMode, setDialogMode] = React.useState<'create' | 'edit'>('create')\n const [editingTask, setEditingTask] = React.useState<TodoLinkSummary | null>(null)\n const sentinelRef = React.useRef<HTMLDivElement | null>(null)\n\n const dialogContextMessage = React.useMemo(() => {\n if (!dialogContextKey || !entityName) return undefined\n return t(dialogContextKey, dialogContextFallback ?? 'This task will be linked to {{name}}', { name: entityName })\n }, [dialogContextFallback, dialogContextKey, entityName, t])\n\n const openCreateDialog = React.useCallback(() => {\n setEditingTask(null)\n setDialogMode('create')\n setDialogOpen(true)\n }, [])\n\n const openEditDialog = React.useCallback((task: TodoLinkSummary) => {\n setEditingTask(task)\n setDialogMode('edit')\n setDialogOpen(true)\n }, [])\n\n const closeDialog = React.useCallback(() => {\n setDialogOpen(false)\n setEditingTask(null)\n }, [])\n\n React.useEffect(() => {\n if (!onActionChange) return\n if (!entityId) {\n onActionChange(null)\n return\n }\n onActionChange({\n label: addActionLabel,\n onClick: openCreateDialog,\n disabled: isMutating,\n })\n return () => {\n onActionChange(null)\n }\n }, [addActionLabel, entityId, isMutating, onActionChange, openCreateDialog])\n\n React.useEffect(() => {\n if (!onLoadingChange) return\n onLoadingChange(isInitialLoading || isMutating)\n }, [isInitialLoading, isMutating, onLoadingChange])\n\n React.useEffect(() => {\n if (!hasMore) return\n if (typeof IntersectionObserver === 'undefined') return\n const el = sentinelRef.current\n if (!el) return\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n loadMore().catch(() => {})\n }\n },\n { rootMargin: '200px 0px 200px 0px' },\n )\n observer.observe(el)\n return () => {\n observer.disconnect()\n }\n }, [hasMore, loadMore])\n\n const handleCreate = React.useCallback(\n async (payload: TaskFormPayload) => {\n try {\n await runWriteMutation(\n () => createTask(payload),\n {\n entityId,\n title: payload.base.title,\n isDone: payload.base.is_done ?? undefined,\n },\n )\n flash(t('customers.people.detail.tasks.createSuccess', 'Task created'), 'success')\n await Promise.resolve(onDataRefresh?.())\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.people.detail.tasks.error', 'Failed to create task')\n flash(message, 'error')\n throw err\n }\n },\n [createTask, entityId, onDataRefresh, runWriteMutation, t],\n )\n\n const handleUpdate = React.useCallback(\n async (task: TodoLinkSummary, payload: TaskFormPayload) => {\n try {\n await runWriteMutation(\n () => updateTask(task, payload),\n {\n id: task.id,\n todoId: task.todoId,\n title: payload.base.title,\n isDone: payload.base.is_done ?? undefined,\n },\n )\n flash(t('customers.people.detail.tasks.updateSuccess', 'Task updated'), 'success')\n await Promise.resolve(onDataRefresh?.())\n } catch (err) {\n const message =\n err instanceof Error ? err.message : t('customers.people.detail.tasks.updateError', 'Failed to update task')\n flash(message, 'error')\n throw err\n }\n },\n [onDataRefresh, runWriteMutation, t, updateTask],\n )\n\n const handleToggle = React.useCallback(\n async (task: TodoLinkSummary, nextIsDone: boolean) => {\n try {\n await runWriteMutation(\n () => toggleTask(task, nextIsDone),\n {\n id: task.id,\n todoId: task.todoId,\n isDone: nextIsDone,\n },\n )\n flash(\n nextIsDone\n ? t('customers.people.detail.tasks.completeSuccess', 'Task marked as done')\n : t('customers.people.detail.tasks.reopenSuccess', 'Task reopened'),\n 'success',\n )\n await Promise.resolve(onDataRefresh?.())\n } catch (err) {\n const message =\n err instanceof Error ? err.message : t('customers.people.detail.tasks.toggleError', 'Failed to update task status')\n flash(message, 'error')\n }\n },\n [onDataRefresh, runWriteMutation, t, toggleTask],\n )\n\n const handleDelete = React.useCallback(\n async (task: TodoLinkSummary) => {\n try {\n await runWriteMutation(\n () => unlinkTask(task),\n {\n id: task.id,\n todoId: task.todoId,\n },\n )\n flash(t('customers.people.detail.tasks.deleteSuccess', 'Task removed'), 'success')\n await Promise.resolve(onDataRefresh?.())\n await refresh()\n } catch (err) {\n const message =\n err instanceof Error ? err.message : t('customers.people.detail.tasks.deleteError', 'Failed to remove task')\n flash(message, 'error')\n }\n },\n [onDataRefresh, refresh, runWriteMutation, t, unlinkTask],\n )\n\n const handleCancel = React.useCallback(\n async (task: TodoLinkSummary) => {\n if (!useCanonicalInteractions) return\n try {\n await runWriteMutation(\n () => canonicalResult.cancelInteraction(task.todoId),\n { id: task.todoId },\n )\n flash(t('customers.people.detail.tasks.cancelSuccess', 'Task canceled'), 'success')\n await Promise.resolve(onDataRefresh?.())\n } catch (err) {\n const message =\n err instanceof Error ? err.message : t('customers.people.detail.tasks.cancelError', 'Failed to cancel task')\n flash(message, 'error')\n }\n },\n [canonicalResult, onDataRefresh, runWriteMutation, t, useCanonicalInteractions],\n )\n\n const renderTaskMeta = React.useCallback(\n (task: TodoLinkSummary) => {\n const meta: string[] = []\n if (task.status === 'canceled') {\n meta.push(t('customers.people.detail.tasks.status.canceled', 'Canceled'))\n }\n if (typeof task.priority === 'number') {\n meta.push(t('customers.people.detail.tasks.priorityLabel', 'Priority {{priority}}', { priority: task.priority }))\n }\n if (task.severity) {\n meta.push(\n t(\n `customers.people.detail.tasks.severity.${task.severity}`,\n task.severity.charAt(0).toUpperCase() + task.severity.slice(1),\n ),\n )\n }\n if (task.dueAt) {\n const dueLabel =\n formatDate(task.dueAt) ??\n formatDateTime(task.dueAt) ??\n t('customers.people.detail.tasks.dueLabel', 'Due {{date}}', { date: task.dueAt })\n meta.push(t('customers.people.detail.tasks.dueLabel', 'Due {{date}}', { date: dueLabel }))\n }\n return meta\n },\n [t],\n )\n\n const handleDialogSubmit = React.useCallback(\n async (payload: TaskFormPayload) => {\n if (dialogMode === 'edit' && editingTask) {\n await handleUpdate(editingTask, payload)\n } else {\n await handleCreate(payload)\n }\n },\n [dialogMode, editingTask, handleCreate, handleUpdate],\n )\n\n const hasTasks = sortedTasks.length > 0\n\n return (\n <div className=\"mt-0 space-y-6\">\n <div className=\"space-y-4\">\n {isInitialLoading ? (\n <LoadingMessage\n label={t('customers.people.detail.tasks.loading', 'Loading tasks\u2026')}\n className=\"border-0 bg-transparent p-0 py-8 justify-center\"\n />\n ) : null}\n\n {!isInitialLoading && !hasTasks ? (\n <TabEmptyState\n title={emptyState.title}\n action={{\n label: emptyState.actionLabel,\n onClick: openCreateDialog,\n disabled: isMutating || !entityId,\n }}\n />\n ) : null}\n\n {!isInitialLoading && hasTasks ? (\n <div className=\"space-y-4\">\n {error ? (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-sm text-destructive\">\n {error}\n </div>\n ) : null}\n {sortedTasks.map((task) => {\n const todoHref = task.externalHref ?? resolveTodoHref(task.todoSource, task.todoId)\n const createdLabel = formatDateTime(task.createdAt) ?? emptyLabel\n const meta = renderTaskMeta(task)\n const title = task.title ?? t('customers.people.detail.tasks.untitled', 'Untitled task')\n const isDone = task.isDone === true\n const isCanceled = task.status === 'canceled'\n const checkboxId = `person-task-${task.id}`\n const isPendingToggle = pendingTaskId === task.todoId\n return (\n <article key={task.id} className=\"group space-y-3 rounded-lg border bg-card p-4 transition hover:border-border/70\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <TimelineItemHeader\n title={\n <span className=\"inline-flex items-center gap-2\">\n <input\n id={checkboxId}\n type=\"checkbox\"\n checked={isDone}\n onChange={(event) => {\n const next = event.target.checked\n void handleToggle(task, next)\n }}\n disabled={isMutating || isPendingToggle || isCanceled}\n className=\"h-4 w-4 rounded border\"\n />\n <span\n className={cn(\n 'text-sm font-semibold',\n isDone ? 'line-through text-muted-foreground' : undefined,\n isCanceled ? 'text-muted-foreground' : undefined,\n )}\n >\n {title}\n </span>\n </span>\n }\n timestamp={task.createdAt}\n fallbackTimestampLabel={createdLabel}\n />\n <div className=\"flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100\">\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => openEditDialog(task)}\n disabled={isMutating}\n aria-label={t('ui.actions.edit', 'Edit')}\n >\n {isMutating && editingTask?.id === task.id && dialogMode === 'edit' ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Pencil className=\"h-4 w-4\" />\n )}\n </IconButton>\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => handleDelete(task)}\n disabled={isMutating}\n aria-label={t('ui.actions.delete', 'Delete')}\n >\n {isMutating ? <Loader2 className=\"h-4 w-4 animate-spin text-destructive\" /> : <Trash2 className=\"h-4 w-4\" />}\n </IconButton>\n </div>\n </div>\n {meta.length ? (\n <div className=\"flex flex-wrap items-center gap-3 text-xs text-muted-foreground\">\n {meta.map((entry) => (\n <span key={`${task.id}-${entry}`} className=\"rounded bg-muted px-2 py-1 text-xs font-medium text-muted-foreground\">\n {entry}\n </span>\n ))}\n </div>\n ) : null}\n {task.description ? (\n <p className=\"text-sm text-muted-foreground whitespace-pre-wrap\">{task.description}</p>\n ) : null}\n <div className=\"flex flex-wrap items-center gap-3 text-xs\">\n {useCanonicalInteractions && !isDone && !isCanceled ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-auto px-0 text-xs font-medium text-muted-foreground hover:bg-transparent hover:text-foreground\"\n onClick={() => void handleCancel(task)}\n disabled={isMutating || isPendingToggle}\n >\n {t('customers.people.detail.tasks.cancelAction', 'Cancel task')}\n </Button>\n ) : null}\n {todoHref ? (\n <Link href={todoHref} className=\"text-primary hover:underline\">\n {t('customers.people.detail.tasks.openTask', 'Open task')}\n </Link>\n ) : null}\n </div>\n </article>\n )\n })}\n <div ref={sentinelRef} />\n {hasMore ? (\n <div className=\"flex justify-center\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => loadMore().catch(() => {})} disabled={isLoadingMore}>\n {isLoadingMore ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n {t('customers.people.detail.tasks.loadingMore', 'Loading\u2026')}\n </>\n ) : (\n t('customers.people.detail.tasks.loadMore', 'Load more')\n )}\n </Button>\n </div>\n ) : null}\n {isLoadingMore ? (\n <div className=\"flex justify-center text-xs text-muted-foreground\">\n <Loader2 className=\"mr-2 h-3 w-3 animate-spin\" />\n {t('customers.people.detail.tasks.loadingMore', 'Loading\u2026')}\n </div>\n ) : null}\n </div>\n ) : null}\n <div className=\"flex justify-center\">\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/backend/customer-tasks\">\n {t('customers.people.detail.tasks.viewAll', 'View all tasks')}\n </Link>\n </Button>\n </div>\n </div>\n\n <TaskDialog\n open={dialogOpen}\n mode={dialogMode}\n onOpenChange={(next) => {\n if (!next) closeDialog()\n else setDialogOpen(true)\n }}\n initialValues={buildInitialFormValues(editingTask)}\n onSubmit={handleDialogSubmit}\n isSubmitting={isMutating}\n contextMessage={dialogContextMessage}\n />\n </div>\n )\n}\n\nexport default TasksSection\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Loader2, Pencil, Trash2 } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { LoadingMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { InteractionSummary, SectionAction, TabEmptyStateConfig, TodoLinkSummary, Translator } from './types'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { formatDate, resolveTodoHref } from './utils'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\nimport { TimelineItemHeader } from './TimelineItemHeader'\nimport { TaskDialog } from './TaskDialog'\nimport { usePersonTasks, type TaskFormPayload } from './hooks/usePersonTasks'\nimport { useInteractions, type InteractionCreatePayload } from './hooks/useInteractions'\nimport { mapInteractionRecordToTodoSummary } from '../../lib/interactionCompatibility'\n\ntype GuardedMutationRunner = <T>(\n operation: () => Promise<T>,\n mutationPayload?: Record<string, unknown>,\n) => Promise<T>\n\ntype TasksSectionProps = {\n entityId: string | null\n initialTasks: TodoLinkSummary[]\n emptyLabel: string\n addActionLabel: string\n emptyState: TabEmptyStateConfig\n onActionChange?: (action: SectionAction | null) => void\n onLoadingChange?: (isLoading: boolean) => void\n onDataRefresh?: () => void\n translator?: Translator\n entityName?: string | null\n dialogContextKey?: string\n dialogContextFallback?: string\n /** When true, use the canonical interactions API instead of the legacy todos API. */\n useCanonicalInteractions?: boolean\n runGuardedMutation?: GuardedMutationRunner\n}\n\nconst RESERVED_TASK_CUSTOM_KEYS = new Set(['priority', 'description', 'due_at', 'dueAt'])\n\nfunction toTimestamp(value: string | null | undefined): number | null {\n if (!value) return null\n const timestamp = new Date(value).getTime()\n return Number.isNaN(timestamp) ? null : timestamp\n}\n\nfunction sortTaskSummaries(tasks: TodoLinkSummary[]): TodoLinkSummary[] {\n return [...tasks].sort((left, right) => {\n const leftDue = toTimestamp(left.dueAt)\n const rightDue = toTimestamp(right.dueAt)\n if (leftDue !== null || rightDue !== null) {\n if (leftDue === null) return 1\n if (rightDue === null) return -1\n if (leftDue !== rightDue) return leftDue - rightDue\n }\n const leftCreated = toTimestamp(left.createdAt) ?? 0\n const rightCreated = toTimestamp(right.createdAt) ?? 0\n if (leftCreated !== rightCreated) return rightCreated - leftCreated\n return left.id.localeCompare(right.id)\n })\n}\n\nfunction buildInitialFormValues(task: TodoLinkSummary | null): Record<string, unknown> | undefined {\n if (!task) return undefined\n const values: Record<string, unknown> = {\n title: task.title ?? '',\n is_done: task.isDone ?? false,\n description: task.description ?? '',\n priority: task.priority ?? '',\n scheduledAt: task.dueAt ?? '',\n }\n if (task.customValues) {\n for (const [key, value] of Object.entries(task.customValues)) {\n if (RESERVED_TASK_CUSTOM_KEYS.has(key)) continue\n const formKey = `cf_${key}`\n if (values[formKey] === undefined) values[formKey] = value\n }\n }\n return values\n}\n\nexport function TasksSection({\n entityId,\n initialTasks,\n emptyLabel,\n addActionLabel,\n emptyState,\n onActionChange,\n onLoadingChange,\n onDataRefresh,\n translator,\n entityName,\n dialogContextKey,\n dialogContextFallback,\n useCanonicalInteractions = false,\n runGuardedMutation,\n}: TasksSectionProps) {\n const tHook = useT()\n const fallbackTranslator = React.useMemo<Translator>(() => createTranslatorWithFallback(tHook), [tHook])\n const t: Translator = React.useMemo(() => translator ?? fallbackTranslator, [translator, fallbackTranslator])\n const runWriteMutation = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n if (!runGuardedMutation) {\n return operation()\n }\n return runGuardedMutation(operation, mutationPayload)\n },\n [runGuardedMutation],\n )\n\n // Legacy path: usePersonTasks (default)\n const legacyResult = usePersonTasks({ entityId, initialTasks })\n\n // Canonical path: useInteractions with planned-status filter\n const canonicalResult = useInteractions({\n entityId: useCanonicalInteractions ? entityId : null,\n typeFilter: 'task',\n })\n\n // Map canonical interactions to the TodoLinkSummary shape used by the rendering below\n const canonicalTasks = React.useMemo<TodoLinkSummary[]>(\n () => (useCanonicalInteractions ? canonicalResult.interactions.map(mapInteractionRecordToTodoSummary) : []),\n [useCanonicalInteractions, canonicalResult.interactions],\n )\n\n const canonicalCreateTask = React.useCallback(\n async (payload: TaskFormPayload) => {\n if (!entityId) throw new Error('Task creation requires an entity id')\n const interactionPayload: InteractionCreatePayload = {\n entityId,\n interactionType: 'task',\n title: payload.base.title,\n status: payload.base.is_done ? 'done' : 'planned',\n priority: payload.base.priority ?? null,\n body: payload.base.description ?? null,\n scheduledAt: payload.base.scheduledAt ?? null,\n customValues: payload.custom,\n }\n await canonicalResult.createInteraction(interactionPayload)\n },\n [canonicalResult, entityId],\n )\n\n const canonicalUpdateTask = React.useCallback(\n async (task: TodoLinkSummary, payload: TaskFormPayload) => {\n await canonicalResult.updateInteraction(task.todoId, {\n title: payload.base.title,\n status: payload.base.is_done ? 'done' : 'planned',\n priority: payload.base.priority ?? null,\n body: payload.base.description ?? null,\n scheduledAt: payload.base.scheduledAt ?? null,\n customValues: payload.custom,\n })\n },\n [canonicalResult],\n )\n\n const canonicalToggleTask = React.useCallback(\n async (task: TodoLinkSummary, nextIsDone: boolean) => {\n if (nextIsDone) {\n await canonicalResult.completeInteraction(task.todoId)\n } else {\n // Reopen: set status back to planned via update\n await canonicalResult.updateInteraction(task.todoId, { status: 'planned' })\n }\n },\n [canonicalResult],\n )\n\n const canonicalUnlinkTask = React.useCallback(\n async (task: TodoLinkSummary) => {\n await canonicalResult.deleteInteraction(task.todoId)\n },\n [canonicalResult],\n )\n\n // Unified interface: pick the active data source based on the flag\n const tasks = useCanonicalInteractions ? canonicalTasks : legacyResult.tasks\n const isInitialLoading = useCanonicalInteractions ? canonicalResult.isInitialLoading : legacyResult.isInitialLoading\n const isLoadingMore = useCanonicalInteractions ? canonicalResult.isLoadingMore : legacyResult.isLoadingMore\n const isMutating = useCanonicalInteractions ? canonicalResult.isMutating : legacyResult.isMutating\n const hasMore = useCanonicalInteractions ? canonicalResult.hasMore : legacyResult.hasMore\n const loadMore = useCanonicalInteractions ? canonicalResult.loadMore : legacyResult.loadMore\n const refresh = useCanonicalInteractions ? canonicalResult.refresh : legacyResult.refresh\n const createTask = useCanonicalInteractions ? canonicalCreateTask : legacyResult.createTask\n const updateTask = useCanonicalInteractions ? canonicalUpdateTask : legacyResult.updateTask\n const toggleTask = useCanonicalInteractions ? canonicalToggleTask : legacyResult.toggleTask\n const unlinkTask = useCanonicalInteractions ? canonicalUnlinkTask : legacyResult.unlinkTask\n const pendingTaskId = useCanonicalInteractions ? canonicalResult.pendingId : legacyResult.pendingTaskId\n const error = useCanonicalInteractions ? canonicalResult.error : legacyResult.error\n const sortedTasks = React.useMemo(() => sortTaskSummaries(tasks), [tasks])\n\n const [dialogOpen, setDialogOpen] = React.useState(false)\n const [dialogMode, setDialogMode] = React.useState<'create' | 'edit'>('create')\n const [editingTask, setEditingTask] = React.useState<TodoLinkSummary | null>(null)\n const sentinelRef = React.useRef<HTMLDivElement | null>(null)\n\n const dialogContextMessage = React.useMemo(() => {\n if (!dialogContextKey || !entityName) return undefined\n return t(dialogContextKey, dialogContextFallback ?? 'This task will be linked to {{name}}', { name: entityName })\n }, [dialogContextFallback, dialogContextKey, entityName, t])\n\n const openCreateDialog = React.useCallback(() => {\n setEditingTask(null)\n setDialogMode('create')\n setDialogOpen(true)\n }, [])\n\n const openEditDialog = React.useCallback((task: TodoLinkSummary) => {\n setEditingTask(task)\n setDialogMode('edit')\n setDialogOpen(true)\n }, [])\n\n const closeDialog = React.useCallback(() => {\n setDialogOpen(false)\n setEditingTask(null)\n }, [])\n\n React.useEffect(() => {\n if (!onActionChange) return\n if (!entityId) {\n onActionChange(null)\n return\n }\n onActionChange({\n label: addActionLabel,\n onClick: openCreateDialog,\n disabled: isMutating,\n })\n return () => {\n onActionChange(null)\n }\n }, [addActionLabel, entityId, isMutating, onActionChange, openCreateDialog])\n\n React.useEffect(() => {\n if (!onLoadingChange) return\n onLoadingChange(isInitialLoading || isMutating)\n }, [isInitialLoading, isMutating, onLoadingChange])\n\n React.useEffect(() => {\n if (!hasMore) return\n if (typeof IntersectionObserver === 'undefined') return\n const el = sentinelRef.current\n if (!el) return\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n loadMore().catch(() => {})\n }\n },\n { rootMargin: '200px 0px 200px 0px' },\n )\n observer.observe(el)\n return () => {\n observer.disconnect()\n }\n }, [hasMore, loadMore])\n\n const handleCreate = React.useCallback(\n async (payload: TaskFormPayload) => {\n try {\n await runWriteMutation(\n () => createTask(payload),\n {\n entityId,\n title: payload.base.title,\n isDone: payload.base.is_done ?? undefined,\n },\n )\n flash(t('customers.people.detail.tasks.createSuccess', 'Task created'), 'success')\n await Promise.resolve(onDataRefresh?.())\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.people.detail.tasks.error', 'Failed to create task')\n flash(message, 'error')\n throw err\n }\n },\n [createTask, entityId, onDataRefresh, runWriteMutation, t],\n )\n\n const handleUpdate = React.useCallback(\n async (task: TodoLinkSummary, payload: TaskFormPayload) => {\n try {\n await runWriteMutation(\n () => updateTask(task, payload),\n {\n id: task.id,\n todoId: task.todoId,\n title: payload.base.title,\n isDone: payload.base.is_done ?? undefined,\n },\n )\n flash(t('customers.people.detail.tasks.updateSuccess', 'Task updated'), 'success')\n await Promise.resolve(onDataRefresh?.())\n } catch (err) {\n const message =\n err instanceof Error ? err.message : t('customers.people.detail.tasks.updateError', 'Failed to update task')\n flash(message, 'error')\n throw err\n }\n },\n [onDataRefresh, runWriteMutation, t, updateTask],\n )\n\n const handleToggle = React.useCallback(\n async (task: TodoLinkSummary, nextIsDone: boolean) => {\n try {\n await runWriteMutation(\n () => toggleTask(task, nextIsDone),\n {\n id: task.id,\n todoId: task.todoId,\n isDone: nextIsDone,\n },\n )\n flash(\n nextIsDone\n ? t('customers.people.detail.tasks.completeSuccess', 'Task marked as done')\n : t('customers.people.detail.tasks.reopenSuccess', 'Task reopened'),\n 'success',\n )\n await Promise.resolve(onDataRefresh?.())\n } catch (err) {\n const message =\n err instanceof Error ? err.message : t('customers.people.detail.tasks.toggleError', 'Failed to update task status')\n flash(message, 'error')\n }\n },\n [onDataRefresh, runWriteMutation, t, toggleTask],\n )\n\n const handleDelete = React.useCallback(\n async (task: TodoLinkSummary) => {\n try {\n await runWriteMutation(\n () => unlinkTask(task),\n {\n id: task.id,\n todoId: task.todoId,\n },\n )\n flash(t('customers.people.detail.tasks.deleteSuccess', 'Task removed'), 'success')\n await Promise.resolve(onDataRefresh?.())\n await refresh()\n } catch (err) {\n const message =\n err instanceof Error ? err.message : t('customers.people.detail.tasks.deleteError', 'Failed to remove task')\n flash(message, 'error')\n }\n },\n [onDataRefresh, refresh, runWriteMutation, t, unlinkTask],\n )\n\n const handleCancel = React.useCallback(\n async (task: TodoLinkSummary) => {\n if (!useCanonicalInteractions) return\n try {\n await runWriteMutation(\n () => canonicalResult.cancelInteraction(task.todoId),\n { id: task.todoId },\n )\n flash(t('customers.people.detail.tasks.cancelSuccess', 'Task canceled'), 'success')\n await Promise.resolve(onDataRefresh?.())\n } catch (err) {\n const message =\n err instanceof Error ? err.message : t('customers.people.detail.tasks.cancelError', 'Failed to cancel task')\n flash(message, 'error')\n }\n },\n [canonicalResult, onDataRefresh, runWriteMutation, t, useCanonicalInteractions],\n )\n\n const renderTaskMeta = React.useCallback(\n (task: TodoLinkSummary) => {\n const meta: string[] = []\n if (task.status === 'canceled') {\n meta.push(t('customers.people.detail.tasks.status.canceled', 'Canceled'))\n }\n if (typeof task.priority === 'number') {\n meta.push(t('customers.people.detail.tasks.priorityLabel', 'Priority {{priority}}', { priority: task.priority }))\n }\n if (task.severity) {\n meta.push(\n t(\n `customers.people.detail.tasks.severity.${task.severity}`,\n task.severity.charAt(0).toUpperCase() + task.severity.slice(1),\n ),\n )\n }\n if (task.dueAt) {\n const dueLabel =\n formatDate(task.dueAt) ??\n formatDateTime(task.dueAt) ??\n t('customers.people.detail.tasks.dueLabel', 'Due {{date}}', { date: task.dueAt })\n meta.push(t('customers.people.detail.tasks.dueLabel', 'Due {{date}}', { date: dueLabel }))\n }\n return meta\n },\n [t],\n )\n\n const handleDialogSubmit = React.useCallback(\n async (payload: TaskFormPayload) => {\n if (dialogMode === 'edit' && editingTask) {\n await handleUpdate(editingTask, payload)\n } else {\n await handleCreate(payload)\n }\n },\n [dialogMode, editingTask, handleCreate, handleUpdate],\n )\n\n const hasTasks = sortedTasks.length > 0\n\n return (\n <div className=\"mt-0 space-y-6\">\n <div className=\"space-y-4\">\n {isInitialLoading ? (\n <LoadingMessage\n label={t('customers.people.detail.tasks.loading', 'Loading tasks\u2026')}\n className=\"border-0 bg-transparent p-0 py-8 justify-center\"\n />\n ) : null}\n\n {!isInitialLoading && !hasTasks ? (\n <TabEmptyState title={emptyState.title} />\n ) : null}\n\n {!isInitialLoading && hasTasks ? (\n <div className=\"space-y-4\">\n {error ? (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-sm text-destructive\">\n {error}\n </div>\n ) : null}\n {sortedTasks.map((task) => {\n const todoHref = task.externalHref ?? resolveTodoHref(task.todoSource, task.todoId)\n const createdLabel = formatDateTime(task.createdAt) ?? emptyLabel\n const meta = renderTaskMeta(task)\n const title = task.title ?? t('customers.people.detail.tasks.untitled', 'Untitled task')\n const isDone = task.isDone === true\n const isCanceled = task.status === 'canceled'\n const checkboxId = `person-task-${task.id}`\n const isPendingToggle = pendingTaskId === task.todoId\n return (\n <article key={task.id} className=\"group space-y-3 rounded-lg border bg-card p-4 transition hover:border-border/70\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <TimelineItemHeader\n title={\n <span className=\"inline-flex items-center gap-2\">\n <input\n id={checkboxId}\n type=\"checkbox\"\n checked={isDone}\n onChange={(event) => {\n const next = event.target.checked\n void handleToggle(task, next)\n }}\n disabled={isMutating || isPendingToggle || isCanceled}\n className=\"h-4 w-4 rounded border\"\n />\n <span\n className={cn(\n 'text-sm font-semibold',\n isDone ? 'line-through text-muted-foreground' : undefined,\n isCanceled ? 'text-muted-foreground' : undefined,\n )}\n >\n {title}\n </span>\n </span>\n }\n timestamp={task.createdAt}\n fallbackTimestampLabel={createdLabel}\n />\n <div className=\"flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100\">\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => openEditDialog(task)}\n disabled={isMutating}\n aria-label={t('ui.actions.edit', 'Edit')}\n >\n {isMutating && editingTask?.id === task.id && dialogMode === 'edit' ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Pencil className=\"h-4 w-4\" />\n )}\n </IconButton>\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => handleDelete(task)}\n disabled={isMutating}\n aria-label={t('ui.actions.delete', 'Delete')}\n >\n {isMutating ? <Loader2 className=\"h-4 w-4 animate-spin text-destructive\" /> : <Trash2 className=\"h-4 w-4\" />}\n </IconButton>\n </div>\n </div>\n {meta.length ? (\n <div className=\"flex flex-wrap items-center gap-3 text-xs text-muted-foreground\">\n {meta.map((entry) => (\n <span key={`${task.id}-${entry}`} className=\"rounded bg-muted px-2 py-1 text-xs font-medium text-muted-foreground\">\n {entry}\n </span>\n ))}\n </div>\n ) : null}\n {task.description ? (\n <p className=\"text-sm text-muted-foreground whitespace-pre-wrap\">{task.description}</p>\n ) : null}\n <div className=\"flex flex-wrap items-center gap-3 text-xs\">\n {useCanonicalInteractions && !isDone && !isCanceled ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-auto px-0 text-xs font-medium text-muted-foreground hover:bg-transparent hover:text-foreground\"\n onClick={() => void handleCancel(task)}\n disabled={isMutating || isPendingToggle}\n >\n {t('customers.people.detail.tasks.cancelAction', 'Cancel task')}\n </Button>\n ) : null}\n {todoHref ? (\n <Link href={todoHref} className=\"text-primary hover:underline\">\n {t('customers.people.detail.tasks.openTask', 'Open task')}\n </Link>\n ) : null}\n </div>\n </article>\n )\n })}\n <div ref={sentinelRef} />\n {hasMore ? (\n <div className=\"flex justify-center\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => loadMore().catch(() => {})} disabled={isLoadingMore}>\n {isLoadingMore ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n {t('customers.people.detail.tasks.loadingMore', 'Loading\u2026')}\n </>\n ) : (\n t('customers.people.detail.tasks.loadMore', 'Load more')\n )}\n </Button>\n </div>\n ) : null}\n {isLoadingMore ? (\n <div className=\"flex justify-center text-xs text-muted-foreground\">\n <Loader2 className=\"mr-2 h-3 w-3 animate-spin\" />\n {t('customers.people.detail.tasks.loadingMore', 'Loading\u2026')}\n </div>\n ) : null}\n </div>\n ) : null}\n <div className=\"flex justify-center\">\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/backend/customer-tasks\">\n {t('customers.people.detail.tasks.viewAll', 'View all tasks')}\n </Link>\n </Button>\n </div>\n </div>\n\n <TaskDialog\n open={dialogOpen}\n mode={dialogMode}\n onOpenChange={(next) => {\n if (!next) closeDialog()\n else setDialogOpen(true)\n }}\n initialValues={buildInitialFormValues(editingTask)}\n onSubmit={handleDialogSubmit}\n isSubmitting={isMutating}\n contextMessage={dialogContextMessage}\n />\n </div>\n )\n}\n\nexport default TasksSection\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -7,6 +7,7 @@ import { Check, Pencil, Plus } from "lucide-react";
|
|
|
7
7
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
8
8
|
import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
|
|
9
9
|
import { Button } from "@open-mercato/ui/primitives/button";
|
|
10
|
+
import { deriveDisplayName, isDerivedDisplayName } from "../lib/displayName.js";
|
|
10
11
|
import {
|
|
11
12
|
Dialog,
|
|
12
13
|
DialogContent,
|
|
@@ -504,15 +505,14 @@ const createPersonFormSchema = () => z.object({
|
|
|
504
505
|
const createDisplayNameSection = (t) => function DisplayNameSection({ values, setValue, errors }) {
|
|
505
506
|
const [editing, setEditing] = React.useState(false);
|
|
506
507
|
const [manualOverride, setManualOverride] = React.useState(() => {
|
|
507
|
-
const current = typeof values.displayName === "string" ? values.displayName
|
|
508
|
-
|
|
508
|
+
const current = typeof values.displayName === "string" ? values.displayName : "";
|
|
509
|
+
const firstInit = typeof values.firstName === "string" ? values.firstName : "";
|
|
510
|
+
const lastInit = typeof values.lastName === "string" ? values.lastName : "";
|
|
511
|
+
return !isDerivedDisplayName(current, firstInit, lastInit);
|
|
509
512
|
});
|
|
510
513
|
const first = typeof values.firstName === "string" ? values.firstName.trim() : "";
|
|
511
514
|
const last = typeof values.lastName === "string" ? values.lastName.trim() : "";
|
|
512
|
-
const derived = React.useMemo(() =>
|
|
513
|
-
const parts = [first, last].filter((part) => !!part);
|
|
514
|
-
return parts.join(" ").trim();
|
|
515
|
-
}, [first, last]);
|
|
515
|
+
const derived = React.useMemo(() => deriveDisplayName(first, last), [first, last]);
|
|
516
516
|
React.useEffect(() => {
|
|
517
517
|
if (!manualOverride) {
|
|
518
518
|
const target = derived || "";
|
|
@@ -1275,39 +1275,50 @@ const createPersonEditGroups = (t) => [
|
|
|
1275
1275
|
kind: "customFields"
|
|
1276
1276
|
}
|
|
1277
1277
|
];
|
|
1278
|
-
const createPersonPersonalDataGroups = (t) =>
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1278
|
+
const createPersonPersonalDataGroups = (t, options) => {
|
|
1279
|
+
const entityName = options?.entityName?.trim() || null;
|
|
1280
|
+
const rolesTitle = entityName ? t("customers.roles.groupTitle.person", "My roles with {{name}}", { name: entityName }) : t("customers.people.form.groups.roles", "My roles");
|
|
1281
|
+
return [
|
|
1282
|
+
{
|
|
1283
|
+
id: "personalDataDisplay",
|
|
1284
|
+
title: t("customers.people.form.groups.displayName", "Display name"),
|
|
1285
|
+
column: 1,
|
|
1286
|
+
bare: true,
|
|
1287
|
+
component: createDisplayNameSection(t)
|
|
1288
|
+
},
|
|
1289
|
+
{
|
|
1290
|
+
id: "personalData",
|
|
1291
|
+
title: t("customers.people.form.groups.personalData", "Personal data"),
|
|
1292
|
+
column: 1,
|
|
1293
|
+
fields: ["firstName", "lastName", "jobTitle", "primaryEmail", "primaryPhone"]
|
|
1294
|
+
},
|
|
1295
|
+
{
|
|
1296
|
+
id: "companyRole",
|
|
1297
|
+
title: t("customers.people.form.groups.companyRole", "Company & role"),
|
|
1298
|
+
column: 1,
|
|
1299
|
+
fields: ["companyEntityId", "status", "lifecycleStage", "source"]
|
|
1300
|
+
},
|
|
1301
|
+
{
|
|
1302
|
+
id: "customFields",
|
|
1303
|
+
title: t("customers.people.form.groups.customAttributes", "Custom attributes"),
|
|
1304
|
+
column: 1,
|
|
1305
|
+
kind: "customFields"
|
|
1306
|
+
},
|
|
1307
|
+
{
|
|
1308
|
+
id: "roles",
|
|
1309
|
+
title: rolesTitle,
|
|
1310
|
+
column: 1,
|
|
1311
|
+
component: ({ values }) => values.id ? /* @__PURE__ */ jsx(
|
|
1312
|
+
RolesSection,
|
|
1313
|
+
{
|
|
1314
|
+
entityType: "person",
|
|
1315
|
+
entityId: values.id,
|
|
1316
|
+
entityName: typeof values.displayName === "string" ? values.displayName : null
|
|
1317
|
+
}
|
|
1318
|
+
) : null
|
|
1319
|
+
}
|
|
1320
|
+
];
|
|
1321
|
+
};
|
|
1311
1322
|
function buildCompanyEditPayload(values, organizationId) {
|
|
1312
1323
|
const payload = buildCompanyPayload(values, organizationId);
|
|
1313
1324
|
payload.id = values.id;
|