@open-mercato/core 0.9.1-develop.7477.1.64ba865101 → 0.9.1-develop.7497.1.543ea44c40
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/dist/modules/business_rules/data/validators.js +8 -3
- package/dist/modules/business_rules/data/validators.js.map +2 -2
- package/dist/modules/catalog/api/dictionaries/[key]/route.js +35 -7
- package/dist/modules/catalog/api/dictionaries/[key]/route.js.map +2 -2
- package/dist/modules/communication_channels/lib/email-mime.js +1 -2
- package/dist/modules/communication_channels/lib/email-mime.js.map +2 -2
- package/dist/modules/configs/cli.js +8 -2
- package/dist/modules/configs/cli.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/people/route.js +3 -0
- package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/companies/route.js +3 -3
- package/dist/modules/customers/api/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js +3 -0
- package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +3 -0
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/kind-settings/route.js +6 -0
- package/dist/modules/customers/api/dictionaries/kind-settings/route.js.map +2 -2
- package/dist/modules/customers/api/labels/route.js +10 -1
- package/dist/modules/customers/api/labels/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +6 -0
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +3 -0
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/route.js +6 -0
- package/dist/modules/customers/api/people/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/people/route.js +3 -3
- package/dist/modules/customers/api/people/route.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +2 -0
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/components/ActivityTypeEditor.js +11 -5
- package/dist/modules/customers/components/ActivityTypeEditor.js.map +2 -2
- package/dist/modules/customers/components/detail/InlineEditors.js +7 -3
- package/dist/modules/customers/components/detail/InlineEditors.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonHighlights.js +1 -1
- package/dist/modules/customers/components/detail/PersonHighlights.js.map +2 -2
- package/dist/modules/customers/components/detail/PlannedActivitiesSection.js +4 -5
- package/dist/modules/customers/components/detail/PlannedActivitiesSection.js.map +2 -2
- package/dist/modules/data_sync/di.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-schedule-service.js +60 -27
- package/dist/modules/data_sync/lib/sync-schedule-service.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +10 -7
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/messages/lib/constants.js +3 -1
- package/dist/modules/messages/lib/constants.js.map +2 -2
- package/dist/modules/messages/subscribers/message-notification.js +2 -1
- package/dist/modules/messages/subscribers/message-notification.js.map +2 -2
- package/dist/modules/sales/api/documents/factory.js +3 -4
- package/dist/modules/sales/api/documents/factory.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +9 -1
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/business_rules/data/validators.ts +12 -3
- package/src/modules/catalog/api/dictionaries/[key]/route.ts +49 -7
- package/src/modules/communication_channels/lib/email-mime.ts +1 -2
- package/src/modules/configs/cli.ts +10 -1
- package/src/modules/customers/api/companies/[id]/people/route.ts +3 -0
- package/src/modules/customers/api/companies/route.ts +6 -6
- package/src/modules/customers/api/deals/[id]/companies/route.ts +3 -0
- package/src/modules/customers/api/deals/[id]/people/route.ts +3 -0
- package/src/modules/customers/api/dictionaries/kind-settings/route.ts +6 -0
- package/src/modules/customers/api/labels/route.ts +10 -1
- package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +6 -0
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +3 -0
- package/src/modules/customers/api/people/[id]/companies/route.ts +6 -0
- package/src/modules/customers/api/people/route.ts +6 -6
- package/src/modules/customers/commands/deals.ts +2 -0
- package/src/modules/customers/components/ActivityTypeEditor.tsx +11 -5
- package/src/modules/customers/components/detail/InlineEditors.tsx +8 -4
- package/src/modules/customers/components/detail/PersonHighlights.tsx +4 -1
- package/src/modules/customers/components/detail/PlannedActivitiesSection.tsx +4 -5
- package/src/modules/customers/i18n/de.json +2 -0
- package/src/modules/customers/i18n/en.json +2 -0
- package/src/modules/customers/i18n/es.json +2 -0
- package/src/modules/customers/i18n/ko.json +2 -0
- package/src/modules/customers/i18n/pl.json +2 -0
- package/src/modules/data_sync/di.ts +1 -0
- package/src/modules/data_sync/lib/sync-schedule-service.ts +80 -28
- package/src/modules/messages/commands/messages.ts +10 -7
- package/src/modules/messages/lib/constants.ts +6 -0
- package/src/modules/messages/subscribers/message-notification.ts +2 -0
- package/src/modules/sales/api/documents/factory.ts +6 -7
- package/src/modules/sales/commands/payments.ts +10 -2
|
@@ -26,7 +26,7 @@ const logger = createLogger("customers");
|
|
|
26
26
|
const ENTITY_ID = E.customers.customer_interaction;
|
|
27
27
|
const API = "/api/customers/dictionaries/activity-types";
|
|
28
28
|
const defaults = calendarEventTypes[0].behavior;
|
|
29
|
-
function initialValues(item) {
|
|
29
|
+
function initialValues(item, version) {
|
|
30
30
|
const behavior = item?.behavior ?? defaults;
|
|
31
31
|
return {
|
|
32
32
|
value: item?.key ?? "",
|
|
@@ -38,7 +38,7 @@ function initialValues(item) {
|
|
|
38
38
|
selectable: behavior.selectable,
|
|
39
39
|
...behavior.fields,
|
|
40
40
|
customFieldsetIds: [...behavior.customFieldsetIds],
|
|
41
|
-
updatedAt:
|
|
41
|
+
updatedAt: version ?? void 0
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
function ActivityTypeEditor({ title, description }) {
|
|
@@ -48,6 +48,7 @@ function ActivityTypeEditor({ title, description }) {
|
|
|
48
48
|
const [items, setItems] = React.useState([]);
|
|
49
49
|
const [rows, setRows] = React.useState([]);
|
|
50
50
|
const [selected, setSelected] = React.useState(void 0);
|
|
51
|
+
const [selectedVersion, setSelectedVersion] = React.useState(void 0);
|
|
51
52
|
const [fieldsets, setFieldsets] = React.useState([]);
|
|
52
53
|
const [fieldsetsStatus, setFieldsetsStatus] = React.useState("loading");
|
|
53
54
|
const [fieldsetAttempt, setFieldsetAttempt] = React.useState(0);
|
|
@@ -102,6 +103,10 @@ function ActivityTypeEditor({ title, description }) {
|
|
|
102
103
|
};
|
|
103
104
|
}, [selected, fieldsetAttempt]);
|
|
104
105
|
const localRow = (key) => rows.find((row) => row.value.toLowerCase() === key && !row.isInherited);
|
|
106
|
+
const openEditor = (item) => {
|
|
107
|
+
setSelectedVersion(item ? localRow(item.key)?.updatedAt ?? item.updatedAt : void 0);
|
|
108
|
+
setSelected(item);
|
|
109
|
+
};
|
|
105
110
|
const remove = async (item) => {
|
|
106
111
|
const row = localRow(item.key);
|
|
107
112
|
if (!row) return;
|
|
@@ -161,6 +166,7 @@ function ActivityTypeEditor({ title, description }) {
|
|
|
161
166
|
{ id: "behavior", title: t("customers.config.activityTypes.behavior", "Form behavior"), fields: ["baseKind", "selectable", "endTime", "allDay", "recurrence", "location", "people", "priority", "resources"] },
|
|
162
167
|
...fieldsets.length || selected?.behavior.customFieldsetIds.length ? [{ id: "fieldsets", fields: ["customFieldsetIds"] }] : []
|
|
163
168
|
];
|
|
169
|
+
const formInitialValues = React.useMemo(() => initialValues(selected ?? null, selectedVersion), [selected, selectedVersion]);
|
|
164
170
|
const save = async (values) => {
|
|
165
171
|
const key = String(values.value ?? "").trim();
|
|
166
172
|
if (!calendarEventTypeKeySchema.safeParse(key).success) throw createCrudFormError(t("customers.config.activityTypes.invalidKey", "Use a lowercase key with letters, numbers, hyphens, or underscores."), { value: t("customers.config.activityTypes.invalidKey", "Use a lowercase key with letters, numbers, hyphens, or underscores.") });
|
|
@@ -233,10 +239,10 @@ function ActivityTypeEditor({ title, description }) {
|
|
|
233
239
|
title,
|
|
234
240
|
titleHeadingLevel: 2,
|
|
235
241
|
emptyState: t("customers.config.activityTypes.empty", "No activity types available."),
|
|
236
|
-
actions: /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: () =>
|
|
242
|
+
actions: /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: () => openEditor(null), children: t("customers.config.activityTypes.new", "New activity type") }),
|
|
237
243
|
refreshButton: { label: t("customers.config.activityTypes.refresh", "Refresh"), onRefresh: load, isRefreshing: status === "loading" },
|
|
238
244
|
rowActions: (item) => {
|
|
239
|
-
const actions = [{ id: "edit", label: item.adminConfigurable ? t("customers.config.activityTypes.configure", "Configure") : t("customers.config.activityTypes.view", "View"), onSelect: () =>
|
|
245
|
+
const actions = [{ id: "edit", label: item.adminConfigurable ? t("customers.config.activityTypes.configure", "Configure") : t("customers.config.activityTypes.view", "View"), onSelect: () => openEditor(item) }];
|
|
240
246
|
if (localRow(item.key)) actions.push({
|
|
241
247
|
id: "delete",
|
|
242
248
|
label: item.source === "dictionary" ? t("customers.config.activityTypes.delete", "Delete") : t("customers.config.activityTypes.reset", "Reset override"),
|
|
@@ -271,7 +277,7 @@ function ActivityTypeEditor({ title, description }) {
|
|
|
271
277
|
readOnly: selected?.adminConfigurable === false,
|
|
272
278
|
fields,
|
|
273
279
|
groups,
|
|
274
|
-
initialValues:
|
|
280
|
+
initialValues: formInitialValues,
|
|
275
281
|
onSubmit: save,
|
|
276
282
|
submitLabel: t("customers.config.activityTypes.save", "Save"),
|
|
277
283
|
extraActions: /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: () => setSelected(void 0), children: t("customers.config.dictionaries.dialog.cancel", "Cancel") })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/customers/components/ActivityTypeEditor.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { getTelemetryRuntime } from '@open-mercato/shared/lib/telemetry/runtime'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions, type RowActionItem } from '@open-mercato/ui/backend/RowActions'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { apiCallOrThrow, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { calendarEventTypeBehaviorSchema, calendarEventTypeKeySchema, calendarEventTypes } from '../calendar-event-types'\nimport type { ScopedCalendarEventType } from '../lib/calendar/eventTypeResolver'\nimport { getCustomerDictionarySettingsSectionId } from '../lib/dictionaries'\nimport { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\n\nconst logger = createLogger('customers')\nconst ENTITY_ID = E.customers.customer_interaction\nconst API = '/api/customers/dictionaries/activity-types'\n\ntype DictionaryRow = { id: string; value: string; updatedAt: string | null; isInherited: boolean }\ntype Fieldset = { code: string; label: string }\ntype FormValues = Record<string, unknown>\n\nconst defaults = calendarEventTypes[0]!.behavior\n\nfunction initialValues(item: ScopedCalendarEventType | null): FormValues {\n const behavior = item?.behavior ?? defaults\n return {\n value: item?.key ?? '', label: item?.label ?? '', icon: item?.icon ?? '', color: item?.color ?? '',\n order: behavior.order, baseKind: behavior.baseKind, selectable: behavior.selectable,\n ...behavior.fields, customFieldsetIds: [...behavior.customFieldsetIds], updatedAt: item?.updatedAt ?? undefined,\n }\n}\n\nexport function ActivityTypeEditor({ title, description }: { title: string; description: string }) {\n const t = useT()\n const scopeVersion = useOrganizationScopeVersion()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [items, setItems] = React.useState<ScopedCalendarEventType[]>([])\n const [rows, setRows] = React.useState<DictionaryRow[]>([])\n const [selected, setSelected] = React.useState<ScopedCalendarEventType | null | undefined>(undefined)\n const [fieldsets, setFieldsets] = React.useState<Fieldset[]>([])\n const [fieldsetsStatus, setFieldsetsStatus] = React.useState<'loading' | 'ready' | 'error'>('loading')\n const [fieldsetAttempt, setFieldsetAttempt] = React.useState(0)\n const [status, setStatus] = React.useState<'loading' | 'ready' | 'error'>('loading')\n const { runMutation, retryLastMutation } = useGuardedMutation({\n contextId: 'customers-activity-types',\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const load = React.useCallback(async () => {\n setStatus('loading')\n try {\n const [catalog, dictionary] = await Promise.all([\n readApiResultOrThrow<{ items: ScopedCalendarEventType[] }>('/api/customers/activity-types'),\n readApiResultOrThrow<{ items: DictionaryRow[] }>(API),\n ])\n if (!Array.isArray(catalog.items) || !Array.isArray(dictionary.items)) throw new Error('[internal] Invalid activity type response')\n setItems(catalog.items)\n setRows(dictionary.items)\n setStatus('ready')\n } catch (err) {\n logger.error('customers.activity_types.settings.load failed', { err })\n getTelemetryRuntime()?.reportError(err, {\n module: 'customers',\n code: 'customers.activity_type_settings_load_failed',\n })\n setStatus('error')\n }\n }, [])\n React.useEffect(() => { void load() }, [load, scopeVersion])\n\n React.useEffect(() => {\n if (selected === undefined) return\n let active = true\n setFieldsetsStatus('loading')\n void readApiResultOrThrow<{ fieldsetsByEntity?: Record<string, Fieldset[]> }>(\n `/api/entities/definitions?entityId=${encodeURIComponent(ENTITY_ID)}`,\n ).then((result) => {\n if (!active) return\n setFieldsets(result.fieldsetsByEntity?.[ENTITY_ID] ?? [])\n setFieldsetsStatus('ready')\n }).catch((err) => {\n logger.error('customers.activity_types.fieldsets.load failed', { err })\n getTelemetryRuntime()?.reportError(err, {\n module: 'customers',\n code: 'customers.activity_type_fieldsets_load_failed',\n })\n if (active) setFieldsetsStatus('error')\n })\n return () => { active = false }\n }, [selected, fieldsetAttempt])\n\n const localRow = (key: string) => rows.find((row) => row.value.toLowerCase() === key && !row.isInherited)\n const remove = async (item: ScopedCalendarEventType) => {\n const row = localRow(item.key)\n if (!row) return\n const approved = await confirm({\n title: t('customers.config.activityTypes.resetConfirm', 'Remove the local activity type configuration?'),\n variant: 'destructive',\n })\n if (!approved) return\n try {\n await runMutation({\n operation: () => withScopedApiRequestHeaders(buildOptimisticLockHeader(row.updatedAt), () =>\n apiCallOrThrow(`${API}/${encodeURIComponent(row.id)}`, { method: 'DELETE' })),\n context: { formId: 'customers-activity-types', resourceKind: 'customers.dictionary', retryLastMutation },\n mutationPayload: { action: 'delete', id: row.id, kind: 'activity-types' },\n })\n flash(t('customers.config.activityTypes.removed', 'Activity type configuration removed.'), 'success')\n await load()\n } catch (err) {\n logger.error('customers.activity_types.settings.remove failed', { err })\n getTelemetryRuntime()?.reportError(err, {\n module: 'customers',\n code: 'customers.activity_type_settings_remove_failed',\n })\n if (!surfaceRecordConflict(err, t, { onRefresh: () => { void load() } })) {\n flash(t('customers.config.activityTypes.saveFailed', 'Failed to save activity type.'), 'error')\n }\n }\n }\n\n const fields = React.useMemo<CrudField[]>(() => {\n const label = (key: string, fallback: string) => t(`customers.config.activityTypes.fields.${key}`, fallback)\n const options = (values: readonly string[]) => values.map((value) => ({ value, label: t(`customers.config.activityTypes.options.${value}`, value) }))\n const knownFieldsets = fieldsets.map(({ code, label: fieldsetLabel }) => ({ value: code, label: fieldsetLabel }))\n const missing = selected?.behavior.customFieldsetIds.filter((code) => !fieldsets.some((fieldset) => fieldset.code === code)) ?? []\n return [\n { id: 'value', type: 'text', label: label('value', 'Stable key'), required: true, readOnly: !!selected },\n { id: 'label', type: 'text', label: label('label', 'Label'), required: true },\n { id: 'icon', type: 'text', label: label('icon', 'Icon') },\n { id: 'color', type: 'text', label: label('color', 'Color (#RRGGBB)') },\n { id: 'order', type: 'number', label: label('order', 'Display order'), required: true },\n { id: 'baseKind', type: 'select', label: label('baseKind', 'Base behavior'), options: options(['meeting', 'call', 'email', 'note', 'event', 'task']) },\n { id: 'selectable', type: 'checkbox', label: label('selectable', 'Available for new events') },\n ...(['endTime', 'allDay', 'recurrence', 'priority', 'resources'] as const).map((id): CrudField => ({ id, type: 'checkbox', label: label(id, id) })),\n { id: 'location', type: 'select', label: label('location', 'Location field'), options: options(['none', 'location', 'phoneLink']) },\n { id: 'people', type: 'select', label: label('people', 'People field'), options: options(['none', 'attendees', 'participants', 'recipients', 'assignee']) },\n { id: 'customFieldsetIds', type: 'select', multiple: true, label: label('customFieldsetIds', 'Custom-field fieldsets'),\n options: [...knownFieldsets, ...missing.map((code) => ({ value: code, label: `${code} (${t('customers.config.activityTypes.missing', 'missing')})` }))] },\n ]\n }, [fieldsets, selected, t])\n const groups: CrudFormGroup[] = [\n { id: 'appearance', title: t('customers.config.activityTypes.appearance', 'Appearance'), fields: ['value', 'label', 'icon', 'color', 'order'] },\n { id: 'behavior', title: t('customers.config.activityTypes.behavior', 'Form behavior'), fields: ['baseKind', 'selectable', 'endTime', 'allDay', 'recurrence', 'location', 'people', 'priority', 'resources'] },\n ...(fieldsets.length || selected?.behavior.customFieldsetIds.length ? [{ id: 'fieldsets', fields: ['customFieldsetIds'] }] : []),\n ]\n const save = async (values: FormValues) => {\n const key = String(values.value ?? '').trim()\n if (!calendarEventTypeKeySchema.safeParse(key).success) throw createCrudFormError(t('customers.config.activityTypes.invalidKey', 'Use a lowercase key with letters, numbers, hyphens, or underscores.'), { value: t('customers.config.activityTypes.invalidKey', 'Use a lowercase key with letters, numbers, hyphens, or underscores.') })\n if (fieldsetsStatus !== 'ready') throw createCrudFormError(t('customers.config.activityTypes.fieldsetsUnavailable', 'Fieldsets are unavailable. Retry loading before saving.'))\n const behavior = calendarEventTypeBehaviorSchema.safeParse({\n schemaVersion: 1, baseKind: values.baseKind, selectable: values.selectable === true,\n order: Number(values.order), customFieldsetIds: values.customFieldsetIds ?? [],\n fields: { endTime: values.endTime === true, allDay: values.allDay === true, recurrence: values.recurrence === true,\n location: values.location, people: values.people, priority: values.priority === true, resources: values.resources === true },\n })\n if (!behavior.success) throw createCrudFormError(t('customers.config.activityTypes.invalidBehavior', 'Check the form behavior values.'))\n const payload = { value: key, label: String(values.label ?? '').trim(), icon: String(values.icon ?? '').trim() || null,\n color: String(values.color ?? '').trim() || null, behavior: behavior.data }\n const row = selected ? localRow(selected.key) : undefined\n await apiCallOrThrow(row ? `${API}/${encodeURIComponent(row.id)}` : API, {\n method: row ? 'PATCH' : 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify(row ? { label: payload.label, icon: payload.icon, color: payload.color, behavior: payload.behavior } : payload),\n })\n setSelected(undefined)\n flash(t('customers.config.activityTypes.saved', 'Activity type saved.'), 'success')\n await load()\n }\n\n const columns = React.useMemo<ColumnDef<ScopedCalendarEventType>[]>(() => [\n { accessorKey: 'label', header: t('customers.config.activityTypes.columns.type', 'Activity type'), cell: ({ row }) => (\n <div className=\"flex items-center gap-2\">{row.original.color ? renderDictionaryColor(row.original.color, 'size-4 rounded-full border border-border') : null}\n {row.original.icon ? renderDictionaryIcon(row.original.icon, 'size-4') : null}<span>{row.original.labelKey\n ? t(row.original.labelKey, row.original.label)\n : row.original.label}</span></div>) },\n { accessorKey: 'key', header: t('customers.config.activityTypes.columns.key', 'Stable key') },\n { id: 'source', header: t('customers.config.activityTypes.columns.source', 'Source'), cell: ({ row }) => row.original.isLocalOverride\n ? t('customers.config.activityTypes.local', 'Local override') : row.original.isInherited\n ? t('customers.config.activityTypes.inherited', 'Inherited') : row.original.source },\n { id: 'behavior', header: t('customers.config.activityTypes.columns.behavior', 'Behavior'), cell: ({ row }) =>\n t(`customers.config.activityTypes.options.${row.original.behavior.baseKind}`, row.original.behavior.baseKind) },\n { id: 'active', header: t('customers.config.activityTypes.columns.active', 'Selectable'), cell: ({ row }) => row.original.selectable\n ? t('customers.config.activityTypes.yes', 'Yes') : t('customers.config.activityTypes.no', 'No') },\n { id: 'fields', header: t('customers.config.activityTypes.columns.fields', 'Fields'), cell: ({ row }) =>\n Object.values(row.original.behavior.fields).filter((value) => value !== false && value !== 'none').length },\n { id: 'fieldsets', header: t('customers.config.activityTypes.columns.fieldsets', 'Fieldsets'), cell: ({ row }) => row.original.behavior.customFieldsetIds.length },\n { id: 'order', header: t('customers.config.activityTypes.columns.order', 'Order'), cell: ({ row }) => row.original.behavior.order },\n ], [t])\n\n return <section id={getCustomerDictionarySettingsSectionId('activity-types')} className=\"scroll-mt-24 rounded border bg-card text-card-foreground shadow-sm\">\n <div className=\"space-y-1 border-b px-6 py-4\"><h2 className=\"text-lg font-medium\">{title}</h2><p className=\"text-sm text-muted-foreground\">{description}</p></div>\n <div className=\"px-2 py-4 sm:px-4\">\n {status === 'error' ? <div className=\"space-y-3\"><ErrorMessage label={t('customers.config.activityTypes.loadFailed', 'Failed to load activity types.')} /><Button type=\"button\" onClick={() => { void load() }}>{t('customers.config.activityTypes.retry', 'Retry')}</Button></div> :\n <DataTable<ScopedCalendarEventType> embedded columns={columns} data={items} isLoading={status === 'loading'}\n title={title} titleHeadingLevel={2} emptyState={t('customers.config.activityTypes.empty', 'No activity types available.')}\n actions={<Button type=\"button\" size=\"sm\" onClick={() => setSelected(null)}>{t('customers.config.activityTypes.new', 'New activity type')}</Button>}\n refreshButton={{ label: t('customers.config.activityTypes.refresh', 'Refresh'), onRefresh: load, isRefreshing: status === 'loading' }}\n rowActions={(item) => {\n const actions: RowActionItem[] = [{ id: 'edit', label: item.adminConfigurable\n ? t('customers.config.activityTypes.configure', 'Configure') : t('customers.config.activityTypes.view', 'View'), onSelect: () => setSelected(item) }]\n if (localRow(item.key)) actions.push({ id: 'delete', label: item.source === 'dictionary'\n ? t('customers.config.activityTypes.delete', 'Delete') : t('customers.config.activityTypes.reset', 'Reset override'),\n destructive: true, onSelect: () => { void remove(item) } })\n return <RowActions items={actions} />\n }} />}\n </div>\n <Dialog open={selected !== undefined} onOpenChange={(open) => { if (!open) setSelected(undefined) }}>\n <DialogContent className=\"max-h-screen overflow-y-auto sm:max-w-2xl\">\n <DialogHeader><DialogTitle>{selected\n ? t('customers.config.activityTypes.configure', 'Configure') : t('customers.config.activityTypes.new', 'New activity type')}</DialogTitle></DialogHeader>\n {selected?.isInherited ? <p className=\"text-sm text-muted-foreground\">{t('customers.config.activityTypes.inheritedHint', 'Saving creates a local override for this organization.')}</p> : null}\n {selected?.inactiveDictionaryOverride ? <p className=\"text-sm text-muted-foreground\">{t('customers.config.activityTypes.inactiveHint', 'A module currently prevents this override from taking effect.')}</p> : null}\n {selected?.missingCustomFieldsetIds.length ? <p className=\"text-sm text-muted-foreground\">{t('customers.config.activityTypes.missingHint', 'Some configured fieldsets no longer exist.')}: {selected.missingCustomFieldsetIds.join(', ')}</p> : null}\n {fieldsetsStatus === 'loading' ? <LoadingMessage label={t('customers.config.activityTypes.loadingFieldsets', 'Loading fieldsets\u2026')} /> : null}\n {fieldsetsStatus === 'error' ? <ErrorMessage label={t('customers.config.activityTypes.fieldsetsUnavailable', 'Fieldsets are unavailable. Retry loading before saving.')} /> : null}\n {fieldsetsStatus === 'error' ? <Button type=\"button\" onClick={() => setFieldsetAttempt((attempt) => attempt + 1)}>{t('customers.config.activityTypes.retry', 'Retry')}</Button> : null}\n {fieldsetsStatus === 'ready' && fieldsets.length === 0 ? <p className=\"text-sm text-muted-foreground\">{t('customers.config.activityTypes.noFieldsets', 'No custom-field fieldsets are defined yet.')}</p> : null}\n {selected !== undefined && fieldsetsStatus === 'ready' ? <CrudForm<FormValues> key={selected?.key ?? 'new'} embedded\n readOnly={selected?.adminConfigurable === false} fields={fields} groups={groups}\n initialValues={initialValues(selected)} onSubmit={save} submitLabel={t('customers.config.activityTypes.save', 'Save')}\n extraActions={<Button type=\"button\" variant=\"outline\" onClick={() => setSelected(undefined)}>{t('customers.config.dictionaries.dialog.cancel', 'Cancel')}</Button>} /> : null}\n </DialogContent>\n </Dialog>\n {ConfirmDialogElement}\n </section>\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { getTelemetryRuntime } from '@open-mercato/shared/lib/telemetry/runtime'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions, type RowActionItem } from '@open-mercato/ui/backend/RowActions'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { apiCallOrThrow, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { calendarEventTypeBehaviorSchema, calendarEventTypeKeySchema, calendarEventTypes } from '../calendar-event-types'\nimport type { ScopedCalendarEventType } from '../lib/calendar/eventTypeResolver'\nimport { getCustomerDictionarySettingsSectionId } from '../lib/dictionaries'\nimport { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\n\nconst logger = createLogger('customers')\nconst ENTITY_ID = E.customers.customer_interaction\nconst API = '/api/customers/dictionaries/activity-types'\n\ntype DictionaryRow = { id: string; value: string; updatedAt: string | null; isInherited: boolean }\ntype Fieldset = { code: string; label: string }\ntype FormValues = Record<string, unknown>\n\nconst defaults = calendarEventTypes[0]!.behavior\n\nfunction initialValues(item: ScopedCalendarEventType | null, version: string | null | undefined): FormValues {\n const behavior = item?.behavior ?? defaults\n return {\n value: item?.key ?? '', label: item?.label ?? '', icon: item?.icon ?? '', color: item?.color ?? '',\n order: behavior.order, baseKind: behavior.baseKind, selectable: behavior.selectable,\n ...behavior.fields, customFieldsetIds: [...behavior.customFieldsetIds], updatedAt: version ?? undefined,\n }\n}\n\nexport function ActivityTypeEditor({ title, description }: { title: string; description: string }) {\n const t = useT()\n const scopeVersion = useOrganizationScopeVersion()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [items, setItems] = React.useState<ScopedCalendarEventType[]>([])\n const [rows, setRows] = React.useState<DictionaryRow[]>([])\n const [selected, setSelected] = React.useState<ScopedCalendarEventType | null | undefined>(undefined)\n const [selectedVersion, setSelectedVersion] = React.useState<string | null | undefined>(undefined)\n const [fieldsets, setFieldsets] = React.useState<Fieldset[]>([])\n const [fieldsetsStatus, setFieldsetsStatus] = React.useState<'loading' | 'ready' | 'error'>('loading')\n const [fieldsetAttempt, setFieldsetAttempt] = React.useState(0)\n const [status, setStatus] = React.useState<'loading' | 'ready' | 'error'>('loading')\n const { runMutation, retryLastMutation } = useGuardedMutation({\n contextId: 'customers-activity-types',\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const load = React.useCallback(async () => {\n setStatus('loading')\n try {\n const [catalog, dictionary] = await Promise.all([\n readApiResultOrThrow<{ items: ScopedCalendarEventType[] }>('/api/customers/activity-types'),\n readApiResultOrThrow<{ items: DictionaryRow[] }>(API),\n ])\n if (!Array.isArray(catalog.items) || !Array.isArray(dictionary.items)) throw new Error('[internal] Invalid activity type response')\n setItems(catalog.items)\n setRows(dictionary.items)\n setStatus('ready')\n } catch (err) {\n logger.error('customers.activity_types.settings.load failed', { err })\n getTelemetryRuntime()?.reportError(err, {\n module: 'customers',\n code: 'customers.activity_type_settings_load_failed',\n })\n setStatus('error')\n }\n }, [])\n React.useEffect(() => { void load() }, [load, scopeVersion])\n\n React.useEffect(() => {\n if (selected === undefined) return\n let active = true\n setFieldsetsStatus('loading')\n void readApiResultOrThrow<{ fieldsetsByEntity?: Record<string, Fieldset[]> }>(\n `/api/entities/definitions?entityId=${encodeURIComponent(ENTITY_ID)}`,\n ).then((result) => {\n if (!active) return\n setFieldsets(result.fieldsetsByEntity?.[ENTITY_ID] ?? [])\n setFieldsetsStatus('ready')\n }).catch((err) => {\n logger.error('customers.activity_types.fieldsets.load failed', { err })\n getTelemetryRuntime()?.reportError(err, {\n module: 'customers',\n code: 'customers.activity_type_fieldsets_load_failed',\n })\n if (active) setFieldsetsStatus('error')\n })\n return () => { active = false }\n }, [selected, fieldsetAttempt])\n\n const localRow = (key: string) => rows.find((row) => row.value.toLowerCase() === key && !row.isInherited)\n const openEditor = (item: ScopedCalendarEventType | null) => {\n setSelectedVersion(item ? localRow(item.key)?.updatedAt ?? item.updatedAt : undefined)\n setSelected(item)\n }\n const remove = async (item: ScopedCalendarEventType) => {\n const row = localRow(item.key)\n if (!row) return\n const approved = await confirm({\n title: t('customers.config.activityTypes.resetConfirm', 'Remove the local activity type configuration?'),\n variant: 'destructive',\n })\n if (!approved) return\n try {\n await runMutation({\n operation: () => withScopedApiRequestHeaders(buildOptimisticLockHeader(row.updatedAt), () =>\n apiCallOrThrow(`${API}/${encodeURIComponent(row.id)}`, { method: 'DELETE' })),\n context: { formId: 'customers-activity-types', resourceKind: 'customers.dictionary', retryLastMutation },\n mutationPayload: { action: 'delete', id: row.id, kind: 'activity-types' },\n })\n flash(t('customers.config.activityTypes.removed', 'Activity type configuration removed.'), 'success')\n await load()\n } catch (err) {\n logger.error('customers.activity_types.settings.remove failed', { err })\n getTelemetryRuntime()?.reportError(err, {\n module: 'customers',\n code: 'customers.activity_type_settings_remove_failed',\n })\n if (!surfaceRecordConflict(err, t, { onRefresh: () => { void load() } })) {\n flash(t('customers.config.activityTypes.saveFailed', 'Failed to save activity type.'), 'error')\n }\n }\n }\n\n const fields = React.useMemo<CrudField[]>(() => {\n const label = (key: string, fallback: string) => t(`customers.config.activityTypes.fields.${key}`, fallback)\n const options = (values: readonly string[]) => values.map((value) => ({ value, label: t(`customers.config.activityTypes.options.${value}`, value) }))\n const knownFieldsets = fieldsets.map(({ code, label: fieldsetLabel }) => ({ value: code, label: fieldsetLabel }))\n const missing = selected?.behavior.customFieldsetIds.filter((code) => !fieldsets.some((fieldset) => fieldset.code === code)) ?? []\n return [\n { id: 'value', type: 'text', label: label('value', 'Stable key'), required: true, readOnly: !!selected },\n { id: 'label', type: 'text', label: label('label', 'Label'), required: true },\n { id: 'icon', type: 'text', label: label('icon', 'Icon') },\n { id: 'color', type: 'text', label: label('color', 'Color (#RRGGBB)') },\n { id: 'order', type: 'number', label: label('order', 'Display order'), required: true },\n { id: 'baseKind', type: 'select', label: label('baseKind', 'Base behavior'), options: options(['meeting', 'call', 'email', 'note', 'event', 'task']) },\n { id: 'selectable', type: 'checkbox', label: label('selectable', 'Available for new events') },\n ...(['endTime', 'allDay', 'recurrence', 'priority', 'resources'] as const).map((id): CrudField => ({ id, type: 'checkbox', label: label(id, id) })),\n { id: 'location', type: 'select', label: label('location', 'Location field'), options: options(['none', 'location', 'phoneLink']) },\n { id: 'people', type: 'select', label: label('people', 'People field'), options: options(['none', 'attendees', 'participants', 'recipients', 'assignee']) },\n { id: 'customFieldsetIds', type: 'select', multiple: true, label: label('customFieldsetIds', 'Custom-field fieldsets'),\n options: [...knownFieldsets, ...missing.map((code) => ({ value: code, label: `${code} (${t('customers.config.activityTypes.missing', 'missing')})` }))] },\n ]\n }, [fieldsets, selected, t])\n const groups: CrudFormGroup[] = [\n { id: 'appearance', title: t('customers.config.activityTypes.appearance', 'Appearance'), fields: ['value', 'label', 'icon', 'color', 'order'] },\n { id: 'behavior', title: t('customers.config.activityTypes.behavior', 'Form behavior'), fields: ['baseKind', 'selectable', 'endTime', 'allDay', 'recurrence', 'location', 'people', 'priority', 'resources'] },\n ...(fieldsets.length || selected?.behavior.customFieldsetIds.length ? [{ id: 'fieldsets', fields: ['customFieldsetIds'] }] : []),\n ]\n const formInitialValues = React.useMemo(() => initialValues(selected ?? null, selectedVersion), [selected, selectedVersion])\n const save = async (values: FormValues) => {\n const key = String(values.value ?? '').trim()\n if (!calendarEventTypeKeySchema.safeParse(key).success) throw createCrudFormError(t('customers.config.activityTypes.invalidKey', 'Use a lowercase key with letters, numbers, hyphens, or underscores.'), { value: t('customers.config.activityTypes.invalidKey', 'Use a lowercase key with letters, numbers, hyphens, or underscores.') })\n if (fieldsetsStatus !== 'ready') throw createCrudFormError(t('customers.config.activityTypes.fieldsetsUnavailable', 'Fieldsets are unavailable. Retry loading before saving.'))\n const behavior = calendarEventTypeBehaviorSchema.safeParse({\n schemaVersion: 1, baseKind: values.baseKind, selectable: values.selectable === true,\n order: Number(values.order), customFieldsetIds: values.customFieldsetIds ?? [],\n fields: { endTime: values.endTime === true, allDay: values.allDay === true, recurrence: values.recurrence === true,\n location: values.location, people: values.people, priority: values.priority === true, resources: values.resources === true },\n })\n if (!behavior.success) throw createCrudFormError(t('customers.config.activityTypes.invalidBehavior', 'Check the form behavior values.'))\n const payload = { value: key, label: String(values.label ?? '').trim(), icon: String(values.icon ?? '').trim() || null,\n color: String(values.color ?? '').trim() || null, behavior: behavior.data }\n const row = selected ? localRow(selected.key) : undefined\n await apiCallOrThrow(row ? `${API}/${encodeURIComponent(row.id)}` : API, {\n method: row ? 'PATCH' : 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify(row ? { label: payload.label, icon: payload.icon, color: payload.color, behavior: payload.behavior } : payload),\n })\n setSelected(undefined)\n flash(t('customers.config.activityTypes.saved', 'Activity type saved.'), 'success')\n await load()\n }\n\n const columns = React.useMemo<ColumnDef<ScopedCalendarEventType>[]>(() => [\n { accessorKey: 'label', header: t('customers.config.activityTypes.columns.type', 'Activity type'), cell: ({ row }) => (\n <div className=\"flex items-center gap-2\">{row.original.color ? renderDictionaryColor(row.original.color, 'size-4 rounded-full border border-border') : null}\n {row.original.icon ? renderDictionaryIcon(row.original.icon, 'size-4') : null}<span>{row.original.labelKey\n ? t(row.original.labelKey, row.original.label)\n : row.original.label}</span></div>) },\n { accessorKey: 'key', header: t('customers.config.activityTypes.columns.key', 'Stable key') },\n { id: 'source', header: t('customers.config.activityTypes.columns.source', 'Source'), cell: ({ row }) => row.original.isLocalOverride\n ? t('customers.config.activityTypes.local', 'Local override') : row.original.isInherited\n ? t('customers.config.activityTypes.inherited', 'Inherited') : row.original.source },\n { id: 'behavior', header: t('customers.config.activityTypes.columns.behavior', 'Behavior'), cell: ({ row }) =>\n t(`customers.config.activityTypes.options.${row.original.behavior.baseKind}`, row.original.behavior.baseKind) },\n { id: 'active', header: t('customers.config.activityTypes.columns.active', 'Selectable'), cell: ({ row }) => row.original.selectable\n ? t('customers.config.activityTypes.yes', 'Yes') : t('customers.config.activityTypes.no', 'No') },\n { id: 'fields', header: t('customers.config.activityTypes.columns.fields', 'Fields'), cell: ({ row }) =>\n Object.values(row.original.behavior.fields).filter((value) => value !== false && value !== 'none').length },\n { id: 'fieldsets', header: t('customers.config.activityTypes.columns.fieldsets', 'Fieldsets'), cell: ({ row }) => row.original.behavior.customFieldsetIds.length },\n { id: 'order', header: t('customers.config.activityTypes.columns.order', 'Order'), cell: ({ row }) => row.original.behavior.order },\n ], [t])\n\n return <section id={getCustomerDictionarySettingsSectionId('activity-types')} className=\"scroll-mt-24 rounded border bg-card text-card-foreground shadow-sm\">\n <div className=\"space-y-1 border-b px-6 py-4\"><h2 className=\"text-lg font-medium\">{title}</h2><p className=\"text-sm text-muted-foreground\">{description}</p></div>\n <div className=\"px-2 py-4 sm:px-4\">\n {status === 'error' ? <div className=\"space-y-3\"><ErrorMessage label={t('customers.config.activityTypes.loadFailed', 'Failed to load activity types.')} /><Button type=\"button\" onClick={() => { void load() }}>{t('customers.config.activityTypes.retry', 'Retry')}</Button></div> :\n <DataTable<ScopedCalendarEventType> embedded columns={columns} data={items} isLoading={status === 'loading'}\n title={title} titleHeadingLevel={2} emptyState={t('customers.config.activityTypes.empty', 'No activity types available.')}\n actions={<Button type=\"button\" size=\"sm\" onClick={() => openEditor(null)}>{t('customers.config.activityTypes.new', 'New activity type')}</Button>}\n refreshButton={{ label: t('customers.config.activityTypes.refresh', 'Refresh'), onRefresh: load, isRefreshing: status === 'loading' }}\n rowActions={(item) => {\n const actions: RowActionItem[] = [{ id: 'edit', label: item.adminConfigurable\n ? t('customers.config.activityTypes.configure', 'Configure') : t('customers.config.activityTypes.view', 'View'), onSelect: () => openEditor(item) }]\n if (localRow(item.key)) actions.push({ id: 'delete', label: item.source === 'dictionary'\n ? t('customers.config.activityTypes.delete', 'Delete') : t('customers.config.activityTypes.reset', 'Reset override'),\n destructive: true, onSelect: () => { void remove(item) } })\n return <RowActions items={actions} />\n }} />}\n </div>\n <Dialog open={selected !== undefined} onOpenChange={(open) => { if (!open) setSelected(undefined) }}>\n <DialogContent className=\"max-h-screen overflow-y-auto sm:max-w-2xl\">\n <DialogHeader><DialogTitle>{selected\n ? t('customers.config.activityTypes.configure', 'Configure') : t('customers.config.activityTypes.new', 'New activity type')}</DialogTitle></DialogHeader>\n {selected?.isInherited ? <p className=\"text-sm text-muted-foreground\">{t('customers.config.activityTypes.inheritedHint', 'Saving creates a local override for this organization.')}</p> : null}\n {selected?.inactiveDictionaryOverride ? <p className=\"text-sm text-muted-foreground\">{t('customers.config.activityTypes.inactiveHint', 'A module currently prevents this override from taking effect.')}</p> : null}\n {selected?.missingCustomFieldsetIds.length ? <p className=\"text-sm text-muted-foreground\">{t('customers.config.activityTypes.missingHint', 'Some configured fieldsets no longer exist.')}: {selected.missingCustomFieldsetIds.join(', ')}</p> : null}\n {fieldsetsStatus === 'loading' ? <LoadingMessage label={t('customers.config.activityTypes.loadingFieldsets', 'Loading fieldsets\u2026')} /> : null}\n {fieldsetsStatus === 'error' ? <ErrorMessage label={t('customers.config.activityTypes.fieldsetsUnavailable', 'Fieldsets are unavailable. Retry loading before saving.')} /> : null}\n {fieldsetsStatus === 'error' ? <Button type=\"button\" onClick={() => setFieldsetAttempt((attempt) => attempt + 1)}>{t('customers.config.activityTypes.retry', 'Retry')}</Button> : null}\n {fieldsetsStatus === 'ready' && fieldsets.length === 0 ? <p className=\"text-sm text-muted-foreground\">{t('customers.config.activityTypes.noFieldsets', 'No custom-field fieldsets are defined yet.')}</p> : null}\n {selected !== undefined && fieldsetsStatus === 'ready' ? <CrudForm<FormValues> key={selected?.key ?? 'new'} embedded\n readOnly={selected?.adminConfigurable === false} fields={fields} groups={groups}\n initialValues={formInitialValues} onSubmit={save} submitLabel={t('customers.config.activityTypes.save', 'Save')}\n extraActions={<Button type=\"button\" variant=\"outline\" onClick={() => setSelected(undefined)}>{t('customers.config.dictionaries.dialog.cancel', 'Cancel')}</Button>} /> : null}\n </DialogContent>\n </Dialog>\n {ConfirmDialogElement}\n </section>\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -15,7 +15,8 @@ import { lookupPhoneDuplicate } from "../../utils/phoneDuplicates.js";
|
|
|
15
15
|
import {
|
|
16
16
|
InlineMultilineEditor as UiInlineMultilineEditor,
|
|
17
17
|
InlineTextEditor as UiInlineTextEditor,
|
|
18
|
-
InlineSelectEditor as UiInlineSelectEditor
|
|
18
|
+
InlineSelectEditor as UiInlineSelectEditor,
|
|
19
|
+
INLINE_TRIGGER_HIDDEN_CLASSES
|
|
19
20
|
} from "@open-mercato/ui/backend/detail/InlineEditors";
|
|
20
21
|
import {
|
|
21
22
|
DictionaryValue,
|
|
@@ -312,6 +313,7 @@ function InlineNextInteractionEditor({
|
|
|
312
313
|
const dateErrorId = React.useId();
|
|
313
314
|
const nameErrorId = React.useId();
|
|
314
315
|
const containerClasses = cn("group relative rounded-lg border p-4", activateOnClick && !editing ? "cursor-pointer" : null);
|
|
316
|
+
const triggerLabel = editing ? t("ui.detail.inline.cancel", "Cancel") : t("ui.detail.inline.edit", "Edit");
|
|
315
317
|
const requiredMessage = React.useMemo(
|
|
316
318
|
() => t("customers.people.detail.inline.required", "This field is required"),
|
|
317
319
|
[t]
|
|
@@ -463,13 +465,15 @@ function InlineNextInteractionEditor({
|
|
|
463
465
|
size: "sm",
|
|
464
466
|
className: cn(
|
|
465
467
|
"absolute right-3 top-3 transition-opacity duration-150",
|
|
466
|
-
editing ? "opacity-100" :
|
|
468
|
+
editing ? "opacity-100" : INLINE_TRIGGER_HIDDEN_CLASSES
|
|
467
469
|
),
|
|
468
470
|
onClick: (event) => {
|
|
469
471
|
event.stopPropagation();
|
|
470
472
|
setEditing((state) => !state);
|
|
471
473
|
},
|
|
472
|
-
|
|
474
|
+
"aria-label": triggerLabel,
|
|
475
|
+
title: triggerLabel,
|
|
476
|
+
children: editing ? /* @__PURE__ */ jsx(X, { className: "h-4 w-4", "aria-hidden": true }) : /* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4", "aria-hidden": true })
|
|
473
477
|
}
|
|
474
478
|
),
|
|
475
479
|
/* @__PURE__ */ jsx("div", { className: "flex items-start gap-2", ...interactiveProps, children: /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/customers/components/detail/InlineEditors.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { AtSign, Briefcase, Loader2, Pencil, X } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { MarkdownContent } from '@open-mercato/ui/backend/markdown'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useEmailDuplicateCheck } from '../../backend/hooks/useEmailDuplicateCheck'\nimport { lookupPhoneDuplicate } from '../../utils/phoneDuplicates'\nimport {\n InlineMultilineEditor as UiInlineMultilineEditor,\n InlineTextEditor as UiInlineTextEditor,\n type InlineFieldType as UiInlineFieldType,\n type InlineMultilineEditorProps,\n type InlineTextEditorProps,\n InlineSelectEditor as UiInlineSelectEditor,\n type InlineSelectOption,\n} from '@open-mercato/ui/backend/detail/InlineEditors'\nimport {\n DictionaryValue,\n ICON_SUGGESTIONS,\n renderDictionaryColor,\n renderDictionaryIcon,\n type CustomerDictionaryKind,\n} from '../../lib/dictionaries'\nimport { DictionarySelectField } from '../formConfig'\nimport { AppearanceSelector } from '@open-mercato/core/modules/dictionaries/components/AppearanceSelector'\nimport { createDictionarySelectLabels } from './utils'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\nimport {\n invalidateCustomerDictionary,\n useCustomerDictionary,\n} from './hooks/useCustomerDictionary'\n\nexport type InlineFieldType = UiInlineFieldType\nexport type InlineFieldProps = InlineTextEditorProps\nexport type InlineMultilineDisplayRenderer = NonNullable<InlineMultilineEditorProps['renderDisplay']>\n\nexport function InlineTextEditor(props: InlineFieldProps) {\n const { type = 'text', validator, recordId } = props\n const t = useT()\n const normalizeText = React.useCallback((value: unknown) => {\n if (typeof value === 'string') return value\n if (value === null || value === undefined) return ''\n return String(value)\n }, [])\n const [draft, setDraft] = React.useState<string>(() => normalizeText(props.value))\n const setDraftValue = React.useCallback((value: unknown) => {\n setDraft(normalizeText(value))\n }, [normalizeText])\n const [editing, setEditing] = React.useState(false)\n const currentRecordId = React.useMemo(() => (typeof recordId === 'string' ? recordId : null), [recordId])\n const isEmailField = type === 'email'\n const isPhoneField = type === 'tel'\n const trimmedDraft = React.useMemo(() => draft.trim(), [draft])\n const validationError = React.useMemo(() => {\n if (!validator) return null\n return validator(trimmedDraft)\n }, [trimmedDraft, validator])\n const isValidEmailForLookup = React.useMemo(() => {\n if (!isEmailField) return false\n if (!trimmedDraft.length) return false\n return !validationError\n }, [isEmailField, trimmedDraft, validationError])\n const { duplicate: emailDuplicate, checking: emailChecking } = useEmailDuplicateCheck(draft, {\n recordId: currentRecordId,\n disabled: !editing || !isValidEmailForLookup,\n matchMode: 'prefix',\n })\n const [phoneDuplicate, setPhoneDuplicate] = React.useState<{ id: string; label: string; href?: string } | null>(null)\n const [phoneChecking, setPhoneChecking] = React.useState(false)\n\n React.useEffect(() => {\n if (!editing) {\n setDraftValue(props.value)\n }\n }, [editing, props.value, setDraftValue])\n\n React.useEffect(() => {\n if (!editing || !isPhoneField) {\n setPhoneDuplicate(null)\n setPhoneChecking(false)\n return\n }\n const digits = draft.replace(/\\\\D/g, '')\n if (digits.length < 7) {\n setPhoneDuplicate(null)\n setPhoneChecking(false)\n return\n }\n let cancelled = false\n setPhoneChecking(true)\n void lookupPhoneDuplicate(digits, { recordId: currentRecordId })\n .then((result) => {\n if (cancelled) return\n setPhoneDuplicate(result)\n })\n .catch(() => {\n if (cancelled) return\n setPhoneDuplicate(null)\n })\n .finally(() => {\n if (cancelled) return\n setPhoneChecking(false)\n })\n return () => {\n cancelled = true\n }\n }, [currentRecordId, draft, editing, isPhoneField])\n\n return (\n <UiInlineTextEditor\n {...props}\n type={type}\n validator={validator}\n value={normalizeText(props.value)}\n onDraftChange={setDraftValue}\n onEditingChange={setEditing}\n renderBelowInput={({ resolvedType, error }) => {\n if (resolvedType === 'email') {\n if (error || !editing || !isValidEmailForLookup) return null\n if (emailDuplicate) {\n return (\n <p className=\"text-xs text-muted-foreground\">\n {t('customers.people.detail.inline.emailDuplicate', undefined, { name: emailDuplicate.displayName })}{' '}\n <Link\n className=\"font-medium text-primary underline underline-offset-2\"\n href={`/backend/customers/people-v2/${emailDuplicate.id}`}\n >\n {t('customers.people.detail.inline.emailDuplicateLink')}\n </Link>\n </p>\n )\n }\n if (emailChecking) {\n return <p className=\"text-xs text-muted-foreground\">{t('customers.people.detail.inline.emailChecking')}</p>\n }\n }\n if (resolvedType === 'tel') {\n if (error || !editing) return null\n if (phoneDuplicate) {\n return (\n <p className=\"text-xs text-muted-foreground\">\n {t('customers.people.form.phoneDuplicateNotice', undefined, { name: phoneDuplicate.label })}{' '}\n {phoneDuplicate.href ? (\n <Link\n className=\"font-medium text-primary underline underline-offset-2\"\n href={phoneDuplicate.href}\n >\n {t('customers.people.form.phoneDuplicateLink')}\n </Link>\n ) : null}\n </p>\n )\n }\n if (phoneChecking) {\n return <p className=\"text-xs text-muted-foreground\">{t('customers.people.form.phoneChecking')}</p>\n }\n }\n return null\n }}\n />\n )\n}\nexport const InlineMultilineEditor = UiInlineMultilineEditor\nexport const InlineSelectEditor = UiInlineSelectEditor\n\nfunction createSocialRenderDisplay(IconComponent: typeof Briefcase): NonNullable<InlineFieldProps['renderDisplay']> {\n // eslint-disable-next-line react/display-name\n return ({ value, emptyLabel }) => {\n const raw = typeof value === 'string' ? value.trim() : ''\n if (!raw.length) {\n return <span className=\"text-sm text-muted-foreground\">{emptyLabel}</span>\n }\n const display = raw.replace(/^https?:\\/\\/(www\\.)?/i, '').replace(/\\/$/, '')\n return (\n <a\n className=\"inline-flex items-center gap-2 text-sm text-primary hover:text-primary/90 hover:underline\"\n href={raw}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n <IconComponent aria-hidden className=\"h-4 w-4\" />\n <span className=\"truncate\">{display}</span>\n </a>\n )\n }\n}\n\nexport const renderLinkedInDisplay = createSocialRenderDisplay(Briefcase)\nexport const renderTwitterDisplay = createSocialRenderDisplay(AtSign)\n\nexport const renderMultilineMarkdownDisplay: InlineMultilineDisplayRenderer = ({ value, emptyLabel }) => {\n const raw = typeof value === 'string' ? value : ''\n const trimmed = raw.trim()\n if (!trimmed.length) {\n return <span className=\"text-muted-foreground\">{emptyLabel}</span>\n }\n return (\n <MarkdownContent\n format=\"markdown\"\n body={raw}\n className=\"text-sm text-foreground [&>*]:mb-2 [&>*:last-child]:mb-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:text-xs\"\n />\n )\n}\n\ntype DictionaryEditorProps = {\n label: string\n value: string | null | undefined\n emptyLabel: string\n onSave: (value: string | null) => Promise<void>\n kind: CustomerDictionaryKind\n variant?: 'default' | 'muted'\n activateOnClick?: boolean\n containerClassName?: string\n triggerClassName?: string\n selectClassName?: string\n}\n\nexport function InlineDictionaryEditor({\n label,\n value,\n emptyLabel,\n onSave,\n kind,\n variant = 'default',\n activateOnClick = false,\n containerClassName,\n triggerClassName,\n selectClassName,\n}: DictionaryEditorProps) {\n const t = useT()\n const queryClient = useQueryClient()\n const translate = React.useCallback(\n (key: string, fallback: string) => {\n const result = t(key)\n return result === key ? fallback : result\n },\n [t],\n )\n const dictionaryLabels = React.useMemo(() => createDictionarySelectLabels(kind, translate), [kind, translate])\n const scopeVersion = useOrganizationScopeVersion()\n const dictionaryQuery = useCustomerDictionary(kind, scopeVersion)\n const dictionaryMap = dictionaryQuery.data?.map ?? null\n const selectOptions = React.useMemo<InlineSelectOption[]>(() => {\n if (!dictionaryMap) return []\n return Object.values(dictionaryMap).map((entry) => ({ value: entry.value, label: entry.label }))\n }, [dictionaryMap])\n\n const handleSave = React.useCallback(\n async (nextValue: string | null) => {\n try {\n await onSave(nextValue)\n await invalidateCustomerDictionary(queryClient, kind)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.people.detail.inline.error')\n flash(message, 'error')\n }\n },\n [kind, onSave, queryClient, t],\n )\n\n return (\n <UiInlineSelectEditor\n label={label}\n value={value}\n emptyLabel={emptyLabel}\n options={selectOptions}\n onSave={handleSave}\n variant={variant}\n activateOnClick={activateOnClick}\n containerClassName={containerClassName}\n triggerClassName={triggerClassName}\n hideLabel={false}\n renderEditor={({ value: selectValue, onChange }) => (\n <>\n <DictionarySelectField\n kind={kind}\n value={selectValue.length ? selectValue : undefined}\n onChange={(next) => onChange(next ?? '')}\n labels={dictionaryLabels}\n selectClassName={selectClassName}\n />\n {dictionaryQuery.isError ? (\n <p className=\"text-xs text-status-error-text\">\n {dictionaryQuery.error instanceof Error\n ? dictionaryQuery.error.message\n : translate('customers.people.form.dictionary.errorLoad', 'Failed to load options')}\n </p>\n ) : null}\n </>\n )}\n renderDisplay={({ value: currentValue }) => {\n if (dictionaryMap) {\n return (\n <DictionaryValue\n value={currentValue}\n map={dictionaryMap}\n fallback={<span className=\"text-sm text-muted-foreground\">{emptyLabel}</span>}\n className=\"text-sm\"\n iconWrapperClassName=\"inline-flex h-6 w-6 items-center justify-center rounded border border-border bg-card\"\n iconClassName=\"h-4 w-4\"\n colorClassName=\"h-3 w-3 rounded-full\"\n />\n )\n }\n if (currentValue && currentValue.length) {\n return <span className=\"break-words text-sm\">{currentValue}</span>\n }\n if (dictionaryQuery.isLoading) {\n return (\n <span className=\"text-sm text-muted-foreground\">\n {translate('customers.people.form.dictionary.loading', 'Loading\u2026')}\n </span>\n )\n }\n return <span className=\"text-sm text-muted-foreground\">{emptyLabel}</span>\n }}\n />\n )\n}\n\nexport type NextInteractionPayload = {\n at: string\n name: string\n refId?: string | null\n icon?: string | null\n color?: string | null\n}\n\ntype NextInteractionEditorProps = {\n label: string\n valueAt: string | null | undefined\n valueName: string | null | undefined\n valueRefId: string | null | undefined\n valueIcon: string | null | undefined\n valueColor: string | null | undefined\n emptyLabel: string\n onSave: (next: NextInteractionPayload | null) => Promise<void>\n activateOnClick?: boolean\n}\n\nexport function InlineNextInteractionEditor({\n label,\n valueAt,\n valueName,\n valueRefId,\n valueIcon,\n valueColor,\n emptyLabel,\n onSave,\n activateOnClick = false,\n}: NextInteractionEditorProps) {\n const t = useT()\n const [editing, setEditing] = React.useState(false)\n const [draftDate, setDraftDate] = React.useState<string>(() => (valueAt ? valueAt.slice(0, 16) : ''))\n const [draftName, setDraftName] = React.useState(valueName ?? '')\n const [draftRefId, setDraftRefId] = React.useState(valueRefId ?? '')\n const [draftIcon, setDraftIcon] = React.useState(valueIcon ?? '')\n const [draftColor, setDraftColor] = React.useState<string | null>(valueColor ?? null)\n const [dateError, setDateError] = React.useState<string | null>(null)\n const [nameError, setNameError] = React.useState<string | null>(null)\n const [submitError, setSubmitError] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n const formRef = React.useRef<HTMLFormElement | null>(null)\n const dateErrorId = React.useId()\n const nameErrorId = React.useId()\n const containerClasses = cn('group relative rounded-lg border p-4', activateOnClick && !editing ? 'cursor-pointer' : null)\n const requiredMessage = React.useMemo(\n () => t('customers.people.detail.inline.required', 'This field is required'),\n [t],\n )\n\n React.useEffect(() => {\n if (!editing) {\n setDraftDate(valueAt ? valueAt.slice(0, 16) : '')\n setDraftName(valueName ?? '')\n setDraftRefId(valueRefId ?? '')\n setDraftIcon(valueIcon ?? '')\n setDraftColor(valueColor ?? null)\n setDateError(null)\n setNameError(null)\n setSubmitError(null)\n }\n }, [editing, valueAt, valueName, valueRefId, valueIcon, valueColor])\n\n const appearanceLabels = React.useMemo(\n () => ({\n colorLabel: t('customers.people.detail.inline.nextInteractionColorLabel'),\n colorHelp: t('customers.people.detail.inline.nextInteractionColorHelp'),\n colorClearLabel: t('customers.people.detail.inline.nextInteractionColorClear'),\n iconLabel: t('customers.people.detail.inline.nextInteractionIconLabel'),\n iconPlaceholder: t('customers.people.detail.inline.nextInteractionIconPlaceholder'),\n iconPickerTriggerLabel: t('customers.people.detail.inline.nextInteractionIconBrowse'),\n iconSearchPlaceholder: t('customers.people.detail.inline.nextInteractionIconSearchPlaceholder'),\n iconSearchEmptyLabel: t('customers.people.detail.inline.nextInteractionIconSearchEmpty'),\n iconSuggestionsLabel: t('customers.people.detail.inline.nextInteractionIconSuggestions'),\n iconClearLabel: t('customers.people.detail.inline.nextInteractionIconClear'),\n previewEmptyLabel: t('customers.people.detail.inline.nextInteractionAppearanceEmpty'),\n }),\n [t],\n )\n\n const handleSave = React.useCallback(async () => {\n setSubmitError(null)\n setDateError(null)\n setNameError(null)\n const trimmedName = draftName.trim()\n let hasError = false\n if (!draftDate) {\n setDateError(requiredMessage)\n hasError = true\n }\n if (!trimmedName.length) {\n setNameError(requiredMessage)\n hasError = true\n }\n if (hasError) return\n const parsedDate = new Date(draftDate)\n if (Number.isNaN(parsedDate.getTime())) {\n setDateError(t('customers.people.detail.inline.nextInteractionInvalid'))\n return\n }\n const iso = parsedDate.toISOString()\n const trimmedRef = draftRefId.trim()\n const trimmedIcon = draftIcon.trim()\n const normalizedColor = (() => {\n if (!draftColor) return null\n const trimmed = draftColor.trim().toLowerCase()\n return /^#([0-9a-f]{6})$/.test(trimmed) ? trimmed : null\n })()\n setSaving(true)\n try {\n await onSave({\n at: iso,\n name: trimmedName,\n refId: trimmedRef.length ? trimmedRef : null,\n icon: trimmedIcon.length ? trimmedIcon : null,\n color: normalizedColor,\n })\n setEditing(false)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.people.detail.inline.error')\n setSubmitError(message)\n } finally {\n setSaving(false)\n }\n }, [draftColor, draftDate, draftIcon, draftName, draftRefId, onSave, requiredMessage, t])\n\n const handleFormSubmit = React.useCallback(\n (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault()\n if (saving) return\n void handleSave()\n },\n [handleSave, saving],\n )\n\n const handleFormKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLFormElement>) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n setEditing(false)\n return\n }\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n if (saving) return\n try {\n formRef.current?.requestSubmit()\n } catch {\n void handleSave()\n }\n }\n },\n [handleSave, saving],\n )\n\n const handleActivate = React.useCallback(() => {\n if (!editing) setEditing(true)\n }, [editing])\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!activateOnClick || editing) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n handleActivate()\n }\n },\n [activateOnClick, editing, handleActivate],\n )\n\n const handleInteractiveClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (!activateOnClick || editing) return\n const target = event.target as HTMLElement\n const interactiveElement = target.closest('button, input, select, textarea, a, [role=\\\"link\\\"]')\n if (interactiveElement) {\n if (interactiveElement.tagName.toLowerCase() === 'a') {\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {\n return\n }\n event.preventDefault()\n } else {\n return\n }\n }\n handleActivate()\n },\n [activateOnClick, editing, handleActivate],\n )\n\n const interactiveProps: React.HTMLAttributes<HTMLDivElement> =\n activateOnClick && !editing\n ? {\n role: 'button' as const,\n tabIndex: 0,\n onClick: handleInteractiveClick,\n onKeyDown: handleKeyDown,\n }\n : {}\n\n return (\n <div className={containerClasses} onClick={handleInteractiveClick}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className={cn(\n 'absolute right-3 top-3 transition-opacity duration-150',\n editing\n ? 'opacity-100'\n : 'opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100',\n )}\n onClick={(event) => {\n event.stopPropagation()\n setEditing((state) => !state)\n }}\n >\n {editing ? <X className=\"h-4 w-4\" /> : <Pencil className=\"h-4 w-4\" />}\n </Button>\n <div className=\"flex items-start gap-2\" {...interactiveProps}>\n <div className=\"flex-1\">\n <p className=\"text-xs uppercase tracking-wide text-muted-foreground\">{label}</p>\n {editing ? (\n <form\n ref={formRef}\n className=\"mt-2 space-y-4\"\n onSubmit={handleFormSubmit}\n onKeyDown={handleFormKeyDown}\n >\n <input\n type=\"datetime-local\"\n className={cn(\n 'w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n dateError ? 'border-destructive aria-invalid:border-destructive aria-invalid:ring-destructive' : null,\n )}\n value={draftDate}\n aria-invalid={dateError ? 'true' : undefined}\n aria-required=\"true\"\n aria-describedby={dateError ? dateErrorId : undefined}\n onChange={(event) => {\n if (dateError) setDateError(null)\n if (submitError) setSubmitError(null)\n setDraftDate(event.target.value)\n }}\n />\n {dateError ? (\n <p id={dateErrorId} className=\"text-xs text-destructive\">\n {dateError}\n </p>\n ) : null}\n <input\n placeholder={t('customers.people.detail.inline.nextInteractionName')}\n className={cn(\n 'w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n nameError ? 'border-destructive aria-invalid:border-destructive aria-invalid:ring-destructive' : null,\n )}\n value={draftName}\n aria-invalid={nameError ? 'true' : undefined}\n aria-required=\"true\"\n aria-describedby={nameError ? nameErrorId : undefined}\n onChange={(event) => {\n if (submitError) setSubmitError(null)\n if (nameError) setNameError(null)\n setDraftName(event.target.value)\n }}\n />\n {nameError ? (\n <p id={nameErrorId} className=\"text-xs text-destructive\">\n {nameError}\n </p>\n ) : null}\n <input\n placeholder={t('customers.people.detail.inline.nextInteractionRef')}\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={draftRefId}\n onChange={(event) => {\n if (submitError) setSubmitError(null)\n setDraftRefId(event.target.value)\n }}\n />\n <AppearanceSelector\n icon={draftIcon || null}\n color={draftColor}\n onIconChange={(next) => {\n if (submitError) setSubmitError(null)\n setDraftIcon(next ?? '')\n }}\n onColorChange={(next) => {\n if (submitError) setSubmitError(null)\n setDraftColor(next)\n }}\n iconSuggestions={ICON_SUGGESTIONS}\n disabled={saving}\n labels={appearanceLabels}\n />\n {submitError && !dateError && !nameError ? (\n <p className=\"text-xs text-destructive\">{submitError}</p>\n ) : null}\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button type=\"submit\" size=\"sm\" disabled={saving}>\n {saving ? <Loader2 className=\"mr-2 h-3.5 w-3.5 animate-spin\" /> : null}\n {t('customers.people.detail.inline.saveShortcut', 'Save \u2318\u23CE / Ctrl+Enter')}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => setEditing(false)} disabled={saving}>\n {t('customers.people.detail.inline.cancel')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n onClick={async () => {\n setDraftDate('')\n setDraftName('')\n setDraftRefId('')\n setDraftIcon('')\n setDraftColor(null)\n setDateError(null)\n setNameError(null)\n setSubmitError(null)\n setSaving(true)\n try {\n await onSave(null)\n setEditing(false)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.people.detail.inline.error')\n setSubmitError(message)\n } finally {\n setSaving(false)\n }\n }}\n disabled={saving}\n >\n {t('customers.people.detail.inline.clear')}\n </Button>\n </div>\n </form>\n ) : (\n <div className=\"mt-1 text-sm\">\n {valueAt ? (\n <div className=\"flex items-start gap-3\">\n {valueIcon ? (\n <span className=\"inline-flex h-8 w-8 items-center justify-center rounded border border-border bg-card\">\n {renderDictionaryIcon(valueIcon, 'h-4 w-4')}\n </span>\n ) : null}\n <div className=\"flex-1\">\n <span className=\"block\">{formatDateTime(valueAt)}</span>\n {valueName ? <span className=\"text-xs text-muted-foreground\">{valueName}</span> : null}\n {valueRefId ? <span className=\"text-xs text-muted-foreground\">#{valueRefId}</span> : null}\n </div>\n {valueColor ? renderDictionaryColor(valueColor, 'h-3 w-3 rounded-full border border-border') : null}\n </div>\n ) : (\n <span className=\"text-muted-foreground\">{emptyLabel}</span>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { AtSign, Briefcase, Loader2, Pencil, X } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { MarkdownContent } from '@open-mercato/ui/backend/markdown'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useEmailDuplicateCheck } from '../../backend/hooks/useEmailDuplicateCheck'\nimport { lookupPhoneDuplicate } from '../../utils/phoneDuplicates'\nimport {\n InlineMultilineEditor as UiInlineMultilineEditor,\n InlineTextEditor as UiInlineTextEditor,\n type InlineFieldType as UiInlineFieldType,\n type InlineMultilineEditorProps,\n type InlineTextEditorProps,\n InlineSelectEditor as UiInlineSelectEditor,\n INLINE_TRIGGER_HIDDEN_CLASSES,\n type InlineSelectOption,\n} from '@open-mercato/ui/backend/detail/InlineEditors'\nimport {\n DictionaryValue,\n ICON_SUGGESTIONS,\n renderDictionaryColor,\n renderDictionaryIcon,\n type CustomerDictionaryKind,\n} from '../../lib/dictionaries'\nimport { DictionarySelectField } from '../formConfig'\nimport { AppearanceSelector } from '@open-mercato/core/modules/dictionaries/components/AppearanceSelector'\nimport { createDictionarySelectLabels } from './utils'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\nimport {\n invalidateCustomerDictionary,\n useCustomerDictionary,\n} from './hooks/useCustomerDictionary'\n\nexport type InlineFieldType = UiInlineFieldType\nexport type InlineFieldProps = InlineTextEditorProps\nexport type InlineMultilineDisplayRenderer = NonNullable<InlineMultilineEditorProps['renderDisplay']>\n\nexport function InlineTextEditor(props: InlineFieldProps) {\n const { type = 'text', validator, recordId } = props\n const t = useT()\n const normalizeText = React.useCallback((value: unknown) => {\n if (typeof value === 'string') return value\n if (value === null || value === undefined) return ''\n return String(value)\n }, [])\n const [draft, setDraft] = React.useState<string>(() => normalizeText(props.value))\n const setDraftValue = React.useCallback((value: unknown) => {\n setDraft(normalizeText(value))\n }, [normalizeText])\n const [editing, setEditing] = React.useState(false)\n const currentRecordId = React.useMemo(() => (typeof recordId === 'string' ? recordId : null), [recordId])\n const isEmailField = type === 'email'\n const isPhoneField = type === 'tel'\n const trimmedDraft = React.useMemo(() => draft.trim(), [draft])\n const validationError = React.useMemo(() => {\n if (!validator) return null\n return validator(trimmedDraft)\n }, [trimmedDraft, validator])\n const isValidEmailForLookup = React.useMemo(() => {\n if (!isEmailField) return false\n if (!trimmedDraft.length) return false\n return !validationError\n }, [isEmailField, trimmedDraft, validationError])\n const { duplicate: emailDuplicate, checking: emailChecking } = useEmailDuplicateCheck(draft, {\n recordId: currentRecordId,\n disabled: !editing || !isValidEmailForLookup,\n matchMode: 'prefix',\n })\n const [phoneDuplicate, setPhoneDuplicate] = React.useState<{ id: string; label: string; href?: string } | null>(null)\n const [phoneChecking, setPhoneChecking] = React.useState(false)\n\n React.useEffect(() => {\n if (!editing) {\n setDraftValue(props.value)\n }\n }, [editing, props.value, setDraftValue])\n\n React.useEffect(() => {\n if (!editing || !isPhoneField) {\n setPhoneDuplicate(null)\n setPhoneChecking(false)\n return\n }\n const digits = draft.replace(/\\\\D/g, '')\n if (digits.length < 7) {\n setPhoneDuplicate(null)\n setPhoneChecking(false)\n return\n }\n let cancelled = false\n setPhoneChecking(true)\n void lookupPhoneDuplicate(digits, { recordId: currentRecordId })\n .then((result) => {\n if (cancelled) return\n setPhoneDuplicate(result)\n })\n .catch(() => {\n if (cancelled) return\n setPhoneDuplicate(null)\n })\n .finally(() => {\n if (cancelled) return\n setPhoneChecking(false)\n })\n return () => {\n cancelled = true\n }\n }, [currentRecordId, draft, editing, isPhoneField])\n\n return (\n <UiInlineTextEditor\n {...props}\n type={type}\n validator={validator}\n value={normalizeText(props.value)}\n onDraftChange={setDraftValue}\n onEditingChange={setEditing}\n renderBelowInput={({ resolvedType, error }) => {\n if (resolvedType === 'email') {\n if (error || !editing || !isValidEmailForLookup) return null\n if (emailDuplicate) {\n return (\n <p className=\"text-xs text-muted-foreground\">\n {t('customers.people.detail.inline.emailDuplicate', undefined, { name: emailDuplicate.displayName })}{' '}\n <Link\n className=\"font-medium text-primary underline underline-offset-2\"\n href={`/backend/customers/people-v2/${emailDuplicate.id}`}\n >\n {t('customers.people.detail.inline.emailDuplicateLink')}\n </Link>\n </p>\n )\n }\n if (emailChecking) {\n return <p className=\"text-xs text-muted-foreground\">{t('customers.people.detail.inline.emailChecking')}</p>\n }\n }\n if (resolvedType === 'tel') {\n if (error || !editing) return null\n if (phoneDuplicate) {\n return (\n <p className=\"text-xs text-muted-foreground\">\n {t('customers.people.form.phoneDuplicateNotice', undefined, { name: phoneDuplicate.label })}{' '}\n {phoneDuplicate.href ? (\n <Link\n className=\"font-medium text-primary underline underline-offset-2\"\n href={phoneDuplicate.href}\n >\n {t('customers.people.form.phoneDuplicateLink')}\n </Link>\n ) : null}\n </p>\n )\n }\n if (phoneChecking) {\n return <p className=\"text-xs text-muted-foreground\">{t('customers.people.form.phoneChecking')}</p>\n }\n }\n return null\n }}\n />\n )\n}\nexport const InlineMultilineEditor = UiInlineMultilineEditor\nexport const InlineSelectEditor = UiInlineSelectEditor\n\nfunction createSocialRenderDisplay(IconComponent: typeof Briefcase): NonNullable<InlineFieldProps['renderDisplay']> {\n // eslint-disable-next-line react/display-name\n return ({ value, emptyLabel }) => {\n const raw = typeof value === 'string' ? value.trim() : ''\n if (!raw.length) {\n return <span className=\"text-sm text-muted-foreground\">{emptyLabel}</span>\n }\n const display = raw.replace(/^https?:\\/\\/(www\\.)?/i, '').replace(/\\/$/, '')\n return (\n <a\n className=\"inline-flex items-center gap-2 text-sm text-primary hover:text-primary/90 hover:underline\"\n href={raw}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n <IconComponent aria-hidden className=\"h-4 w-4\" />\n <span className=\"truncate\">{display}</span>\n </a>\n )\n }\n}\n\nexport const renderLinkedInDisplay = createSocialRenderDisplay(Briefcase)\nexport const renderTwitterDisplay = createSocialRenderDisplay(AtSign)\n\nexport const renderMultilineMarkdownDisplay: InlineMultilineDisplayRenderer = ({ value, emptyLabel }) => {\n const raw = typeof value === 'string' ? value : ''\n const trimmed = raw.trim()\n if (!trimmed.length) {\n return <span className=\"text-muted-foreground\">{emptyLabel}</span>\n }\n return (\n <MarkdownContent\n format=\"markdown\"\n body={raw}\n className=\"text-sm text-foreground [&>*]:mb-2 [&>*:last-child]:mb-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:text-xs\"\n />\n )\n}\n\ntype DictionaryEditorProps = {\n label: string\n value: string | null | undefined\n emptyLabel: string\n onSave: (value: string | null) => Promise<void>\n kind: CustomerDictionaryKind\n variant?: 'default' | 'muted'\n activateOnClick?: boolean\n containerClassName?: string\n triggerClassName?: string\n selectClassName?: string\n}\n\nexport function InlineDictionaryEditor({\n label,\n value,\n emptyLabel,\n onSave,\n kind,\n variant = 'default',\n activateOnClick = false,\n containerClassName,\n triggerClassName,\n selectClassName,\n}: DictionaryEditorProps) {\n const t = useT()\n const queryClient = useQueryClient()\n const translate = React.useCallback(\n (key: string, fallback: string) => {\n const result = t(key)\n return result === key ? fallback : result\n },\n [t],\n )\n const dictionaryLabels = React.useMemo(() => createDictionarySelectLabels(kind, translate), [kind, translate])\n const scopeVersion = useOrganizationScopeVersion()\n const dictionaryQuery = useCustomerDictionary(kind, scopeVersion)\n const dictionaryMap = dictionaryQuery.data?.map ?? null\n const selectOptions = React.useMemo<InlineSelectOption[]>(() => {\n if (!dictionaryMap) return []\n return Object.values(dictionaryMap).map((entry) => ({ value: entry.value, label: entry.label }))\n }, [dictionaryMap])\n\n const handleSave = React.useCallback(\n async (nextValue: string | null) => {\n try {\n await onSave(nextValue)\n await invalidateCustomerDictionary(queryClient, kind)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.people.detail.inline.error')\n flash(message, 'error')\n }\n },\n [kind, onSave, queryClient, t],\n )\n\n return (\n <UiInlineSelectEditor\n label={label}\n value={value}\n emptyLabel={emptyLabel}\n options={selectOptions}\n onSave={handleSave}\n variant={variant}\n activateOnClick={activateOnClick}\n containerClassName={containerClassName}\n triggerClassName={triggerClassName}\n hideLabel={false}\n renderEditor={({ value: selectValue, onChange }) => (\n <>\n <DictionarySelectField\n kind={kind}\n value={selectValue.length ? selectValue : undefined}\n onChange={(next) => onChange(next ?? '')}\n labels={dictionaryLabels}\n selectClassName={selectClassName}\n />\n {dictionaryQuery.isError ? (\n <p className=\"text-xs text-status-error-text\">\n {dictionaryQuery.error instanceof Error\n ? dictionaryQuery.error.message\n : translate('customers.people.form.dictionary.errorLoad', 'Failed to load options')}\n </p>\n ) : null}\n </>\n )}\n renderDisplay={({ value: currentValue }) => {\n if (dictionaryMap) {\n return (\n <DictionaryValue\n value={currentValue}\n map={dictionaryMap}\n fallback={<span className=\"text-sm text-muted-foreground\">{emptyLabel}</span>}\n className=\"text-sm\"\n iconWrapperClassName=\"inline-flex h-6 w-6 items-center justify-center rounded border border-border bg-card\"\n iconClassName=\"h-4 w-4\"\n colorClassName=\"h-3 w-3 rounded-full\"\n />\n )\n }\n if (currentValue && currentValue.length) {\n return <span className=\"break-words text-sm\">{currentValue}</span>\n }\n if (dictionaryQuery.isLoading) {\n return (\n <span className=\"text-sm text-muted-foreground\">\n {translate('customers.people.form.dictionary.loading', 'Loading\u2026')}\n </span>\n )\n }\n return <span className=\"text-sm text-muted-foreground\">{emptyLabel}</span>\n }}\n />\n )\n}\n\nexport type NextInteractionPayload = {\n at: string\n name: string\n refId?: string | null\n icon?: string | null\n color?: string | null\n}\n\ntype NextInteractionEditorProps = {\n label: string\n valueAt: string | null | undefined\n valueName: string | null | undefined\n valueRefId: string | null | undefined\n valueIcon: string | null | undefined\n valueColor: string | null | undefined\n emptyLabel: string\n onSave: (next: NextInteractionPayload | null) => Promise<void>\n activateOnClick?: boolean\n}\n\nexport function InlineNextInteractionEditor({\n label,\n valueAt,\n valueName,\n valueRefId,\n valueIcon,\n valueColor,\n emptyLabel,\n onSave,\n activateOnClick = false,\n}: NextInteractionEditorProps) {\n const t = useT()\n const [editing, setEditing] = React.useState(false)\n const [draftDate, setDraftDate] = React.useState<string>(() => (valueAt ? valueAt.slice(0, 16) : ''))\n const [draftName, setDraftName] = React.useState(valueName ?? '')\n const [draftRefId, setDraftRefId] = React.useState(valueRefId ?? '')\n const [draftIcon, setDraftIcon] = React.useState(valueIcon ?? '')\n const [draftColor, setDraftColor] = React.useState<string | null>(valueColor ?? null)\n const [dateError, setDateError] = React.useState<string | null>(null)\n const [nameError, setNameError] = React.useState<string | null>(null)\n const [submitError, setSubmitError] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n const formRef = React.useRef<HTMLFormElement | null>(null)\n const dateErrorId = React.useId()\n const nameErrorId = React.useId()\n const containerClasses = cn('group relative rounded-lg border p-4', activateOnClick && !editing ? 'cursor-pointer' : null)\n const triggerLabel = editing\n ? t('ui.detail.inline.cancel', 'Cancel')\n : t('ui.detail.inline.edit', 'Edit')\n const requiredMessage = React.useMemo(\n () => t('customers.people.detail.inline.required', 'This field is required'),\n [t],\n )\n\n React.useEffect(() => {\n if (!editing) {\n setDraftDate(valueAt ? valueAt.slice(0, 16) : '')\n setDraftName(valueName ?? '')\n setDraftRefId(valueRefId ?? '')\n setDraftIcon(valueIcon ?? '')\n setDraftColor(valueColor ?? null)\n setDateError(null)\n setNameError(null)\n setSubmitError(null)\n }\n }, [editing, valueAt, valueName, valueRefId, valueIcon, valueColor])\n\n const appearanceLabels = React.useMemo(\n () => ({\n colorLabel: t('customers.people.detail.inline.nextInteractionColorLabel'),\n colorHelp: t('customers.people.detail.inline.nextInteractionColorHelp'),\n colorClearLabel: t('customers.people.detail.inline.nextInteractionColorClear'),\n iconLabel: t('customers.people.detail.inline.nextInteractionIconLabel'),\n iconPlaceholder: t('customers.people.detail.inline.nextInteractionIconPlaceholder'),\n iconPickerTriggerLabel: t('customers.people.detail.inline.nextInteractionIconBrowse'),\n iconSearchPlaceholder: t('customers.people.detail.inline.nextInteractionIconSearchPlaceholder'),\n iconSearchEmptyLabel: t('customers.people.detail.inline.nextInteractionIconSearchEmpty'),\n iconSuggestionsLabel: t('customers.people.detail.inline.nextInteractionIconSuggestions'),\n iconClearLabel: t('customers.people.detail.inline.nextInteractionIconClear'),\n previewEmptyLabel: t('customers.people.detail.inline.nextInteractionAppearanceEmpty'),\n }),\n [t],\n )\n\n const handleSave = React.useCallback(async () => {\n setSubmitError(null)\n setDateError(null)\n setNameError(null)\n const trimmedName = draftName.trim()\n let hasError = false\n if (!draftDate) {\n setDateError(requiredMessage)\n hasError = true\n }\n if (!trimmedName.length) {\n setNameError(requiredMessage)\n hasError = true\n }\n if (hasError) return\n const parsedDate = new Date(draftDate)\n if (Number.isNaN(parsedDate.getTime())) {\n setDateError(t('customers.people.detail.inline.nextInteractionInvalid'))\n return\n }\n const iso = parsedDate.toISOString()\n const trimmedRef = draftRefId.trim()\n const trimmedIcon = draftIcon.trim()\n const normalizedColor = (() => {\n if (!draftColor) return null\n const trimmed = draftColor.trim().toLowerCase()\n return /^#([0-9a-f]{6})$/.test(trimmed) ? trimmed : null\n })()\n setSaving(true)\n try {\n await onSave({\n at: iso,\n name: trimmedName,\n refId: trimmedRef.length ? trimmedRef : null,\n icon: trimmedIcon.length ? trimmedIcon : null,\n color: normalizedColor,\n })\n setEditing(false)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.people.detail.inline.error')\n setSubmitError(message)\n } finally {\n setSaving(false)\n }\n }, [draftColor, draftDate, draftIcon, draftName, draftRefId, onSave, requiredMessage, t])\n\n const handleFormSubmit = React.useCallback(\n (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault()\n if (saving) return\n void handleSave()\n },\n [handleSave, saving],\n )\n\n const handleFormKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLFormElement>) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n setEditing(false)\n return\n }\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n if (saving) return\n try {\n formRef.current?.requestSubmit()\n } catch {\n void handleSave()\n }\n }\n },\n [handleSave, saving],\n )\n\n const handleActivate = React.useCallback(() => {\n if (!editing) setEditing(true)\n }, [editing])\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!activateOnClick || editing) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n handleActivate()\n }\n },\n [activateOnClick, editing, handleActivate],\n )\n\n const handleInteractiveClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (!activateOnClick || editing) return\n const target = event.target as HTMLElement\n const interactiveElement = target.closest('button, input, select, textarea, a, [role=\\\"link\\\"]')\n if (interactiveElement) {\n if (interactiveElement.tagName.toLowerCase() === 'a') {\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {\n return\n }\n event.preventDefault()\n } else {\n return\n }\n }\n handleActivate()\n },\n [activateOnClick, editing, handleActivate],\n )\n\n const interactiveProps: React.HTMLAttributes<HTMLDivElement> =\n activateOnClick && !editing\n ? {\n role: 'button' as const,\n tabIndex: 0,\n onClick: handleInteractiveClick,\n onKeyDown: handleKeyDown,\n }\n : {}\n\n return (\n <div className={containerClasses} onClick={handleInteractiveClick}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className={cn(\n 'absolute right-3 top-3 transition-opacity duration-150',\n editing ? 'opacity-100' : INLINE_TRIGGER_HIDDEN_CLASSES,\n )}\n onClick={(event) => {\n event.stopPropagation()\n setEditing((state) => !state)\n }}\n aria-label={triggerLabel}\n title={triggerLabel}\n >\n {editing ? <X className=\"h-4 w-4\" aria-hidden /> : <Pencil className=\"h-4 w-4\" aria-hidden />}\n </Button>\n <div className=\"flex items-start gap-2\" {...interactiveProps}>\n <div className=\"flex-1\">\n <p className=\"text-xs uppercase tracking-wide text-muted-foreground\">{label}</p>\n {editing ? (\n <form\n ref={formRef}\n className=\"mt-2 space-y-4\"\n onSubmit={handleFormSubmit}\n onKeyDown={handleFormKeyDown}\n >\n <input\n type=\"datetime-local\"\n className={cn(\n 'w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n dateError ? 'border-destructive aria-invalid:border-destructive aria-invalid:ring-destructive' : null,\n )}\n value={draftDate}\n aria-invalid={dateError ? 'true' : undefined}\n aria-required=\"true\"\n aria-describedby={dateError ? dateErrorId : undefined}\n onChange={(event) => {\n if (dateError) setDateError(null)\n if (submitError) setSubmitError(null)\n setDraftDate(event.target.value)\n }}\n />\n {dateError ? (\n <p id={dateErrorId} className=\"text-xs text-destructive\">\n {dateError}\n </p>\n ) : null}\n <input\n placeholder={t('customers.people.detail.inline.nextInteractionName')}\n className={cn(\n 'w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n nameError ? 'border-destructive aria-invalid:border-destructive aria-invalid:ring-destructive' : null,\n )}\n value={draftName}\n aria-invalid={nameError ? 'true' : undefined}\n aria-required=\"true\"\n aria-describedby={nameError ? nameErrorId : undefined}\n onChange={(event) => {\n if (submitError) setSubmitError(null)\n if (nameError) setNameError(null)\n setDraftName(event.target.value)\n }}\n />\n {nameError ? (\n <p id={nameErrorId} className=\"text-xs text-destructive\">\n {nameError}\n </p>\n ) : null}\n <input\n placeholder={t('customers.people.detail.inline.nextInteractionRef')}\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={draftRefId}\n onChange={(event) => {\n if (submitError) setSubmitError(null)\n setDraftRefId(event.target.value)\n }}\n />\n <AppearanceSelector\n icon={draftIcon || null}\n color={draftColor}\n onIconChange={(next) => {\n if (submitError) setSubmitError(null)\n setDraftIcon(next ?? '')\n }}\n onColorChange={(next) => {\n if (submitError) setSubmitError(null)\n setDraftColor(next)\n }}\n iconSuggestions={ICON_SUGGESTIONS}\n disabled={saving}\n labels={appearanceLabels}\n />\n {submitError && !dateError && !nameError ? (\n <p className=\"text-xs text-destructive\">{submitError}</p>\n ) : null}\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button type=\"submit\" size=\"sm\" disabled={saving}>\n {saving ? <Loader2 className=\"mr-2 h-3.5 w-3.5 animate-spin\" /> : null}\n {t('customers.people.detail.inline.saveShortcut', 'Save \u2318\u23CE / Ctrl+Enter')}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => setEditing(false)} disabled={saving}>\n {t('customers.people.detail.inline.cancel')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n onClick={async () => {\n setDraftDate('')\n setDraftName('')\n setDraftRefId('')\n setDraftIcon('')\n setDraftColor(null)\n setDateError(null)\n setNameError(null)\n setSubmitError(null)\n setSaving(true)\n try {\n await onSave(null)\n setEditing(false)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.people.detail.inline.error')\n setSubmitError(message)\n } finally {\n setSaving(false)\n }\n }}\n disabled={saving}\n >\n {t('customers.people.detail.inline.clear')}\n </Button>\n </div>\n </form>\n ) : (\n <div className=\"mt-1 text-sm\">\n {valueAt ? (\n <div className=\"flex items-start gap-3\">\n {valueIcon ? (\n <span className=\"inline-flex h-8 w-8 items-center justify-center rounded border border-border bg-card\">\n {renderDictionaryIcon(valueIcon, 'h-4 w-4')}\n </span>\n ) : null}\n <div className=\"flex-1\">\n <span className=\"block\">{formatDateTime(valueAt)}</span>\n {valueName ? <span className=\"text-xs text-muted-foreground\">{valueName}</span> : null}\n {valueRefId ? <span className=\"text-xs text-muted-foreground\">#{valueRefId}</span> : null}\n </div>\n {valueColor ? renderDictionaryColor(valueColor, 'h-3 w-3 rounded-full border border-border') : null}\n </div>\n ) : (\n <span className=\"text-muted-foreground\">{emptyLabel}</span>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -244,7 +244,7 @@ function PersonHighlights({
|
|
|
244
244
|
setCompanyError(null);
|
|
245
245
|
setCompanyDraftId(activeCompanyId ?? "");
|
|
246
246
|
},
|
|
247
|
-
className: editingCompany ? "opacity-100" : "opacity-0 transition-opacity duration-150 group-hover:opacity-100 hover:opacity-100 focus-visible:opacity-100",
|
|
247
|
+
className: editingCompany ? "opacity-100" : "opacity-0 transition-opacity duration-150 group-hover:opacity-100 hover:opacity-100 focus-visible:opacity-100 [@media(hover:none)]:opacity-100",
|
|
248
248
|
children: [
|
|
249
249
|
editingCompany ? /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4" }),
|
|
250
250
|
/* @__PURE__ */ jsx("span", { className: "sr-only", children: editingCompany ? t("ui.forms.actions.cancel") : t("ui.forms.actions.edit") })
|