@open-mercato/ui 0.5.1-develop.2953.6647bb2c43 → 0.5.1-develop.2964.d5ac4a6ebb
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 +8 -0
- package/dist/backend/CrudForm.js +57 -29
- package/dist/backend/CrudForm.js.map +2 -2
- package/dist/backend/DataTable.js +32 -14
- package/dist/backend/DataTable.js.map +2 -2
- package/dist/backend/FilterOverlay.js +23 -17
- package/dist/backend/FilterOverlay.js.map +2 -2
- package/dist/backend/JsonBuilder.js +32 -18
- package/dist/backend/JsonBuilder.js.map +2 -2
- package/dist/backend/columns/ColumnChooserPanel.js +12 -13
- package/dist/backend/columns/ColumnChooserPanel.js.map +2 -2
- package/dist/backend/custom-fields/FieldDefinitionsEditor.js +71 -62
- package/dist/backend/custom-fields/FieldDefinitionsEditor.js.map +2 -2
- package/dist/backend/date-range/DateRangeSelect.js +11 -10
- package/dist/backend/date-range/DateRangeSelect.js.map +2 -2
- package/dist/backend/date-range/InlineDateRangeSelect.js +10 -22
- package/dist/backend/date-range/InlineDateRangeSelect.js.map +2 -2
- package/dist/backend/detail/ActivitiesSection.js +20 -12
- package/dist/backend/detail/ActivitiesSection.js.map +2 -2
- package/dist/backend/detail/AddressEditor.js +24 -7
- package/dist/backend/detail/AddressEditor.js.map +2 -2
- package/dist/backend/detail/InlineEditors.js +12 -6
- package/dist/backend/detail/InlineEditors.js.map +2 -2
- package/dist/backend/detail/NotesSection.js +20 -14
- package/dist/backend/detail/NotesSection.js.map +2 -2
- package/dist/backend/filters/AdvancedFilterBuilder.js +52 -24
- package/dist/backend/filters/AdvancedFilterBuilder.js.map +2 -2
- package/dist/backend/injection/InjectedField.js +12 -7
- package/dist/backend/injection/InjectedField.js.map +2 -2
- package/dist/backend/inputs/ComboboxInput.js.map +2 -2
- package/dist/backend/inputs/EventSelect.js +22 -6
- package/dist/backend/inputs/EventSelect.js.map +2 -2
- package/dist/backend/inputs/PhoneNumberField.js +2 -2
- package/dist/backend/inputs/PhoneNumberField.js.map +2 -2
- package/dist/backend/inputs/TimeInput.js +9 -10
- package/dist/backend/inputs/TimeInput.js.map +2 -2
- package/dist/backend/messages/message-compose-form-groups.js +12 -7
- package/dist/backend/messages/message-compose-form-groups.js.map +2 -2
- package/dist/backend/messages/useMessageCompose.js +7 -1
- package/dist/backend/messages/useMessageCompose.js.map +2 -2
- package/dist/frontend/LanguageSwitcher.js +19 -14
- package/dist/frontend/LanguageSwitcher.js.map +2 -2
- package/dist/index.js +5 -0
- package/dist/index.js.map +2 -2
- package/dist/primitives/checkbox-field.js +17 -5
- package/dist/primitives/checkbox-field.js.map +2 -2
- package/dist/primitives/input.js +71 -14
- package/dist/primitives/input.js.map +2 -2
- package/dist/primitives/radio-field.js +74 -0
- package/dist/primitives/radio-field.js.map +7 -0
- package/dist/primitives/radio.js +37 -0
- package/dist/primitives/radio.js.map +7 -0
- package/dist/primitives/select.js +155 -0
- package/dist/primitives/select.js.map +7 -0
- package/dist/primitives/switch-field.js +76 -0
- package/dist/primitives/switch-field.js.map +7 -0
- package/dist/primitives/switch.js +17 -3
- package/dist/primitives/switch.js.map +2 -2
- package/dist/primitives/textarea.js +48 -12
- package/dist/primitives/textarea.js.map +2 -2
- package/dist/primitives/tooltip.js +44 -15
- package/dist/primitives/tooltip.js.map +2 -2
- package/package.json +5 -3
- package/src/backend/CrudForm.tsx +104 -37
- package/src/backend/DataTable.tsx +38 -20
- package/src/backend/FilterOverlay.tsx +35 -21
- package/src/backend/JsonBuilder.tsx +38 -20
- package/src/backend/__tests__/FieldDefinitionsEditor.test.tsx +23 -6
- package/src/backend/columns/ColumnChooserPanel.tsx +9 -10
- package/src/backend/custom-fields/FieldDefinitionsEditor.tsx +120 -87
- package/src/backend/date-range/DateRangeSelect.tsx +19 -12
- package/src/backend/date-range/InlineDateRangeSelect.tsx +16 -20
- package/src/backend/detail/ActivitiesSection.tsx +35 -23
- package/src/backend/detail/AddressEditor.tsx +30 -16
- package/src/backend/detail/InlineEditors.tsx +21 -11
- package/src/backend/detail/NotesSection.tsx +35 -25
- package/src/backend/filters/AdvancedFilterBuilder.tsx +60 -34
- package/src/backend/injection/InjectedField.tsx +21 -12
- package/src/backend/inputs/ComboboxInput.tsx +4 -0
- package/src/backend/inputs/EventSelect.tsx +30 -17
- package/src/backend/inputs/PhoneNumberField.tsx +2 -2
- package/src/backend/inputs/TimeInput.tsx +9 -10
- package/src/backend/messages/message-compose-form-groups.tsx +21 -12
- package/src/backend/messages/useMessageCompose.ts +20 -1
- package/src/frontend/LanguageSwitcher.tsx +20 -17
- package/src/index.ts +5 -0
- package/src/primitives/checkbox-field.tsx +10 -2
- package/src/primitives/input.tsx +73 -12
- package/src/primitives/radio-field.tsx +92 -0
- package/src/primitives/radio.tsx +42 -0
- package/src/primitives/select.tsx +200 -0
- package/src/primitives/switch-field.tsx +100 -0
- package/src/primitives/switch.tsx +17 -4
- package/src/primitives/textarea.tsx +67 -11
- package/src/primitives/tooltip.tsx +68 -24
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/date-range/InlineDateRangeSelect.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { DATE_RANGE_OPTIONS, type DateRangePreset } from './dateRanges'\n\nexport type InlineDateRangeSelectProps = {\n value: DateRangePreset\n onChange: (value: DateRangePreset) => void\n className?: string\n}\n\nexport function InlineDateRangeSelect({\n value,\n onChange,\n className = '',\n}: InlineDateRangeSelectProps) {\n const t = useT()\n\n const currentOption = DATE_RANGE_OPTIONS.find((opt) => opt.value === value)\n const displayLabel = currentOption\n ? t(currentOption.labelKey, currentOption.value.replace(/_/g, ' '))\n : value.replace(/_/g, ' ')\n\n return (\n <
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../../primitives/select'\nimport { DATE_RANGE_OPTIONS, type DateRangePreset } from './dateRanges'\n\nexport type InlineDateRangeSelectProps = {\n value: DateRangePreset\n onChange: (value: DateRangePreset) => void\n className?: string\n}\n\nexport function InlineDateRangeSelect({\n value,\n onChange,\n className = '',\n}: InlineDateRangeSelectProps) {\n const t = useT()\n\n const currentOption = DATE_RANGE_OPTIONS.find((opt) => opt.value === value)\n const displayLabel = currentOption\n ? t(currentOption.labelKey, currentOption.value.replace(/_/g, ' '))\n : value.replace(/_/g, ' ')\n\n return (\n <Select value={value} onValueChange={(next) => onChange(next as DateRangePreset)}>\n <SelectTrigger size=\"sm\" className={className} title={displayLabel}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {DATE_RANGE_OPTIONS.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {t(option.labelKey, option.value.replace(/_/g, ' '))}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )\n}\n\nexport default InlineDateRangeSelect\n"],
|
|
5
|
+
"mappings": ";AAgCI,SAEI,KAFJ;AA7BJ,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,0BAAgD;AAQlD,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA,YAAY;AACd,GAA+B;AAC7B,QAAM,IAAI,KAAK;AAEf,QAAM,gBAAgB,mBAAmB,KAAK,CAAC,QAAQ,IAAI,UAAU,KAAK;AAC1E,QAAM,eAAe,gBACjB,EAAE,cAAc,UAAU,cAAc,MAAM,QAAQ,MAAM,GAAG,CAAC,IAChE,MAAM,QAAQ,MAAM,GAAG;AAE3B,SACE,qBAAC,UAAO,OAAc,eAAe,CAAC,SAAS,SAAS,IAAuB,GAC7E;AAAA,wBAAC,iBAAc,MAAK,MAAK,WAAsB,OAAO,cACpD,8BAAC,eAAY,GACf;AAAA,IACA,oBAAC,iBACE,6BAAmB,IAAI,CAAC,WACvB,oBAAC,cAA8B,OAAO,OAAO,OAC1C,YAAE,OAAO,UAAU,OAAO,MAAM,QAAQ,MAAM,GAAG,CAAC,KADpC,OAAO,KAExB,CACD,GACH;AAAA,KACF;AAEJ;AAEA,IAAO,gCAAQ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -4,6 +4,13 @@ import * as React from "react";
|
|
|
4
4
|
import Link from "next/link";
|
|
5
5
|
import { ArrowUpRightSquare, Pencil, Plus, Trash2 } from "lucide-react";
|
|
6
6
|
import { Button } from "@open-mercato/ui/primitives/button";
|
|
7
|
+
import {
|
|
8
|
+
Select,
|
|
9
|
+
SelectContent,
|
|
10
|
+
SelectItem,
|
|
11
|
+
SelectTrigger,
|
|
12
|
+
SelectValue
|
|
13
|
+
} from "@open-mercato/ui/primitives/select";
|
|
7
14
|
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
8
15
|
import { createCrudFormError } from "@open-mercato/ui/backend/utils/serverErrors";
|
|
9
16
|
import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
|
|
@@ -165,13 +172,15 @@ function ActivityForm({
|
|
|
165
172
|
layout: "half",
|
|
166
173
|
component: ({ value, setValue }) => {
|
|
167
174
|
const currentValue = typeof value === "string" && value.length ? value : normalizedEntityOptions[0]?.id ?? "";
|
|
168
|
-
return /* @__PURE__ */
|
|
169
|
-
|
|
175
|
+
return /* @__PURE__ */ jsxs(
|
|
176
|
+
Select,
|
|
170
177
|
{
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
178
|
+
value: currentValue || void 0,
|
|
179
|
+
onValueChange: (next) => setValue(next ?? ""),
|
|
180
|
+
children: [
|
|
181
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
182
|
+
/* @__PURE__ */ jsx(SelectContent, { children: normalizedEntityOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.id, children: option.label }, option.id)) })
|
|
183
|
+
]
|
|
175
184
|
}
|
|
176
185
|
);
|
|
177
186
|
}
|
|
@@ -186,14 +195,13 @@ function ActivityForm({
|
|
|
186
195
|
component: ({ value, setValue }) => {
|
|
187
196
|
const currentValue = typeof value === "string" ? value : "";
|
|
188
197
|
return /* @__PURE__ */ jsxs(
|
|
189
|
-
|
|
198
|
+
Select,
|
|
190
199
|
{
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
onChange: (event) => setValue(event.target.value),
|
|
200
|
+
value: currentValue || void 0,
|
|
201
|
+
onValueChange: (next) => setValue(next ?? ""),
|
|
194
202
|
children: [
|
|
195
|
-
/* @__PURE__ */ jsx(
|
|
196
|
-
normalizedDealOptions.map((option) => /* @__PURE__ */ jsx(
|
|
203
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: translate("fields.dealPlaceholder", "No linked deal") }) }),
|
|
204
|
+
/* @__PURE__ */ jsx(SelectContent, { children: normalizedDealOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.id, children: option.label }, option.id)) })
|
|
197
205
|
]
|
|
198
206
|
}
|
|
199
207
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/detail/ActivitiesSection.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { ArrowUpRightSquare, Pencil, Plus, Trash2 } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { DictionaryEntrySelect, type DictionarySelectLabels } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport type { AppearanceSelectorLabels } from '@open-mercato/core/modules/dictionaries/components/AppearanceSelector'\nimport { formatRelativeTime, formatDateTime } from '@open-mercato/shared/lib/time'\nimport { LoadingMessage, TabEmptyState } from './'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { useConfirmDialog } from '../confirm-dialog'\nimport { ComponentReplacementHandles } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { useRegisteredComponent } from '../injection/useRegisteredComponent'\n\ntype Translator = (key: string, fallback?: string, params?: Record<string, string | number>) => string\n\nexport type ActivitySummary = {\n id: string\n activityType: string\n subject?: string | null\n body?: string | null\n occurredAt?: string | null\n createdAt: string\n appearanceIcon?: string | null\n appearanceColor?: string | null\n entityId?: string | null\n authorUserId?: string | null\n authorName?: string | null\n authorEmail?: string | null\n dealId?: string | null\n dealTitle?: string | null\n customFields?: Array<{ key: string; label?: string | null; value: unknown }>\n customValues?: Record<string, unknown> | null\n}\n\nexport type SectionAction = {\n label: React.ReactNode\n onClick: () => void\n disabled?: boolean\n icon?: React.ReactNode\n}\n\nexport type TabEmptyStateConfig = {\n title: string\n actionLabel: string\n description?: string\n}\n\nexport type ActivityCreatePayload = {\n entityId: string\n activityType: string\n subject?: string | null\n body?: string | null\n occurredAt?: string | null\n dealId?: string | null\n customFields?: Record<string, unknown>\n}\n\nexport type ActivityUpdatePayload = Partial<ActivityCreatePayload>\n\nexport type ActivitiesDataAdapter<C = unknown> = {\n list: (params: { entityId: string | null; dealId?: string | null; context?: C }) => Promise<ActivitySummary[]>\n create: (params: ActivityCreatePayload & { context?: C }) => Promise<void>\n update: (params: { id: string; patch: ActivityUpdatePayload; context?: C }) => Promise<void>\n delete: (params: { id: string; context?: C }) => Promise<void>\n}\n\ntype DictionaryOption = {\n value: string\n label: string\n color: string | null\n icon: string | null\n}\n\ntype ActivityTypePresentation = {\n label: string\n icon?: string | null\n color?: string | null\n}\n\ntype PendingAction =\n | { kind: 'create' }\n | { kind: 'update'; id: string }\n | { kind: 'delete'; id: string }\n\nconst INVALID_DATE_MESSAGE = 'invalidDate'\n\nconst schema = {\n validate(values: Record<string, unknown>) {\n const result: { ok: boolean; errors?: Array<{ path: string; message: string }> } = { ok: true }\n const activityType = typeof values.activityType === 'string' ? values.activityType.trim() : ''\n if (!activityType) {\n result.ok = false\n result.errors = [{ path: 'activityType', message: 'required' }]\n return result\n }\n const occurredAt = typeof values.occurredAt === 'string' ? values.occurredAt.trim() : ''\n if (occurredAt.length) {\n const parsed = new Date(occurredAt)\n if (Number.isNaN(parsed.getTime())) {\n result.ok = false\n result.errors = [{ path: 'occurredAt', message: INVALID_DATE_MESSAGE }]\n }\n }\n return result\n },\n}\n\nfunction toLocalDateTimeInput(value?: string | null): string {\n if (!value) return ''\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return ''\n const pad = (input: number) => `${input}`.padStart(2, '0')\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(\n date.getMinutes(),\n )}`\n}\n\n\ntype TimelineItemHeaderProps = {\n title: React.ReactNode\n subtitle?: React.ReactNode\n timestamp?: string | Date | null\n fallbackTimestampLabel?: React.ReactNode\n icon?: string | null\n color?: string | null\n iconSize?: 'sm' | 'md'\n className?: string\n renderIcon?: (icon: string, className?: string) => React.ReactNode\n renderColor?: (color: string, className?: string) => React.ReactNode\n}\n\nfunction TimelineItemHeader({\n title,\n subtitle,\n timestamp,\n fallbackTimestampLabel,\n icon,\n color,\n iconSize = 'md',\n className,\n renderIcon,\n renderColor,\n}: TimelineItemHeaderProps) {\n const wrapperSize = iconSize === 'sm' ? 'h-6 w-6' : 'h-8 w-8'\n const iconSizeClass = iconSize === 'sm' ? 'h-3.5 w-3.5' : 'h-4 w-4'\n const resolvedTimestamp = React.useMemo(() => {\n if (subtitle) return subtitle\n if (!timestamp) return fallbackTimestampLabel ?? null\n const value = typeof timestamp === 'string' ? timestamp : timestamp.toISOString()\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return fallbackTimestampLabel ?? null\n const now = Date.now()\n const diff = Math.abs(now - date.getTime())\n const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000\n const relativeLabel = diff <= THIRTY_DAYS_MS ? formatRelativeTime(value) : null\n const absoluteLabel = formatDateTime(value)\n if (relativeLabel) {\n return (\n <span title={absoluteLabel ?? undefined}>\n {relativeLabel}\n </span>\n )\n }\n return absoluteLabel ?? fallbackTimestampLabel ?? null\n }, [fallbackTimestampLabel, subtitle, timestamp])\n\n const iconNode = icon && renderIcon ? renderIcon(icon, iconSizeClass) : null\n\n return (\n <div className={['flex items-start gap-3', className].filter(Boolean).join(' ')}>\n {iconNode ? (\n <span className={['inline-flex items-center justify-center rounded border border-border bg-muted/50', wrapperSize].join(' ')}>\n {iconNode}\n </span>\n ) : null}\n <div className=\"space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-semibold text-foreground\">{title}</span>\n {color && renderColor ? renderColor(color, 'h-3 w-3 rounded-full border border-border') : null}\n </div>\n {resolvedTimestamp ? <div className=\"text-xs text-muted-foreground\">{resolvedTimestamp}</div> : null}\n </div>\n </div>\n )\n}\n\nexport type ActivityFormBaseValues = {\n activityType: string\n subject?: string | null\n body?: string | null\n occurredAt?: string | null\n dealId?: string | null\n}\n\nexport type ActivityFormSubmitPayload = {\n base: ActivityFormBaseValues\n custom: Record<string, unknown>\n entityId?: string | null\n}\n\ntype ActivityFormProps = {\n mode: 'create' | 'edit'\n initialValues?: Partial<ActivityFormBaseValues & Record<string, unknown>>\n onSubmit: (payload: ActivityFormSubmitPayload) => Promise<void>\n onCancel: () => void\n submitLabel?: string\n cancelLabel?: string\n isSubmitting?: boolean\n activityTypeLabels: DictionarySelectLabels\n loadActivityOptions: () => Promise<DictionaryOption[]>\n createActivityOption?: (input: { value: string; label?: string; color?: string | null; icon?: string | null }) => Promise<DictionaryOption>\n dealOptions?: Array<{ id: string; label: string }>\n entityOptions?: Array<{ id: string; label: string }>\n defaultEntityId?: string | null\n manageHref?: string\n customFieldEntityIds?: string[]\n labelPrefix?: string\n appearanceLabels?: AppearanceSelectorLabels\n}\n\nfunction normalizeCustomFieldSubmitValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.filter((entry) => entry !== undefined)\n }\n if (value === undefined) return null\n return value\n}\n\nfunction buildActivityValidationError(errors: Array<{ path: string; message: string }>, translate: (key: string, fallback?: string) => string) {\n const issue = errors[0]\n if (!issue) {\n throw createCrudFormError(translate('error', 'Failed to save activity.'))\n }\n const message = issue.message === INVALID_DATE_MESSAGE\n ? translate('invalidDate', 'Invalid date')\n : translate('error', 'Failed to save activity.')\n const field = issue.path\n throw createCrudFormError(message, field ? { [field]: message } : undefined)\n}\n\nfunction ActivityForm({\n mode,\n initialValues,\n onSubmit,\n onCancel,\n submitLabel,\n cancelLabel,\n isSubmitting = false,\n activityTypeLabels,\n loadActivityOptions,\n createActivityOption,\n dealOptions,\n entityOptions,\n defaultEntityId,\n manageHref = '/backend/config/dictionaries',\n customFieldEntityIds,\n labelPrefix = 'customers.people.detail.activities',\n appearanceLabels,\n}: ActivityFormProps) {\n const tHook = useT()\n const t = React.useMemo<Translator>(() => createTranslatorWithFallback(tHook), [tHook])\n const translate = React.useCallback(\n (suffix: string, fallback?: string) => t(`${labelPrefix}.${suffix}`, fallback ?? ''),\n [labelPrefix, t],\n )\n const [pending, setPending] = React.useState(false)\n\n const normalizedDealOptions = React.useMemo(() => {\n if (!Array.isArray(dealOptions)) return []\n const seen = new Set<string>()\n return dealOptions\n .map((option) => {\n if (!option || typeof option !== 'object') return null\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (!id || seen.has(id)) return null\n const label =\n typeof option.label === 'string' && option.label.trim().length\n ? option.label.trim()\n : id\n seen.add(id)\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => !!option)\n }, [dealOptions])\n\n const normalizedEntityOptions = React.useMemo(() => {\n if (!Array.isArray(entityOptions)) return []\n const seen = new Set<string>()\n return entityOptions\n .map((option) => {\n if (!option || typeof option !== 'object') return null\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (!id || seen.has(id)) return null\n const label =\n typeof option.label === 'string' && option.label.trim().length\n ? option.label.trim()\n : id\n seen.add(id)\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => !!option)\n }, [entityOptions])\n\n const baseFields = React.useMemo<CrudField[]>(() => {\n const fields: CrudField[] = []\n\n if (normalizedEntityOptions.length) {\n fields.push({\n id: 'entityId',\n label: translate('fields.entity', 'Assign to record'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => {\n const currentValue =\n typeof value === 'string' && value.length ? value : normalizedEntityOptions[0]?.id ?? ''\n return (\n <select\n className=\"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-ring\"\n value={currentValue}\n onChange={(event) => setValue(event.target.value)}\n >\n {normalizedEntityOptions.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n )\n },\n } as CrudField)\n }\n\n if (normalizedDealOptions.length) {\n fields.push({\n id: 'dealId',\n label: translate('fields.deal', 'Link to deal (optional)'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => {\n const currentValue = typeof value === 'string' ? value : ''\n return (\n <select\n className=\"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-ring\"\n value={currentValue}\n onChange={(event) => setValue(event.target.value)}\n >\n <option value=\"\">\n {translate('fields.dealPlaceholder', 'No linked deal')}\n </option>\n {normalizedDealOptions.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n )\n },\n } as CrudField)\n }\n\n fields.push({\n id: 'activityType',\n label: translate('fields.type', 'Activity type'),\n type: 'custom',\n required: true,\n layout: 'half',\n component: ({ value, setValue }) => (\n <DictionaryEntrySelect\n value={typeof value === 'string' ? value : undefined}\n onChange={(next) => setValue(next ?? '')}\n fetchOptions={loadActivityOptions}\n createOption={createActivityOption}\n labels={activityTypeLabels}\n allowAppearance\n allowInlineCreate\n appearanceLabels={appearanceLabels}\n selectClassName=\"w-full\"\n manageHref={manageHref}\n />\n ),\n } as CrudField)\n\n fields.push({\n id: 'subject',\n label: translate('fields.subject', 'Subject'),\n type: 'text',\n layout: 'half',\n placeholder: translate('subjectPlaceholder', 'Add a subject (optional)'),\n } as CrudField)\n\n fields.push({\n id: 'body',\n label: translate('fields.body', 'Details'),\n type: 'textarea',\n placeholder: translate('bodyPlaceholder', 'Describe the interaction'),\n } as CrudField)\n\n fields.push({\n id: 'occurredAt',\n label: translate('fields.occurredAt', 'Occurred / will occur at'),\n type: 'custom',\n component: ({ value, setValue }) => (\n <input\n type=\"datetime-local\"\n className=\"w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n value={typeof value === 'string' ? value : ''}\n onChange={(event) => setValue(event.target.value || '')}\n onFocus={(event) => {\n const target = event.currentTarget as HTMLInputElement & { showPicker?: () => void }\n if (typeof target.showPicker === 'function') {\n try { target.showPicker() } catch { /* ignore unsupported */ }\n }\n }}\n onClick={(event) => {\n const target = event.currentTarget as HTMLInputElement & { showPicker?: () => void }\n if (typeof target.showPicker === 'function') {\n try { target.showPicker() } catch { /* ignore unsupported */ }\n }\n }}\n />\n ),\n layout: 'half',\n } as CrudField)\n\n return fields\n }, [\n activityTypeLabels,\n appearanceLabels,\n createActivityOption,\n loadActivityOptions,\n manageHref,\n normalizedDealOptions,\n normalizedEntityOptions,\n translate,\n ])\n\n const baseFieldIds = React.useMemo(() => new Set(baseFields.map((field) => field.id)), [baseFields])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => {\n const detailFields: string[] = []\n if (normalizedEntityOptions.length) detailFields.push('entityId')\n if (normalizedDealOptions.length) detailFields.push('dealId')\n detailFields.push('activityType', 'subject', 'occurredAt', 'body')\n const baseGroups: CrudFormGroup[] = [\n {\n id: 'details',\n title: translate('form.details', 'Activity details'),\n column: 1,\n fields: detailFields,\n },\n ]\n baseGroups.push({\n id: 'custom',\n title: translate('form.customFields', 'Custom fields'),\n column: 2,\n kind: 'customFields',\n })\n return baseGroups\n }, [normalizedDealOptions.length, normalizedEntityOptions.length, translate])\n\n const handleSubmit = React.useCallback(\n async (values: Record<string, unknown>) => {\n if (pending || isSubmitting) return\n setPending(true)\n try {\n const parsed = schema.validate(values)\n if (!parsed.ok) {\n throw buildActivityValidationError(parsed.errors ?? [], translate)\n }\n const rawEntityId = typeof values.entityId === 'string' ? values.entityId.trim() : ''\n const resolvedEntityId = rawEntityId || (typeof defaultEntityId === 'string' ? defaultEntityId : '')\n const rawDealId = typeof values.dealId === 'string' ? values.dealId.trim() : ''\n const base: ActivityFormBaseValues = {\n activityType: typeof values.activityType === 'string' ? values.activityType.trim() : '',\n subject: typeof values.subject === 'string' && values.subject.trim().length ? values.subject.trim() : undefined,\n body: typeof values.body === 'string' && values.body.trim().length ? values.body.trim() : undefined,\n occurredAt: typeof values.occurredAt === 'string' && values.occurredAt.trim().length\n ? new Date(values.occurredAt as string).toISOString()\n : undefined,\n dealId: rawDealId.length ? rawDealId : undefined,\n }\n const reservedCustomKeys = new Set(['entityId', 'dealId'])\n const customEntries = collectCustomFieldValues(values, {\n transform: (value) => normalizeCustomFieldSubmitValue(value),\n accept: (fieldId) => !reservedCustomKeys.has(fieldId),\n })\n Object.entries(values).forEach(([key, value]) => {\n if (key.startsWith('cf_')) return\n if (!baseFieldIds.has(key) && key !== 'id') {\n if (reservedCustomKeys.has(key)) return\n customEntries[key] = normalizeCustomFieldSubmitValue(value)\n }\n })\n await onSubmit({ base, custom: customEntries, entityId: resolvedEntityId.length ? resolvedEntityId : undefined })\n } finally {\n setPending(false)\n }\n },\n [baseFieldIds, defaultEntityId, isSubmitting, onSubmit, pending, translate],\n )\n\n const embeddedInitialValues = React.useMemo(() => {\n const occurredAt = toLocalDateTimeInput(initialValues?.occurredAt ?? null)\n const resolvedEntity = (() => {\n const raw = typeof (initialValues as Record<string, unknown> | undefined)?.entityId === 'string'\n ? (initialValues as Record<string, unknown>).entityId as string\n : typeof defaultEntityId === 'string'\n ? defaultEntityId\n : normalizedEntityOptions[0]?.id ?? ''\n return raw ?? ''\n })()\n const resolvedDeal = typeof (initialValues as Record<string, unknown> | undefined)?.dealId === 'string'\n ? (initialValues as Record<string, unknown>).dealId as string\n : ''\n\n return {\n entityId: resolvedEntity,\n dealId: resolvedDeal,\n activityType: initialValues?.activityType ?? '',\n subject: initialValues?.subject ?? '',\n body: initialValues?.body ?? '',\n occurredAt,\n ...Object.fromEntries(\n Object.entries(initialValues ?? {})\n .filter(([key]) => {\n if (!key.startsWith('cf_')) return false\n const trimmed = key.slice(3)\n return trimmed !== 'entityId' && trimmed !== 'dealId'\n })\n .map(([key, value]) => [key, value]),\n ),\n }\n }, [defaultEntityId, initialValues, normalizedEntityOptions])\n\n return (\n <CrudForm<Record<string, unknown>>\n embedded\n fields={baseFields}\n groups={groups}\n initialValues={embeddedInitialValues}\n onSubmit={handleSubmit}\n submitLabel={submitLabel ?? (mode === 'edit'\n ? translate('update', 'Update activity (\u2318/Ctrl + Enter)')\n : translate('save', 'Save activity (\u2318/Ctrl + Enter)'))}\n extraActions={(\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onCancel}\n disabled={pending || isSubmitting}\n >\n {cancelLabel ?? translate('cancel', 'Cancel')}\n </Button>\n )}\n entityIds={customFieldEntityIds}\n />\n )\n}\n\ntype ActivityDialogProps = {\n open: boolean\n mode: 'create' | 'edit'\n onOpenChange: (next: boolean) => void\n initialValues?: Partial<ActivityFormBaseValues & Record<string, unknown>>\n onSubmit: (payload: ActivityFormSubmitPayload) => Promise<void>\n isSubmitting?: boolean\n activityTypeLabels: DictionarySelectLabels\n loadActivityOptions: () => Promise<DictionaryOption[]>\n createActivityOption?: (input: { value: string; label?: string; color?: string | null; icon?: string | null }) => Promise<DictionaryOption>\n titles?: {\n create?: string\n edit?: string\n }\n submitLabels?: {\n create?: string\n edit?: string\n }\n cancelLabel?: string\n dealOptions?: Array<{ id: string; label: string }>\n entityOptions?: Array<{ id: string; label: string }>\n defaultEntityId?: string | null\n manageHref?: string\n customFieldEntityIds?: string[]\n labelPrefix?: string\n appearanceLabels?: AppearanceSelectorLabels\n}\n\nfunction ActivityDialog({\n open,\n mode,\n onOpenChange,\n initialValues,\n onSubmit,\n isSubmitting,\n activityTypeLabels,\n loadActivityOptions,\n createActivityOption,\n titles,\n submitLabels,\n cancelLabel,\n dealOptions,\n entityOptions,\n defaultEntityId,\n manageHref,\n customFieldEntityIds,\n labelPrefix = 'customers.people.detail.activities',\n appearanceLabels,\n}: ActivityDialogProps) {\n const tHook = useT()\n const t = React.useMemo<Translator>(() => createTranslatorWithFallback(tHook), [tHook])\n const translate = React.useCallback(\n (suffix: string, fallback?: string, params?: Record<string, string | number>) =>\n t(`${labelPrefix}.${suffix}`, fallback ?? '', params),\n [labelPrefix, t],\n )\n\n const dialogTitle =\n mode === 'edit'\n ? titles?.edit ?? translate('editTitle', 'Edit activity')\n : titles?.create ?? translate('addTitle', 'Add activity')\n\n const resolvedSubmitLabel =\n mode === 'edit'\n ? submitLabels?.edit ?? translate('update', 'Update activity (\u2318/Ctrl + Enter)')\n : submitLabels?.create ?? translate('save', 'Save activity (\u2318/Ctrl + Enter)')\n\n const resolvedCancelLabel = cancelLabel ?? translate('cancel', 'Cancel')\n\n const handleCancel = React.useCallback(() => {\n onOpenChange(false)\n }, [onOpenChange])\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-3xl\">\n <DialogHeader>\n <DialogTitle>{dialogTitle}</DialogTitle>\n </DialogHeader>\n <ActivityForm\n mode={mode}\n initialValues={initialValues}\n onSubmit={onSubmit}\n onCancel={handleCancel}\n submitLabel={resolvedSubmitLabel}\n cancelLabel={resolvedCancelLabel}\n isSubmitting={isSubmitting}\n activityTypeLabels={activityTypeLabels}\n loadActivityOptions={loadActivityOptions}\n createActivityOption={createActivityOption}\n dealOptions={dealOptions}\n entityOptions={entityOptions}\n defaultEntityId={defaultEntityId}\n manageHref={manageHref}\n customFieldEntityIds={customFieldEntityIds}\n labelPrefix={labelPrefix}\n appearanceLabels={appearanceLabels}\n />\n </DialogContent>\n </Dialog>\n )\n}\n\nexport type ActivitiesSectionProps<C = unknown> = {\n entityId: string | null\n dealId?: string | null\n addActionLabel: string\n emptyState: TabEmptyStateConfig\n onActionChange?: (action: SectionAction | null) => void\n onLoadingChange?: (isLoading: boolean) => void\n dealOptions?: Array<{ id: string; label: string }>\n entityOptions?: Array<{ id: string; label: string }>\n defaultEntityId?: string | null\n dataAdapter: ActivitiesDataAdapter<C>\n dataContext?: C\n activityTypeLabels: DictionarySelectLabels\n loadActivityOptions: () => Promise<DictionaryOption[]>\n createActivityOption?: (input: { value: string; label?: string; color?: string | null; icon?: string | null }) => Promise<DictionaryOption>\n resolveActivityPresentation?: (activity: ActivitySummary) => ActivityTypePresentation\n renderCustomFields?: (activity: ActivitySummary) => React.ReactNode\n customFieldEntityIds?: string[]\n labelPrefix?: string\n renderIcon?: (icon: string, className?: string) => React.ReactNode\n renderColor?: (color: string, className?: string) => React.ReactNode\n appearanceLabels?: AppearanceSelectorLabels\n dealLinkHref?: (dealId: string) => string\n manageHref?: string\n}\n\nfunction ActivitiesSectionImpl<C = unknown>({\n entityId,\n dealId,\n addActionLabel,\n emptyState,\n onActionChange,\n onLoadingChange,\n dealOptions,\n entityOptions,\n defaultEntityId,\n dataAdapter,\n dataContext,\n activityTypeLabels,\n loadActivityOptions,\n createActivityOption,\n resolveActivityPresentation,\n renderCustomFields,\n customFieldEntityIds,\n labelPrefix = 'customers.people.detail.activities',\n renderIcon,\n renderColor,\n appearanceLabels,\n dealLinkHref,\n manageHref,\n}: ActivitiesSectionProps<C>) {\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const tHook = useT()\n const baseTranslator = React.useMemo<Translator>(() => createTranslatorWithFallback(tHook), [tHook])\n const translate = React.useCallback(\n (suffix: string, fallback?: string, params?: Record<string, string | number>) =>\n baseTranslator(`${labelPrefix}.${suffix}`, fallback ?? '', params),\n [baseTranslator, labelPrefix],\n )\n const resolvedDefaultEntityId = React.useMemo(() => {\n const primary = typeof entityId === 'string' ? entityId.trim() : ''\n if (primary.length) return primary\n const fallback = typeof defaultEntityId === 'string' ? defaultEntityId.trim() : ''\n if (fallback.length) return fallback\n if (Array.isArray(entityOptions)) {\n for (const option of entityOptions) {\n if (!option || typeof option !== 'object') continue\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (id.length) return id\n }\n }\n return ''\n }, [defaultEntityId, entityId, entityOptions])\n\n const resolveEntityForSubmission = React.useCallback(\n (input?: string | null) => {\n const candidate = typeof input === 'string' ? input.trim() : ''\n if (candidate.length) return candidate\n return resolvedDefaultEntityId.length ? resolvedDefaultEntityId : null\n },\n [resolvedDefaultEntityId],\n )\n\n const [activities, setActivities] = React.useState<ActivitySummary[]>([])\n const [isLoading, setIsLoading] = React.useState<boolean>(() => {\n const entity = typeof entityId === 'string' ? entityId.trim() : ''\n const deal = typeof dealId === 'string' ? dealId.trim() : ''\n return Boolean(entity || deal || resolvedDefaultEntityId)\n })\n const [loadError, setLoadError] = React.useState<string | null>(null)\n const [pendingAction, setPendingAction] = React.useState<PendingAction | null>(null)\n const [dialogOpen, setDialogOpen] = React.useState(false)\n const [dialogMode, setDialogMode] = React.useState<'create' | 'edit'>('create')\n const [editingActivityId, setEditingActivityId] = React.useState<string | null>(null)\n const [initialValues, setInitialValues] = React.useState<Partial<ActivityFormBaseValues & Record<string, unknown>> | undefined>(undefined)\n const [visibleCount, setVisibleCount] = React.useState(0)\n const pendingCounterRef = React.useRef(0)\n const onLoadingChangeRef = React.useRef(onLoadingChange)\n React.useEffect(() => { onLoadingChangeRef.current = onLoadingChange })\n\n const t = translate\n\n const pushLoading = React.useCallback(() => {\n pendingCounterRef.current += 1\n if (pendingCounterRef.current === 1) {\n onLoadingChangeRef.current?.(true)\n }\n }, [])\n\n const popLoading = React.useCallback(() => {\n pendingCounterRef.current = Math.max(0, pendingCounterRef.current - 1)\n if (pendingCounterRef.current === 0) {\n onLoadingChangeRef.current?.(false)\n }\n }, [])\n\n const updateVisibleCount = React.useCallback((length: number) => {\n if (!length) {\n setVisibleCount(0)\n return\n }\n const baseline = Math.min(5, length)\n setVisibleCount((prev) => {\n if (prev >= length) {\n return Math.min(prev, length)\n }\n return Math.min(Math.max(prev, baseline), length)\n })\n }, [])\n\n const loadActivities = React.useCallback(async () => {\n const queryEntityId = typeof entityId === 'string' ? entityId.trim() : ''\n const queryDealId = typeof dealId === 'string' ? dealId.trim() : ''\n if (!queryEntityId && !queryDealId) {\n setActivities([])\n setLoadError(null)\n updateVisibleCount(0)\n return\n }\n pushLoading()\n setIsLoading(true)\n try {\n const items = await dataAdapter.list({\n entityId: queryEntityId || null,\n dealId: queryDealId || null,\n context: dataContext,\n })\n setActivities(items)\n setLoadError(null)\n updateVisibleCount(items.length)\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : t('loadError', 'Failed to load activities.')\n setLoadError(message)\n } finally {\n setIsLoading(false)\n popLoading()\n }\n }, [dataAdapter, dataContext, dealId, entityId, popLoading, pushLoading, t, updateVisibleCount])\n\n React.useEffect(() => {\n updateVisibleCount(activities.length)\n }, [activities.length, updateVisibleCount])\n\n React.useEffect(() => {\n const queryEntityId = typeof entityId === 'string' ? entityId.trim() : ''\n const queryDealId = typeof dealId === 'string' ? dealId.trim() : ''\n if (!queryEntityId && !queryDealId) {\n setActivities([])\n setLoadError(null)\n setIsLoading(false)\n pendingCounterRef.current = 0\n onLoadingChangeRef.current?.(false)\n updateVisibleCount(0)\n return\n }\n loadActivities().catch(() => {})\n }, [dealId, entityId, loadActivities, updateVisibleCount])\n\n const openCreateDialog = React.useCallback(() => {\n setDialogMode('create')\n setEditingActivityId(null)\n setInitialValues(undefined)\n setDialogOpen(true)\n }, [])\n\n const openEditDialog = React.useCallback((activity: ActivitySummary) => {\n setDialogMode('edit')\n setEditingActivityId(activity.id)\n const baseValues: Partial<ActivityFormBaseValues & Record<string, unknown>> = {\n activityType: activity.activityType,\n subject: activity.subject ?? '',\n body: activity.body ?? '',\n occurredAt: activity.occurredAt ?? activity.createdAt ?? null,\n dealId: activity.dealId ?? '',\n entityId: activity.entityId ?? '',\n }\n const customEntries = Array.isArray(activity.customFields) ? activity.customFields : []\n customEntries.forEach((entry) => {\n if (entry.key === 'entityId' || entry.key === 'dealId') return\n baseValues[`cf_${entry.key}`] = entry.value ?? null\n })\n setInitialValues(baseValues)\n setDialogOpen(true)\n }, [])\n\n const closeDialog = React.useCallback(() => {\n setDialogOpen(false)\n setDialogMode('create')\n setEditingActivityId(null)\n setInitialValues(undefined)\n }, [])\n\n const handleDialogOpenChange = React.useCallback(\n (next: boolean) => {\n if (!next) {\n closeDialog()\n } else {\n setDialogOpen(true)\n }\n },\n [closeDialog],\n )\n\n const handleCreate = React.useCallback(\n async ({ base, custom, entityId: formEntityId }: ActivityFormSubmitPayload) => {\n const submissionEntityId = resolveEntityForSubmission(formEntityId)\n if (!submissionEntityId) {\n const message = t('entityMissing', 'Select a related record before saving.')\n flash(message, 'error')\n throw new Error(message)\n }\n setPendingAction({ kind: 'create' })\n pushLoading()\n try {\n const payload: ActivityCreatePayload = {\n entityId: submissionEntityId,\n activityType: base.activityType,\n subject: base.subject ?? undefined,\n body: base.body ?? undefined,\n occurredAt: base.occurredAt ?? undefined,\n dealId: base.dealId ?? undefined,\n customFields: Object.keys(custom).length ? custom : undefined,\n }\n await dataAdapter.create({ ...payload, context: dataContext })\n await loadActivities()\n flash(t('success', 'Activity saved'), 'success')\n } finally {\n setPendingAction(null)\n popLoading()\n }\n },\n [dataAdapter, dataContext, loadActivities, popLoading, pushLoading, resolveEntityForSubmission, t],\n )\n\n const handleUpdate = React.useCallback(\n async (activityId: string, { base, custom, entityId: formEntityId }: ActivityFormSubmitPayload) => {\n const submissionEntityId = resolveEntityForSubmission(formEntityId)\n if (!submissionEntityId) {\n const message = t('entityMissing', 'Select a related record before saving.')\n flash(message, 'error')\n throw new Error(message)\n }\n setPendingAction({ kind: 'update', id: activityId })\n pushLoading()\n try {\n const patch: ActivityUpdatePayload = {\n entityId: submissionEntityId,\n activityType: base.activityType,\n subject: base.subject ?? undefined,\n body: base.body ?? undefined,\n occurredAt: base.occurredAt ?? undefined,\n dealId: base.dealId ?? undefined,\n customFields: Object.keys(custom).length ? custom : undefined,\n }\n await dataAdapter.update({ id: activityId, patch, context: dataContext })\n await loadActivities()\n flash(t('updateSuccess', 'Activity updated.'), 'success')\n } finally {\n setPendingAction(null)\n popLoading()\n }\n },\n [dataAdapter, dataContext, loadActivities, popLoading, pushLoading, resolveEntityForSubmission, t],\n )\n\n const handleDelete = React.useCallback(\n async (activity: ActivitySummary) => {\n if (!activity.id) return\n const confirmed = await confirm({\n title: t('deleteConfirm', 'Delete this activity? You can restore it using version history.'),\n variant: 'destructive',\n })\n if (!confirmed) return\n setPendingAction({ kind: 'delete', id: activity.id })\n try {\n await dataAdapter.delete({ id: activity.id, context: dataContext })\n setActivities((prev) => prev.filter((existing) => existing.id !== activity.id))\n flash(t('deleteSuccess', 'Activity deleted.'), 'success')\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : t('deleteError', 'Failed to delete activity.')\n flash(message, 'error')\n } finally {\n setPendingAction(null)\n }\n },\n [confirm, dataAdapter, dataContext, t],\n )\n\n const handleDialogSubmit = React.useCallback(\n async (payload: ActivityFormSubmitPayload) => {\n try {\n if (dialogMode === 'edit' && editingActivityId) {\n await handleUpdate(editingActivityId, payload)\n } else {\n await handleCreate(payload)\n }\n closeDialog()\n } catch (err) {\n const message =\n err instanceof Error ? err.message : t('error', 'Failed to save activity')\n flash(message, 'error')\n }\n },\n [closeDialog, dialogMode, editingActivityId, handleCreate, handleUpdate, t],\n )\n\n React.useEffect(() => {\n if (!onActionChange) return\n if (activities.length === 0) {\n onActionChange(null)\n return () => {\n onActionChange(null)\n }\n }\n const disabled = resolveEntityForSubmission(null) === null || pendingAction !== null || isLoading\n const action: SectionAction = {\n label: (\n <span className=\"inline-flex items-center gap-1.5\">\n <Plus className=\"h-4 w-4\" />\n {addActionLabel}\n </span>\n ),\n onClick: () => {\n if (!disabled) openCreateDialog()\n },\n disabled,\n }\n onActionChange(action)\n return () => {\n onActionChange(null)\n }\n }, [\n activities.length,\n addActionLabel,\n isLoading,\n onActionChange,\n openCreateDialog,\n pendingAction,\n resolveEntityForSubmission,\n ])\n\n const isFormPending =\n pendingAction?.kind === 'create' ||\n (pendingAction?.kind === 'update' && pendingAction.id === editingActivityId)\n const visibleActivities = React.useMemo(\n () => activities.slice(0, visibleCount),\n [activities, visibleCount],\n )\n const hasMoreActivities = visibleCount < activities.length\n const loadMoreLabel = t('loadMore', 'Load more activities')\n\n const handleLoadMore = React.useCallback(() => {\n setVisibleCount((prev) => {\n if (prev >= activities.length) return prev\n return Math.min(prev + 5, activities.length)\n })\n }, [activities.length])\n\n const resolvePresentation = React.useCallback(\n (activity: ActivitySummary): ActivityTypePresentation => {\n if (resolveActivityPresentation) return resolveActivityPresentation(activity)\n return {\n label: activity.activityType,\n icon: activity.appearanceIcon ?? null,\n color: activity.appearanceColor ?? null,\n }\n },\n [resolveActivityPresentation],\n )\n\n const resolveDealHref = React.useCallback(\n (id: string) => (dealLinkHref ? dealLinkHref(id) : `/backend/customers/deals/${encodeURIComponent(id)}`),\n [dealLinkHref],\n )\n\n return (\n <div className=\"mt-3 space-y-4\">\n {loadError ? (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-sm text-destructive\">\n {loadError}\n </div>\n ) : null}\n <div className=\"space-y-4\">\n {isLoading && activities.length === 0 ? (\n <LoadingMessage\n label={t('loading', 'Loading activities\u2026')}\n className=\"border-0 bg-transparent p-0 py-8 justify-center\"\n />\n ) : (\n <>\n {!isLoading && activities.length === 0 && !dialogOpen ? (\n <TabEmptyState\n title={emptyState.title}\n action={{\n label: emptyState.actionLabel,\n onClick: openCreateDialog,\n disabled: resolveEntityForSubmission(null) === null || pendingAction !== null,\n }}\n />\n ) : null}\n {visibleActivities.length > 0\n ? visibleActivities.map((activity) => {\n const presentation = resolvePresentation(activity)\n const timestampValue = activity.occurredAt ?? activity.createdAt ?? null\n const occurredLabel =\n formatDateTime(timestampValue) ?? t('noDate', 'No date provided')\n const authorLabel = activity.authorName ?? activity.authorEmail ?? null\n const loggedByText = authorLabel\n ? (() => {\n const translated = t('loggedBy', `Logged by ${authorLabel}`, { user: authorLabel })\n if (\n !translated ||\n translated.includes('{{') ||\n translated.includes('{user')\n ) {\n return `Logged by ${authorLabel}`\n }\n return translated\n })()\n : null\n const isUpdatePending = pendingAction?.kind === 'update' && pendingAction.id === activity.id\n const isDeletePending = pendingAction?.kind === 'delete' && pendingAction.id === activity.id\n\n return (\n <div\n key={activity.id}\n className=\"group space-y-3 rounded-lg border bg-card p-4 transition hover:border-border/70 cursor-pointer\"\n role=\"button\"\n tabIndex={0}\n onClick={() => openEditDialog(activity)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n openEditDialog(activity)\n }\n }}\n >\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"space-y-1\">\n <TimelineItemHeader\n title={presentation.label}\n timestamp={timestampValue}\n fallbackTimestampLabel={occurredLabel}\n icon={presentation.icon}\n color={presentation.color}\n renderIcon={renderIcon}\n renderColor={renderColor}\n />\n {activity.dealId ? (\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <ArrowUpRightSquare className=\"h-3.5 w-3.5\" />\n <Link\n href={resolveDealHref(activity.dealId)}\n className=\"font-medium text-foreground hover:underline\"\n onClick={(event) => event.stopPropagation()}\n >\n {activity.dealTitle && activity.dealTitle.length\n ? activity.dealTitle\n : t('linkedDeal', 'Linked deal')}\n </Link>\n </div>\n ) : null}\n </div>\n <div className=\"flex items-center gap-1 opacity-100 md:opacity-0 transition-opacity md:group-hover:opacity-100 focus-within:opacity-100\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={(event) => {\n event.stopPropagation()\n openEditDialog(activity)\n }}\n disabled={pendingAction !== null}\n >\n {isUpdatePending ? (\n <span className=\"relative flex h-4 w-4 items-center justify-center\">\n <span className=\"absolute h-4 w-4 animate-spin rounded-full border border-primary border-t-transparent\" />\n </span>\n ) : (\n <Pencil className=\"h-4 w-4\" />\n )}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={(event) => {\n event.stopPropagation()\n handleDelete(activity).catch(() => {})\n }}\n disabled={pendingAction !== null}\n >\n {isDeletePending ? (\n <span className=\"relative flex h-4 w-4 items-center justify-center text-destructive\">\n <span className=\"absolute h-4 w-4 animate-spin rounded-full border border-destructive border-t-transparent\" />\n </span>\n ) : (\n <Trash2 className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </div>\n {activity.subject ? <p className=\"text-sm font-medium\">{activity.subject}</p> : null}\n {activity.body ? (\n <p className=\"text-sm whitespace-pre-wrap text-muted-foreground\">{activity.body}</p>\n ) : null}\n {renderCustomFields ? renderCustomFields(activity) : null}\n {loggedByText ? (\n <p className=\"text-xs text-muted-foreground\">{loggedByText}</p>\n ) : null}\n </div>\n )\n })\n : null}\n {hasMoreActivities ? (\n <div className=\"flex justify-center\">\n <Button variant=\"outline\" size=\"sm\" onClick={handleLoadMore} disabled={pendingAction !== null}>\n {loadMoreLabel}\n </Button>\n </div>\n ) : null}\n </>\n )}\n </div>\n\n <ActivityDialog\n open={dialogOpen}\n mode={dialogMode}\n onOpenChange={handleDialogOpenChange}\n initialValues={initialValues}\n onSubmit={async (payload) => {\n await handleDialogSubmit(payload)\n }}\n isSubmitting={Boolean(isFormPending)}\n activityTypeLabels={activityTypeLabels}\n loadActivityOptions={loadActivityOptions}\n createActivityOption={createActivityOption}\n dealOptions={dealOptions}\n entityOptions={entityOptions}\n defaultEntityId={resolvedDefaultEntityId || undefined}\n manageHref={manageHref}\n customFieldEntityIds={customFieldEntityIds}\n labelPrefix={labelPrefix}\n appearanceLabels={appearanceLabels}\n />\n {ConfirmDialogElement}\n </div>\n )\n}\n\nexport function ActivitiesSection<C = unknown>(props: ActivitiesSectionProps<C>) {\n const handle = ComponentReplacementHandles.section('ui.detail', 'ActivitiesSection')\n const Resolved = useRegisteredComponent<ActivitiesSectionProps<C>>(\n handle,\n ActivitiesSectionImpl as React.ComponentType<ActivitiesSectionProps<C>>,\n )\n\n return (\n <div data-component-handle={handle}>\n <Resolved {...props} />\n </div>\n )\n}\n\nexport default ActivitiesSection\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { ArrowUpRightSquare, Pencil, Plus, Trash2 } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { DictionaryEntrySelect, type DictionarySelectLabels } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport type { AppearanceSelectorLabels } from '@open-mercato/core/modules/dictionaries/components/AppearanceSelector'\nimport { formatRelativeTime, formatDateTime } from '@open-mercato/shared/lib/time'\nimport { LoadingMessage, TabEmptyState } from './'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { useConfirmDialog } from '../confirm-dialog'\nimport { ComponentReplacementHandles } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { useRegisteredComponent } from '../injection/useRegisteredComponent'\n\ntype Translator = (key: string, fallback?: string, params?: Record<string, string | number>) => string\n\nexport type ActivitySummary = {\n id: string\n activityType: string\n subject?: string | null\n body?: string | null\n occurredAt?: string | null\n createdAt: string\n appearanceIcon?: string | null\n appearanceColor?: string | null\n entityId?: string | null\n authorUserId?: string | null\n authorName?: string | null\n authorEmail?: string | null\n dealId?: string | null\n dealTitle?: string | null\n customFields?: Array<{ key: string; label?: string | null; value: unknown }>\n customValues?: Record<string, unknown> | null\n}\n\nexport type SectionAction = {\n label: React.ReactNode\n onClick: () => void\n disabled?: boolean\n icon?: React.ReactNode\n}\n\nexport type TabEmptyStateConfig = {\n title: string\n actionLabel: string\n description?: string\n}\n\nexport type ActivityCreatePayload = {\n entityId: string\n activityType: string\n subject?: string | null\n body?: string | null\n occurredAt?: string | null\n dealId?: string | null\n customFields?: Record<string, unknown>\n}\n\nexport type ActivityUpdatePayload = Partial<ActivityCreatePayload>\n\nexport type ActivitiesDataAdapter<C = unknown> = {\n list: (params: { entityId: string | null; dealId?: string | null; context?: C }) => Promise<ActivitySummary[]>\n create: (params: ActivityCreatePayload & { context?: C }) => Promise<void>\n update: (params: { id: string; patch: ActivityUpdatePayload; context?: C }) => Promise<void>\n delete: (params: { id: string; context?: C }) => Promise<void>\n}\n\ntype DictionaryOption = {\n value: string\n label: string\n color: string | null\n icon: string | null\n}\n\ntype ActivityTypePresentation = {\n label: string\n icon?: string | null\n color?: string | null\n}\n\ntype PendingAction =\n | { kind: 'create' }\n | { kind: 'update'; id: string }\n | { kind: 'delete'; id: string }\n\nconst INVALID_DATE_MESSAGE = 'invalidDate'\n\nconst schema = {\n validate(values: Record<string, unknown>) {\n const result: { ok: boolean; errors?: Array<{ path: string; message: string }> } = { ok: true }\n const activityType = typeof values.activityType === 'string' ? values.activityType.trim() : ''\n if (!activityType) {\n result.ok = false\n result.errors = [{ path: 'activityType', message: 'required' }]\n return result\n }\n const occurredAt = typeof values.occurredAt === 'string' ? values.occurredAt.trim() : ''\n if (occurredAt.length) {\n const parsed = new Date(occurredAt)\n if (Number.isNaN(parsed.getTime())) {\n result.ok = false\n result.errors = [{ path: 'occurredAt', message: INVALID_DATE_MESSAGE }]\n }\n }\n return result\n },\n}\n\nfunction toLocalDateTimeInput(value?: string | null): string {\n if (!value) return ''\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return ''\n const pad = (input: number) => `${input}`.padStart(2, '0')\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(\n date.getMinutes(),\n )}`\n}\n\n\ntype TimelineItemHeaderProps = {\n title: React.ReactNode\n subtitle?: React.ReactNode\n timestamp?: string | Date | null\n fallbackTimestampLabel?: React.ReactNode\n icon?: string | null\n color?: string | null\n iconSize?: 'sm' | 'md'\n className?: string\n renderIcon?: (icon: string, className?: string) => React.ReactNode\n renderColor?: (color: string, className?: string) => React.ReactNode\n}\n\nfunction TimelineItemHeader({\n title,\n subtitle,\n timestamp,\n fallbackTimestampLabel,\n icon,\n color,\n iconSize = 'md',\n className,\n renderIcon,\n renderColor,\n}: TimelineItemHeaderProps) {\n const wrapperSize = iconSize === 'sm' ? 'h-6 w-6' : 'h-8 w-8'\n const iconSizeClass = iconSize === 'sm' ? 'h-3.5 w-3.5' : 'h-4 w-4'\n const resolvedTimestamp = React.useMemo(() => {\n if (subtitle) return subtitle\n if (!timestamp) return fallbackTimestampLabel ?? null\n const value = typeof timestamp === 'string' ? timestamp : timestamp.toISOString()\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return fallbackTimestampLabel ?? null\n const now = Date.now()\n const diff = Math.abs(now - date.getTime())\n const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000\n const relativeLabel = diff <= THIRTY_DAYS_MS ? formatRelativeTime(value) : null\n const absoluteLabel = formatDateTime(value)\n if (relativeLabel) {\n return (\n <span title={absoluteLabel ?? undefined}>\n {relativeLabel}\n </span>\n )\n }\n return absoluteLabel ?? fallbackTimestampLabel ?? null\n }, [fallbackTimestampLabel, subtitle, timestamp])\n\n const iconNode = icon && renderIcon ? renderIcon(icon, iconSizeClass) : null\n\n return (\n <div className={['flex items-start gap-3', className].filter(Boolean).join(' ')}>\n {iconNode ? (\n <span className={['inline-flex items-center justify-center rounded border border-border bg-muted/50', wrapperSize].join(' ')}>\n {iconNode}\n </span>\n ) : null}\n <div className=\"space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-semibold text-foreground\">{title}</span>\n {color && renderColor ? renderColor(color, 'h-3 w-3 rounded-full border border-border') : null}\n </div>\n {resolvedTimestamp ? <div className=\"text-xs text-muted-foreground\">{resolvedTimestamp}</div> : null}\n </div>\n </div>\n )\n}\n\nexport type ActivityFormBaseValues = {\n activityType: string\n subject?: string | null\n body?: string | null\n occurredAt?: string | null\n dealId?: string | null\n}\n\nexport type ActivityFormSubmitPayload = {\n base: ActivityFormBaseValues\n custom: Record<string, unknown>\n entityId?: string | null\n}\n\ntype ActivityFormProps = {\n mode: 'create' | 'edit'\n initialValues?: Partial<ActivityFormBaseValues & Record<string, unknown>>\n onSubmit: (payload: ActivityFormSubmitPayload) => Promise<void>\n onCancel: () => void\n submitLabel?: string\n cancelLabel?: string\n isSubmitting?: boolean\n activityTypeLabels: DictionarySelectLabels\n loadActivityOptions: () => Promise<DictionaryOption[]>\n createActivityOption?: (input: { value: string; label?: string; color?: string | null; icon?: string | null }) => Promise<DictionaryOption>\n dealOptions?: Array<{ id: string; label: string }>\n entityOptions?: Array<{ id: string; label: string }>\n defaultEntityId?: string | null\n manageHref?: string\n customFieldEntityIds?: string[]\n labelPrefix?: string\n appearanceLabels?: AppearanceSelectorLabels\n}\n\nfunction normalizeCustomFieldSubmitValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.filter((entry) => entry !== undefined)\n }\n if (value === undefined) return null\n return value\n}\n\nfunction buildActivityValidationError(errors: Array<{ path: string; message: string }>, translate: (key: string, fallback?: string) => string) {\n const issue = errors[0]\n if (!issue) {\n throw createCrudFormError(translate('error', 'Failed to save activity.'))\n }\n const message = issue.message === INVALID_DATE_MESSAGE\n ? translate('invalidDate', 'Invalid date')\n : translate('error', 'Failed to save activity.')\n const field = issue.path\n throw createCrudFormError(message, field ? { [field]: message } : undefined)\n}\n\nfunction ActivityForm({\n mode,\n initialValues,\n onSubmit,\n onCancel,\n submitLabel,\n cancelLabel,\n isSubmitting = false,\n activityTypeLabels,\n loadActivityOptions,\n createActivityOption,\n dealOptions,\n entityOptions,\n defaultEntityId,\n manageHref = '/backend/config/dictionaries',\n customFieldEntityIds,\n labelPrefix = 'customers.people.detail.activities',\n appearanceLabels,\n}: ActivityFormProps) {\n const tHook = useT()\n const t = React.useMemo<Translator>(() => createTranslatorWithFallback(tHook), [tHook])\n const translate = React.useCallback(\n (suffix: string, fallback?: string) => t(`${labelPrefix}.${suffix}`, fallback ?? ''),\n [labelPrefix, t],\n )\n const [pending, setPending] = React.useState(false)\n\n const normalizedDealOptions = React.useMemo(() => {\n if (!Array.isArray(dealOptions)) return []\n const seen = new Set<string>()\n return dealOptions\n .map((option) => {\n if (!option || typeof option !== 'object') return null\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (!id || seen.has(id)) return null\n const label =\n typeof option.label === 'string' && option.label.trim().length\n ? option.label.trim()\n : id\n seen.add(id)\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => !!option)\n }, [dealOptions])\n\n const normalizedEntityOptions = React.useMemo(() => {\n if (!Array.isArray(entityOptions)) return []\n const seen = new Set<string>()\n return entityOptions\n .map((option) => {\n if (!option || typeof option !== 'object') return null\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (!id || seen.has(id)) return null\n const label =\n typeof option.label === 'string' && option.label.trim().length\n ? option.label.trim()\n : id\n seen.add(id)\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => !!option)\n }, [entityOptions])\n\n const baseFields = React.useMemo<CrudField[]>(() => {\n const fields: CrudField[] = []\n\n if (normalizedEntityOptions.length) {\n fields.push({\n id: 'entityId',\n label: translate('fields.entity', 'Assign to record'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => {\n const currentValue =\n typeof value === 'string' && value.length ? value : normalizedEntityOptions[0]?.id ?? ''\n return (\n <Select\n value={currentValue || undefined}\n onValueChange={(next) => setValue(next ?? '')}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {normalizedEntityOptions.map((option) => (\n <SelectItem key={option.id} value={option.id}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )\n },\n } as CrudField)\n }\n\n if (normalizedDealOptions.length) {\n fields.push({\n id: 'dealId',\n label: translate('fields.deal', 'Link to deal (optional)'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => {\n const currentValue = typeof value === 'string' ? value : ''\n return (\n <Select\n value={currentValue || undefined}\n onValueChange={(next) => setValue(next ?? '')}\n >\n <SelectTrigger>\n <SelectValue placeholder={translate('fields.dealPlaceholder', 'No linked deal')} />\n </SelectTrigger>\n <SelectContent>\n {normalizedDealOptions.map((option) => (\n <SelectItem key={option.id} value={option.id}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )\n },\n } as CrudField)\n }\n\n fields.push({\n id: 'activityType',\n label: translate('fields.type', 'Activity type'),\n type: 'custom',\n required: true,\n layout: 'half',\n component: ({ value, setValue }) => (\n <DictionaryEntrySelect\n value={typeof value === 'string' ? value : undefined}\n onChange={(next) => setValue(next ?? '')}\n fetchOptions={loadActivityOptions}\n createOption={createActivityOption}\n labels={activityTypeLabels}\n allowAppearance\n allowInlineCreate\n appearanceLabels={appearanceLabels}\n selectClassName=\"w-full\"\n manageHref={manageHref}\n />\n ),\n } as CrudField)\n\n fields.push({\n id: 'subject',\n label: translate('fields.subject', 'Subject'),\n type: 'text',\n layout: 'half',\n placeholder: translate('subjectPlaceholder', 'Add a subject (optional)'),\n } as CrudField)\n\n fields.push({\n id: 'body',\n label: translate('fields.body', 'Details'),\n type: 'textarea',\n placeholder: translate('bodyPlaceholder', 'Describe the interaction'),\n } as CrudField)\n\n fields.push({\n id: 'occurredAt',\n label: translate('fields.occurredAt', 'Occurred / will occur at'),\n type: 'custom',\n component: ({ value, setValue }) => (\n <input\n type=\"datetime-local\"\n className=\"w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n value={typeof value === 'string' ? value : ''}\n onChange={(event) => setValue(event.target.value || '')}\n onFocus={(event) => {\n const target = event.currentTarget as HTMLInputElement & { showPicker?: () => void }\n if (typeof target.showPicker === 'function') {\n try { target.showPicker() } catch { /* ignore unsupported */ }\n }\n }}\n onClick={(event) => {\n const target = event.currentTarget as HTMLInputElement & { showPicker?: () => void }\n if (typeof target.showPicker === 'function') {\n try { target.showPicker() } catch { /* ignore unsupported */ }\n }\n }}\n />\n ),\n layout: 'half',\n } as CrudField)\n\n return fields\n }, [\n activityTypeLabels,\n appearanceLabels,\n createActivityOption,\n loadActivityOptions,\n manageHref,\n normalizedDealOptions,\n normalizedEntityOptions,\n translate,\n ])\n\n const baseFieldIds = React.useMemo(() => new Set(baseFields.map((field) => field.id)), [baseFields])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => {\n const detailFields: string[] = []\n if (normalizedEntityOptions.length) detailFields.push('entityId')\n if (normalizedDealOptions.length) detailFields.push('dealId')\n detailFields.push('activityType', 'subject', 'occurredAt', 'body')\n const baseGroups: CrudFormGroup[] = [\n {\n id: 'details',\n title: translate('form.details', 'Activity details'),\n column: 1,\n fields: detailFields,\n },\n ]\n baseGroups.push({\n id: 'custom',\n title: translate('form.customFields', 'Custom fields'),\n column: 2,\n kind: 'customFields',\n })\n return baseGroups\n }, [normalizedDealOptions.length, normalizedEntityOptions.length, translate])\n\n const handleSubmit = React.useCallback(\n async (values: Record<string, unknown>) => {\n if (pending || isSubmitting) return\n setPending(true)\n try {\n const parsed = schema.validate(values)\n if (!parsed.ok) {\n throw buildActivityValidationError(parsed.errors ?? [], translate)\n }\n const rawEntityId = typeof values.entityId === 'string' ? values.entityId.trim() : ''\n const resolvedEntityId = rawEntityId || (typeof defaultEntityId === 'string' ? defaultEntityId : '')\n const rawDealId = typeof values.dealId === 'string' ? values.dealId.trim() : ''\n const base: ActivityFormBaseValues = {\n activityType: typeof values.activityType === 'string' ? values.activityType.trim() : '',\n subject: typeof values.subject === 'string' && values.subject.trim().length ? values.subject.trim() : undefined,\n body: typeof values.body === 'string' && values.body.trim().length ? values.body.trim() : undefined,\n occurredAt: typeof values.occurredAt === 'string' && values.occurredAt.trim().length\n ? new Date(values.occurredAt as string).toISOString()\n : undefined,\n dealId: rawDealId.length ? rawDealId : undefined,\n }\n const reservedCustomKeys = new Set(['entityId', 'dealId'])\n const customEntries = collectCustomFieldValues(values, {\n transform: (value) => normalizeCustomFieldSubmitValue(value),\n accept: (fieldId) => !reservedCustomKeys.has(fieldId),\n })\n Object.entries(values).forEach(([key, value]) => {\n if (key.startsWith('cf_')) return\n if (!baseFieldIds.has(key) && key !== 'id') {\n if (reservedCustomKeys.has(key)) return\n customEntries[key] = normalizeCustomFieldSubmitValue(value)\n }\n })\n await onSubmit({ base, custom: customEntries, entityId: resolvedEntityId.length ? resolvedEntityId : undefined })\n } finally {\n setPending(false)\n }\n },\n [baseFieldIds, defaultEntityId, isSubmitting, onSubmit, pending, translate],\n )\n\n const embeddedInitialValues = React.useMemo(() => {\n const occurredAt = toLocalDateTimeInput(initialValues?.occurredAt ?? null)\n const resolvedEntity = (() => {\n const raw = typeof (initialValues as Record<string, unknown> | undefined)?.entityId === 'string'\n ? (initialValues as Record<string, unknown>).entityId as string\n : typeof defaultEntityId === 'string'\n ? defaultEntityId\n : normalizedEntityOptions[0]?.id ?? ''\n return raw ?? ''\n })()\n const resolvedDeal = typeof (initialValues as Record<string, unknown> | undefined)?.dealId === 'string'\n ? (initialValues as Record<string, unknown>).dealId as string\n : ''\n\n return {\n entityId: resolvedEntity,\n dealId: resolvedDeal,\n activityType: initialValues?.activityType ?? '',\n subject: initialValues?.subject ?? '',\n body: initialValues?.body ?? '',\n occurredAt,\n ...Object.fromEntries(\n Object.entries(initialValues ?? {})\n .filter(([key]) => {\n if (!key.startsWith('cf_')) return false\n const trimmed = key.slice(3)\n return trimmed !== 'entityId' && trimmed !== 'dealId'\n })\n .map(([key, value]) => [key, value]),\n ),\n }\n }, [defaultEntityId, initialValues, normalizedEntityOptions])\n\n return (\n <CrudForm<Record<string, unknown>>\n embedded\n fields={baseFields}\n groups={groups}\n initialValues={embeddedInitialValues}\n onSubmit={handleSubmit}\n submitLabel={submitLabel ?? (mode === 'edit'\n ? translate('update', 'Update activity (\u2318/Ctrl + Enter)')\n : translate('save', 'Save activity (\u2318/Ctrl + Enter)'))}\n extraActions={(\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onCancel}\n disabled={pending || isSubmitting}\n >\n {cancelLabel ?? translate('cancel', 'Cancel')}\n </Button>\n )}\n entityIds={customFieldEntityIds}\n />\n )\n}\n\ntype ActivityDialogProps = {\n open: boolean\n mode: 'create' | 'edit'\n onOpenChange: (next: boolean) => void\n initialValues?: Partial<ActivityFormBaseValues & Record<string, unknown>>\n onSubmit: (payload: ActivityFormSubmitPayload) => Promise<void>\n isSubmitting?: boolean\n activityTypeLabels: DictionarySelectLabels\n loadActivityOptions: () => Promise<DictionaryOption[]>\n createActivityOption?: (input: { value: string; label?: string; color?: string | null; icon?: string | null }) => Promise<DictionaryOption>\n titles?: {\n create?: string\n edit?: string\n }\n submitLabels?: {\n create?: string\n edit?: string\n }\n cancelLabel?: string\n dealOptions?: Array<{ id: string; label: string }>\n entityOptions?: Array<{ id: string; label: string }>\n defaultEntityId?: string | null\n manageHref?: string\n customFieldEntityIds?: string[]\n labelPrefix?: string\n appearanceLabels?: AppearanceSelectorLabels\n}\n\nfunction ActivityDialog({\n open,\n mode,\n onOpenChange,\n initialValues,\n onSubmit,\n isSubmitting,\n activityTypeLabels,\n loadActivityOptions,\n createActivityOption,\n titles,\n submitLabels,\n cancelLabel,\n dealOptions,\n entityOptions,\n defaultEntityId,\n manageHref,\n customFieldEntityIds,\n labelPrefix = 'customers.people.detail.activities',\n appearanceLabels,\n}: ActivityDialogProps) {\n const tHook = useT()\n const t = React.useMemo<Translator>(() => createTranslatorWithFallback(tHook), [tHook])\n const translate = React.useCallback(\n (suffix: string, fallback?: string, params?: Record<string, string | number>) =>\n t(`${labelPrefix}.${suffix}`, fallback ?? '', params),\n [labelPrefix, t],\n )\n\n const dialogTitle =\n mode === 'edit'\n ? titles?.edit ?? translate('editTitle', 'Edit activity')\n : titles?.create ?? translate('addTitle', 'Add activity')\n\n const resolvedSubmitLabel =\n mode === 'edit'\n ? submitLabels?.edit ?? translate('update', 'Update activity (\u2318/Ctrl + Enter)')\n : submitLabels?.create ?? translate('save', 'Save activity (\u2318/Ctrl + Enter)')\n\n const resolvedCancelLabel = cancelLabel ?? translate('cancel', 'Cancel')\n\n const handleCancel = React.useCallback(() => {\n onOpenChange(false)\n }, [onOpenChange])\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-3xl\">\n <DialogHeader>\n <DialogTitle>{dialogTitle}</DialogTitle>\n </DialogHeader>\n <ActivityForm\n mode={mode}\n initialValues={initialValues}\n onSubmit={onSubmit}\n onCancel={handleCancel}\n submitLabel={resolvedSubmitLabel}\n cancelLabel={resolvedCancelLabel}\n isSubmitting={isSubmitting}\n activityTypeLabels={activityTypeLabels}\n loadActivityOptions={loadActivityOptions}\n createActivityOption={createActivityOption}\n dealOptions={dealOptions}\n entityOptions={entityOptions}\n defaultEntityId={defaultEntityId}\n manageHref={manageHref}\n customFieldEntityIds={customFieldEntityIds}\n labelPrefix={labelPrefix}\n appearanceLabels={appearanceLabels}\n />\n </DialogContent>\n </Dialog>\n )\n}\n\nexport type ActivitiesSectionProps<C = unknown> = {\n entityId: string | null\n dealId?: string | null\n addActionLabel: string\n emptyState: TabEmptyStateConfig\n onActionChange?: (action: SectionAction | null) => void\n onLoadingChange?: (isLoading: boolean) => void\n dealOptions?: Array<{ id: string; label: string }>\n entityOptions?: Array<{ id: string; label: string }>\n defaultEntityId?: string | null\n dataAdapter: ActivitiesDataAdapter<C>\n dataContext?: C\n activityTypeLabels: DictionarySelectLabels\n loadActivityOptions: () => Promise<DictionaryOption[]>\n createActivityOption?: (input: { value: string; label?: string; color?: string | null; icon?: string | null }) => Promise<DictionaryOption>\n resolveActivityPresentation?: (activity: ActivitySummary) => ActivityTypePresentation\n renderCustomFields?: (activity: ActivitySummary) => React.ReactNode\n customFieldEntityIds?: string[]\n labelPrefix?: string\n renderIcon?: (icon: string, className?: string) => React.ReactNode\n renderColor?: (color: string, className?: string) => React.ReactNode\n appearanceLabels?: AppearanceSelectorLabels\n dealLinkHref?: (dealId: string) => string\n manageHref?: string\n}\n\nfunction ActivitiesSectionImpl<C = unknown>({\n entityId,\n dealId,\n addActionLabel,\n emptyState,\n onActionChange,\n onLoadingChange,\n dealOptions,\n entityOptions,\n defaultEntityId,\n dataAdapter,\n dataContext,\n activityTypeLabels,\n loadActivityOptions,\n createActivityOption,\n resolveActivityPresentation,\n renderCustomFields,\n customFieldEntityIds,\n labelPrefix = 'customers.people.detail.activities',\n renderIcon,\n renderColor,\n appearanceLabels,\n dealLinkHref,\n manageHref,\n}: ActivitiesSectionProps<C>) {\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const tHook = useT()\n const baseTranslator = React.useMemo<Translator>(() => createTranslatorWithFallback(tHook), [tHook])\n const translate = React.useCallback(\n (suffix: string, fallback?: string, params?: Record<string, string | number>) =>\n baseTranslator(`${labelPrefix}.${suffix}`, fallback ?? '', params),\n [baseTranslator, labelPrefix],\n )\n const resolvedDefaultEntityId = React.useMemo(() => {\n const primary = typeof entityId === 'string' ? entityId.trim() : ''\n if (primary.length) return primary\n const fallback = typeof defaultEntityId === 'string' ? defaultEntityId.trim() : ''\n if (fallback.length) return fallback\n if (Array.isArray(entityOptions)) {\n for (const option of entityOptions) {\n if (!option || typeof option !== 'object') continue\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (id.length) return id\n }\n }\n return ''\n }, [defaultEntityId, entityId, entityOptions])\n\n const resolveEntityForSubmission = React.useCallback(\n (input?: string | null) => {\n const candidate = typeof input === 'string' ? input.trim() : ''\n if (candidate.length) return candidate\n return resolvedDefaultEntityId.length ? resolvedDefaultEntityId : null\n },\n [resolvedDefaultEntityId],\n )\n\n const [activities, setActivities] = React.useState<ActivitySummary[]>([])\n const [isLoading, setIsLoading] = React.useState<boolean>(() => {\n const entity = typeof entityId === 'string' ? entityId.trim() : ''\n const deal = typeof dealId === 'string' ? dealId.trim() : ''\n return Boolean(entity || deal || resolvedDefaultEntityId)\n })\n const [loadError, setLoadError] = React.useState<string | null>(null)\n const [pendingAction, setPendingAction] = React.useState<PendingAction | null>(null)\n const [dialogOpen, setDialogOpen] = React.useState(false)\n const [dialogMode, setDialogMode] = React.useState<'create' | 'edit'>('create')\n const [editingActivityId, setEditingActivityId] = React.useState<string | null>(null)\n const [initialValues, setInitialValues] = React.useState<Partial<ActivityFormBaseValues & Record<string, unknown>> | undefined>(undefined)\n const [visibleCount, setVisibleCount] = React.useState(0)\n const pendingCounterRef = React.useRef(0)\n const onLoadingChangeRef = React.useRef(onLoadingChange)\n React.useEffect(() => { onLoadingChangeRef.current = onLoadingChange })\n\n const t = translate\n\n const pushLoading = React.useCallback(() => {\n pendingCounterRef.current += 1\n if (pendingCounterRef.current === 1) {\n onLoadingChangeRef.current?.(true)\n }\n }, [])\n\n const popLoading = React.useCallback(() => {\n pendingCounterRef.current = Math.max(0, pendingCounterRef.current - 1)\n if (pendingCounterRef.current === 0) {\n onLoadingChangeRef.current?.(false)\n }\n }, [])\n\n const updateVisibleCount = React.useCallback((length: number) => {\n if (!length) {\n setVisibleCount(0)\n return\n }\n const baseline = Math.min(5, length)\n setVisibleCount((prev) => {\n if (prev >= length) {\n return Math.min(prev, length)\n }\n return Math.min(Math.max(prev, baseline), length)\n })\n }, [])\n\n const loadActivities = React.useCallback(async () => {\n const queryEntityId = typeof entityId === 'string' ? entityId.trim() : ''\n const queryDealId = typeof dealId === 'string' ? dealId.trim() : ''\n if (!queryEntityId && !queryDealId) {\n setActivities([])\n setLoadError(null)\n updateVisibleCount(0)\n return\n }\n pushLoading()\n setIsLoading(true)\n try {\n const items = await dataAdapter.list({\n entityId: queryEntityId || null,\n dealId: queryDealId || null,\n context: dataContext,\n })\n setActivities(items)\n setLoadError(null)\n updateVisibleCount(items.length)\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : t('loadError', 'Failed to load activities.')\n setLoadError(message)\n } finally {\n setIsLoading(false)\n popLoading()\n }\n }, [dataAdapter, dataContext, dealId, entityId, popLoading, pushLoading, t, updateVisibleCount])\n\n React.useEffect(() => {\n updateVisibleCount(activities.length)\n }, [activities.length, updateVisibleCount])\n\n React.useEffect(() => {\n const queryEntityId = typeof entityId === 'string' ? entityId.trim() : ''\n const queryDealId = typeof dealId === 'string' ? dealId.trim() : ''\n if (!queryEntityId && !queryDealId) {\n setActivities([])\n setLoadError(null)\n setIsLoading(false)\n pendingCounterRef.current = 0\n onLoadingChangeRef.current?.(false)\n updateVisibleCount(0)\n return\n }\n loadActivities().catch(() => {})\n }, [dealId, entityId, loadActivities, updateVisibleCount])\n\n const openCreateDialog = React.useCallback(() => {\n setDialogMode('create')\n setEditingActivityId(null)\n setInitialValues(undefined)\n setDialogOpen(true)\n }, [])\n\n const openEditDialog = React.useCallback((activity: ActivitySummary) => {\n setDialogMode('edit')\n setEditingActivityId(activity.id)\n const baseValues: Partial<ActivityFormBaseValues & Record<string, unknown>> = {\n activityType: activity.activityType,\n subject: activity.subject ?? '',\n body: activity.body ?? '',\n occurredAt: activity.occurredAt ?? activity.createdAt ?? null,\n dealId: activity.dealId ?? '',\n entityId: activity.entityId ?? '',\n }\n const customEntries = Array.isArray(activity.customFields) ? activity.customFields : []\n customEntries.forEach((entry) => {\n if (entry.key === 'entityId' || entry.key === 'dealId') return\n baseValues[`cf_${entry.key}`] = entry.value ?? null\n })\n setInitialValues(baseValues)\n setDialogOpen(true)\n }, [])\n\n const closeDialog = React.useCallback(() => {\n setDialogOpen(false)\n setDialogMode('create')\n setEditingActivityId(null)\n setInitialValues(undefined)\n }, [])\n\n const handleDialogOpenChange = React.useCallback(\n (next: boolean) => {\n if (!next) {\n closeDialog()\n } else {\n setDialogOpen(true)\n }\n },\n [closeDialog],\n )\n\n const handleCreate = React.useCallback(\n async ({ base, custom, entityId: formEntityId }: ActivityFormSubmitPayload) => {\n const submissionEntityId = resolveEntityForSubmission(formEntityId)\n if (!submissionEntityId) {\n const message = t('entityMissing', 'Select a related record before saving.')\n flash(message, 'error')\n throw new Error(message)\n }\n setPendingAction({ kind: 'create' })\n pushLoading()\n try {\n const payload: ActivityCreatePayload = {\n entityId: submissionEntityId,\n activityType: base.activityType,\n subject: base.subject ?? undefined,\n body: base.body ?? undefined,\n occurredAt: base.occurredAt ?? undefined,\n dealId: base.dealId ?? undefined,\n customFields: Object.keys(custom).length ? custom : undefined,\n }\n await dataAdapter.create({ ...payload, context: dataContext })\n await loadActivities()\n flash(t('success', 'Activity saved'), 'success')\n } finally {\n setPendingAction(null)\n popLoading()\n }\n },\n [dataAdapter, dataContext, loadActivities, popLoading, pushLoading, resolveEntityForSubmission, t],\n )\n\n const handleUpdate = React.useCallback(\n async (activityId: string, { base, custom, entityId: formEntityId }: ActivityFormSubmitPayload) => {\n const submissionEntityId = resolveEntityForSubmission(formEntityId)\n if (!submissionEntityId) {\n const message = t('entityMissing', 'Select a related record before saving.')\n flash(message, 'error')\n throw new Error(message)\n }\n setPendingAction({ kind: 'update', id: activityId })\n pushLoading()\n try {\n const patch: ActivityUpdatePayload = {\n entityId: submissionEntityId,\n activityType: base.activityType,\n subject: base.subject ?? undefined,\n body: base.body ?? undefined,\n occurredAt: base.occurredAt ?? undefined,\n dealId: base.dealId ?? undefined,\n customFields: Object.keys(custom).length ? custom : undefined,\n }\n await dataAdapter.update({ id: activityId, patch, context: dataContext })\n await loadActivities()\n flash(t('updateSuccess', 'Activity updated.'), 'success')\n } finally {\n setPendingAction(null)\n popLoading()\n }\n },\n [dataAdapter, dataContext, loadActivities, popLoading, pushLoading, resolveEntityForSubmission, t],\n )\n\n const handleDelete = React.useCallback(\n async (activity: ActivitySummary) => {\n if (!activity.id) return\n const confirmed = await confirm({\n title: t('deleteConfirm', 'Delete this activity? You can restore it using version history.'),\n variant: 'destructive',\n })\n if (!confirmed) return\n setPendingAction({ kind: 'delete', id: activity.id })\n try {\n await dataAdapter.delete({ id: activity.id, context: dataContext })\n setActivities((prev) => prev.filter((existing) => existing.id !== activity.id))\n flash(t('deleteSuccess', 'Activity deleted.'), 'success')\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : t('deleteError', 'Failed to delete activity.')\n flash(message, 'error')\n } finally {\n setPendingAction(null)\n }\n },\n [confirm, dataAdapter, dataContext, t],\n )\n\n const handleDialogSubmit = React.useCallback(\n async (payload: ActivityFormSubmitPayload) => {\n try {\n if (dialogMode === 'edit' && editingActivityId) {\n await handleUpdate(editingActivityId, payload)\n } else {\n await handleCreate(payload)\n }\n closeDialog()\n } catch (err) {\n const message =\n err instanceof Error ? err.message : t('error', 'Failed to save activity')\n flash(message, 'error')\n }\n },\n [closeDialog, dialogMode, editingActivityId, handleCreate, handleUpdate, t],\n )\n\n React.useEffect(() => {\n if (!onActionChange) return\n if (activities.length === 0) {\n onActionChange(null)\n return () => {\n onActionChange(null)\n }\n }\n const disabled = resolveEntityForSubmission(null) === null || pendingAction !== null || isLoading\n const action: SectionAction = {\n label: (\n <span className=\"inline-flex items-center gap-1.5\">\n <Plus className=\"h-4 w-4\" />\n {addActionLabel}\n </span>\n ),\n onClick: () => {\n if (!disabled) openCreateDialog()\n },\n disabled,\n }\n onActionChange(action)\n return () => {\n onActionChange(null)\n }\n }, [\n activities.length,\n addActionLabel,\n isLoading,\n onActionChange,\n openCreateDialog,\n pendingAction,\n resolveEntityForSubmission,\n ])\n\n const isFormPending =\n pendingAction?.kind === 'create' ||\n (pendingAction?.kind === 'update' && pendingAction.id === editingActivityId)\n const visibleActivities = React.useMemo(\n () => activities.slice(0, visibleCount),\n [activities, visibleCount],\n )\n const hasMoreActivities = visibleCount < activities.length\n const loadMoreLabel = t('loadMore', 'Load more activities')\n\n const handleLoadMore = React.useCallback(() => {\n setVisibleCount((prev) => {\n if (prev >= activities.length) return prev\n return Math.min(prev + 5, activities.length)\n })\n }, [activities.length])\n\n const resolvePresentation = React.useCallback(\n (activity: ActivitySummary): ActivityTypePresentation => {\n if (resolveActivityPresentation) return resolveActivityPresentation(activity)\n return {\n label: activity.activityType,\n icon: activity.appearanceIcon ?? null,\n color: activity.appearanceColor ?? null,\n }\n },\n [resolveActivityPresentation],\n )\n\n const resolveDealHref = React.useCallback(\n (id: string) => (dealLinkHref ? dealLinkHref(id) : `/backend/customers/deals/${encodeURIComponent(id)}`),\n [dealLinkHref],\n )\n\n return (\n <div className=\"mt-3 space-y-4\">\n {loadError ? (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-sm text-destructive\">\n {loadError}\n </div>\n ) : null}\n <div className=\"space-y-4\">\n {isLoading && activities.length === 0 ? (\n <LoadingMessage\n label={t('loading', 'Loading activities\u2026')}\n className=\"border-0 bg-transparent p-0 py-8 justify-center\"\n />\n ) : (\n <>\n {!isLoading && activities.length === 0 && !dialogOpen ? (\n <TabEmptyState\n title={emptyState.title}\n action={{\n label: emptyState.actionLabel,\n onClick: openCreateDialog,\n disabled: resolveEntityForSubmission(null) === null || pendingAction !== null,\n }}\n />\n ) : null}\n {visibleActivities.length > 0\n ? visibleActivities.map((activity) => {\n const presentation = resolvePresentation(activity)\n const timestampValue = activity.occurredAt ?? activity.createdAt ?? null\n const occurredLabel =\n formatDateTime(timestampValue) ?? t('noDate', 'No date provided')\n const authorLabel = activity.authorName ?? activity.authorEmail ?? null\n const loggedByText = authorLabel\n ? (() => {\n const translated = t('loggedBy', `Logged by ${authorLabel}`, { user: authorLabel })\n if (\n !translated ||\n translated.includes('{{') ||\n translated.includes('{user')\n ) {\n return `Logged by ${authorLabel}`\n }\n return translated\n })()\n : null\n const isUpdatePending = pendingAction?.kind === 'update' && pendingAction.id === activity.id\n const isDeletePending = pendingAction?.kind === 'delete' && pendingAction.id === activity.id\n\n return (\n <div\n key={activity.id}\n className=\"group space-y-3 rounded-lg border bg-card p-4 transition hover:border-border/70 cursor-pointer\"\n role=\"button\"\n tabIndex={0}\n onClick={() => openEditDialog(activity)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n openEditDialog(activity)\n }\n }}\n >\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"space-y-1\">\n <TimelineItemHeader\n title={presentation.label}\n timestamp={timestampValue}\n fallbackTimestampLabel={occurredLabel}\n icon={presentation.icon}\n color={presentation.color}\n renderIcon={renderIcon}\n renderColor={renderColor}\n />\n {activity.dealId ? (\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <ArrowUpRightSquare className=\"h-3.5 w-3.5\" />\n <Link\n href={resolveDealHref(activity.dealId)}\n className=\"font-medium text-foreground hover:underline\"\n onClick={(event) => event.stopPropagation()}\n >\n {activity.dealTitle && activity.dealTitle.length\n ? activity.dealTitle\n : t('linkedDeal', 'Linked deal')}\n </Link>\n </div>\n ) : null}\n </div>\n <div className=\"flex items-center gap-1 opacity-100 md:opacity-0 transition-opacity md:group-hover:opacity-100 focus-within:opacity-100\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={(event) => {\n event.stopPropagation()\n openEditDialog(activity)\n }}\n disabled={pendingAction !== null}\n >\n {isUpdatePending ? (\n <span className=\"relative flex h-4 w-4 items-center justify-center\">\n <span className=\"absolute h-4 w-4 animate-spin rounded-full border border-primary border-t-transparent\" />\n </span>\n ) : (\n <Pencil className=\"h-4 w-4\" />\n )}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={(event) => {\n event.stopPropagation()\n handleDelete(activity).catch(() => {})\n }}\n disabled={pendingAction !== null}\n >\n {isDeletePending ? (\n <span className=\"relative flex h-4 w-4 items-center justify-center text-destructive\">\n <span className=\"absolute h-4 w-4 animate-spin rounded-full border border-destructive border-t-transparent\" />\n </span>\n ) : (\n <Trash2 className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </div>\n {activity.subject ? <p className=\"text-sm font-medium\">{activity.subject}</p> : null}\n {activity.body ? (\n <p className=\"text-sm whitespace-pre-wrap text-muted-foreground\">{activity.body}</p>\n ) : null}\n {renderCustomFields ? renderCustomFields(activity) : null}\n {loggedByText ? (\n <p className=\"text-xs text-muted-foreground\">{loggedByText}</p>\n ) : null}\n </div>\n )\n })\n : null}\n {hasMoreActivities ? (\n <div className=\"flex justify-center\">\n <Button variant=\"outline\" size=\"sm\" onClick={handleLoadMore} disabled={pendingAction !== null}>\n {loadMoreLabel}\n </Button>\n </div>\n ) : null}\n </>\n )}\n </div>\n\n <ActivityDialog\n open={dialogOpen}\n mode={dialogMode}\n onOpenChange={handleDialogOpenChange}\n initialValues={initialValues}\n onSubmit={async (payload) => {\n await handleDialogSubmit(payload)\n }}\n isSubmitting={Boolean(isFormPending)}\n activityTypeLabels={activityTypeLabels}\n loadActivityOptions={loadActivityOptions}\n createActivityOption={createActivityOption}\n dealOptions={dealOptions}\n entityOptions={entityOptions}\n defaultEntityId={resolvedDefaultEntityId || undefined}\n manageHref={manageHref}\n customFieldEntityIds={customFieldEntityIds}\n labelPrefix={labelPrefix}\n appearanceLabels={appearanceLabels}\n />\n {ConfirmDialogElement}\n </div>\n )\n}\n\nexport function ActivitiesSection<C = unknown>(props: ActivitiesSectionProps<C>) {\n const handle = ComponentReplacementHandles.section('ui.detail', 'ActivitiesSection')\n const Resolved = useRegisteredComponent<ActivitiesSectionProps<C>>(\n handle,\n ActivitiesSectionImpl as React.ComponentType<ActivitiesSectionProps<C>>,\n )\n\n return (\n <div data-component-handle={handle}>\n <Resolved {...props} />\n </div>\n )\n}\n\nexport default ActivitiesSection\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -6,6 +6,13 @@ import { usePathname, useSearchParams } from "next/navigation";
|
|
|
6
6
|
import { Plus, Settings } from "lucide-react";
|
|
7
7
|
import { Button } from "../../primitives/button.js";
|
|
8
8
|
import { Input } from "@open-mercato/ui/primitives/input";
|
|
9
|
+
import {
|
|
10
|
+
Select,
|
|
11
|
+
SelectContent,
|
|
12
|
+
SelectItem,
|
|
13
|
+
SelectTrigger,
|
|
14
|
+
SelectValue
|
|
15
|
+
} from "@open-mercato/ui/primitives/select";
|
|
9
16
|
import {
|
|
10
17
|
Dialog,
|
|
11
18
|
DialogContent,
|
|
@@ -164,16 +171,26 @@ function AddressEditor({
|
|
|
164
171
|
),
|
|
165
172
|
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
166
173
|
/* @__PURE__ */ jsxs(
|
|
167
|
-
|
|
174
|
+
Select,
|
|
168
175
|
{
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
onChange: (evt) => update("purpose", evt.target.value),
|
|
176
|
+
value: current.purpose || void 0,
|
|
177
|
+
onValueChange: (next) => update("purpose", next ?? ""),
|
|
172
178
|
disabled,
|
|
173
|
-
"aria-invalid": errors.purpose ? "true" : void 0,
|
|
174
179
|
children: [
|
|
175
|
-
/* @__PURE__ */ jsx(
|
|
176
|
-
|
|
180
|
+
/* @__PURE__ */ jsx(
|
|
181
|
+
SelectTrigger,
|
|
182
|
+
{
|
|
183
|
+
className: errors.purpose ? "border-destructive" : void 0,
|
|
184
|
+
"aria-invalid": errors.purpose ? "true" : void 0,
|
|
185
|
+
children: /* @__PURE__ */ jsx(
|
|
186
|
+
SelectValue,
|
|
187
|
+
{
|
|
188
|
+
placeholder: addressTypesLoading ? label("types.loading", "Loading\u2026") : label("types.placeholder", "Address type")
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
),
|
|
193
|
+
/* @__PURE__ */ jsx(SelectContent, { children: addressTypes.map((entry) => /* @__PURE__ */ jsx(SelectItem, { value: entry.value, children: entry.label }, entry.value)) })
|
|
177
194
|
]
|
|
178
195
|
}
|
|
179
196
|
),
|