@open-mercato/core 0.6.6-develop.6314.1.c7b8291aa2 → 0.6.6-develop.6330.1.a261878aa8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +7 -12
  3. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
  4. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +5 -2
  5. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
  6. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +2 -1
  7. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
  8. package/dist/modules/customer_accounts/widgets/injection/company-users/widget.client.js +2 -1
  9. package/dist/modules/customer_accounts/widgets/injection/company-users/widget.client.js.map +2 -2
  10. package/dist/modules/customers/ai-tools/_shared.js +158 -0
  11. package/dist/modules/customers/ai-tools/_shared.js.map +7 -0
  12. package/dist/modules/customers/ai-tools/companies-pack.js +15 -121
  13. package/dist/modules/customers/ai-tools/companies-pack.js.map +2 -2
  14. package/dist/modules/customers/ai-tools/people-pack.js +9 -107
  15. package/dist/modules/customers/ai-tools/people-pack.js.map +2 -2
  16. package/dist/modules/customers/components/calendar/CalendarScreen.js +1 -0
  17. package/dist/modules/customers/components/calendar/CalendarScreen.js.map +2 -2
  18. package/dist/modules/customers/components/calendar/EventPeekPopover.js +12 -1
  19. package/dist/modules/customers/components/calendar/EventPeekPopover.js.map +2 -2
  20. package/dist/modules/customers/components/calendar/TimeGrid.js +3 -0
  21. package/dist/modules/customers/components/calendar/TimeGrid.js.map +2 -2
  22. package/dist/modules/customers/components/calendar/types.js.map +1 -1
  23. package/dist/modules/customers/components/detail/EntityTagsDialog.js +76 -67
  24. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +3 -3
  25. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +4 -3
  26. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  27. package/dist/modules/data_sync/api/runs.js +1 -0
  28. package/dist/modules/data_sync/api/runs.js.map +2 -2
  29. package/dist/modules/data_sync/backend/data-sync/page.js +3 -1
  30. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  31. package/dist/modules/data_sync/data/validators.js +1 -0
  32. package/dist/modules/data_sync/data/validators.js.map +2 -2
  33. package/dist/modules/data_sync/lib/sync-run-service.js +20 -0
  34. package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
  35. package/dist/modules/entities/api/records.js +11 -1
  36. package/dist/modules/entities/api/records.js.map +2 -2
  37. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +17 -10
  38. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  39. package/dist/modules/messages/api/unread-count/route.js +32 -0
  40. package/dist/modules/messages/api/unread-count/route.js.map +2 -2
  41. package/dist/modules/query_index/components/QueryIndexesTable.js +13 -5
  42. package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
  43. package/dist/modules/shipping_carriers/i18n/en.js +11 -1
  44. package/dist/modules/shipping_carriers/i18n/en.js.map +2 -2
  45. package/dist/modules/shipping_carriers/i18n/pl.js +11 -1
  46. package/dist/modules/shipping_carriers/i18n/pl.js.map +2 -2
  47. package/dist/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.client.js +25 -0
  48. package/dist/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.client.js.map +7 -0
  49. package/dist/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.js +3 -17
  50. package/dist/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.js.map +2 -2
  51. package/dist/modules/translations/widgets/injection/translation-manager/widget.client.js +19 -14
  52. package/dist/modules/translations/widgets/injection/translation-manager/widget.client.js.map +2 -2
  53. package/package.json +7 -7
  54. package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +7 -10
  55. package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +6 -7
  56. package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +3 -2
  57. package/src/modules/customer_accounts/widgets/injection/company-users/widget.client.tsx +3 -2
  58. package/src/modules/customers/ai-tools/_shared.ts +270 -0
  59. package/src/modules/customers/ai-tools/companies-pack.ts +17 -157
  60. package/src/modules/customers/ai-tools/people-pack.ts +11 -133
  61. package/src/modules/customers/components/calendar/CalendarScreen.tsx +1 -0
  62. package/src/modules/customers/components/calendar/EventPeekPopover.tsx +29 -11
  63. package/src/modules/customers/components/calendar/TimeGrid.tsx +3 -0
  64. package/src/modules/customers/components/calendar/types.ts +1 -0
  65. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +89 -71
  66. package/src/modules/customers/i18n/de.json +1 -0
  67. package/src/modules/customers/i18n/en.json +1 -0
  68. package/src/modules/customers/i18n/es.json +1 -0
  69. package/src/modules/customers/i18n/pl.json +1 -0
  70. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +6 -3
  71. package/src/modules/data_sync/api/runs.ts +1 -0
  72. package/src/modules/data_sync/backend/data-sync/page.tsx +3 -1
  73. package/src/modules/data_sync/data/validators.ts +1 -0
  74. package/src/modules/data_sync/i18n/de.json +1 -0
  75. package/src/modules/data_sync/i18n/en.json +1 -0
  76. package/src/modules/data_sync/i18n/es.json +1 -0
  77. package/src/modules/data_sync/i18n/pl.json +1 -0
  78. package/src/modules/data_sync/lib/sync-run-service.ts +23 -0
  79. package/src/modules/entities/api/records.ts +17 -1
  80. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +25 -12
  81. package/src/modules/messages/api/unread-count/route.ts +40 -0
  82. package/src/modules/query_index/components/QueryIndexesTable.tsx +17 -15
  83. package/src/modules/shipping_carriers/i18n/de.json +11 -1
  84. package/src/modules/shipping_carriers/i18n/en.json +11 -1
  85. package/src/modules/shipping_carriers/i18n/en.ts +10 -0
  86. package/src/modules/shipping_carriers/i18n/es.json +11 -1
  87. package/src/modules/shipping_carriers/i18n/pl.json +11 -1
  88. package/src/modules/shipping_carriers/i18n/pl.ts +10 -0
  89. package/src/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.client.tsx +35 -0
  90. package/src/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.tsx +3 -22
  91. package/src/modules/translations/widgets/injection/translation-manager/widget.client.tsx +30 -13
@@ -316,47 +316,43 @@ function EntityTagsDialog({
316
316
  const loadData = React.useCallback(async () => {
317
317
  setLoading(true);
318
318
  try {
319
- let kindSettings = [];
320
319
  const scopedQuery = new URLSearchParams();
321
320
  if (entityOrganizationId) {
322
321
  scopedQuery.set("organizationId", entityOrganizationId);
323
322
  }
324
- try {
325
- const settingsCall = await apiCall(
326
- `/api/customers/dictionaries/kind-settings${scopedQuery.size ? `?${scopedQuery.toString()}` : ""}`,
327
- { cache: "no-store", headers: { "x-om-unauthorized-redirect": "0" } }
328
- );
329
- if (settingsCall.ok && settingsCall.result?.items) {
330
- kindSettings = settingsCall.result.items;
331
- }
332
- } catch {
333
- }
334
- const settingsMap = new Map(kindSettings.map((setting) => [setting.kind, setting]));
335
- const selectedTagEntries = Array.isArray(entityData.tags) ? entityData.tags.map((tag) => ({
336
- id: tag.id,
337
- value: tag.id,
338
- label: tag.label,
339
- color: tag.color ?? null
340
- })) : [];
341
- let assignedLabelIds = [];
342
- let selectedLabelEntries = [];
343
- try {
344
- const labelsQuery = new URLSearchParams();
345
- labelsQuery.set("entityId", entityId);
346
- labelsQuery.set("pageSize", "1");
347
- if (entityOrganizationId) {
348
- labelsQuery.set("organizationId", entityOrganizationId);
323
+ const loadKindSettings = async () => {
324
+ try {
325
+ const settingsCall = await apiCall(
326
+ `/api/customers/dictionaries/kind-settings${scopedQuery.size ? `?${scopedQuery.toString()}` : ""}`,
327
+ { cache: "no-store", headers: { "x-om-unauthorized-redirect": "0" } }
328
+ );
329
+ if (settingsCall.ok && settingsCall.result?.items) {
330
+ return settingsCall.result.items;
331
+ }
332
+ } catch {
349
333
  }
350
- const labelsCall = await apiCall(`/api/customers/labels?${labelsQuery.toString()}`, {
351
- cache: "no-store",
352
- headers: { "x-om-unauthorized-redirect": "0" }
353
- });
354
- const labelsData = labelsCall.ok ? labelsCall.result : null;
355
- assignedLabelIds = labelsData?.assignedIds ?? [];
356
- if (assignedLabelIds.length > 0) {
334
+ return [];
335
+ };
336
+ const loadLabelData = async () => {
337
+ try {
338
+ const labelsQuery = new URLSearchParams();
339
+ labelsQuery.set("entityId", entityId);
340
+ labelsQuery.set("pageSize", "1");
341
+ if (entityOrganizationId) {
342
+ labelsQuery.set("organizationId", entityOrganizationId);
343
+ }
344
+ const labelsCall = await apiCall(`/api/customers/labels?${labelsQuery.toString()}`, {
345
+ cache: "no-store",
346
+ headers: { "x-om-unauthorized-redirect": "0" }
347
+ });
348
+ const labelsData = labelsCall.ok ? labelsCall.result : null;
349
+ const assignedLabelIds2 = labelsData?.assignedIds ?? [];
350
+ if (assignedLabelIds2.length === 0) {
351
+ return { assignedLabelIds: assignedLabelIds2, selectedLabelEntries: [] };
352
+ }
357
353
  const detailQuery = new URLSearchParams({
358
- ids: assignedLabelIds.join(","),
359
- pageSize: String(Math.min(assignedLabelIds.length, 100))
354
+ ids: assignedLabelIds2.join(","),
355
+ pageSize: String(Math.min(assignedLabelIds2.length, 100))
360
356
  });
361
357
  if (entityOrganizationId) {
362
358
  detailQuery.set("organizationId", entityOrganizationId);
@@ -369,40 +365,28 @@ function EntityTagsDialog({
369
365
  }
370
366
  );
371
367
  const selectedLabels = selectedLabelsCall.ok ? selectedLabelsCall.result?.items ?? [] : [];
372
- selectedLabelEntries = selectedLabels.map((label) => ({
368
+ const selectedLabelEntries2 = selectedLabels.map((label) => ({
373
369
  id: label.id,
374
370
  value: label.id,
375
371
  label: label.label,
376
372
  color: null
377
373
  }));
374
+ return { assignedLabelIds: assignedLabelIds2, selectedLabelEntries: selectedLabelEntries2 };
375
+ } catch {
376
+ return { assignedLabelIds: [], selectedLabelEntries: [] };
378
377
  }
379
- } catch {
380
- assignedLabelIds = [];
381
- selectedLabelEntries = [];
382
- }
378
+ };
379
+ const selectedTagEntries = Array.isArray(entityData.tags) ? entityData.tags.map((tag) => ({
380
+ id: tag.id,
381
+ value: tag.id,
382
+ label: tag.label,
383
+ color: tag.color ?? null
384
+ })) : [];
385
+ const labelDataPromise = loadLabelData();
386
+ const kindSettings = await loadKindSettings();
387
+ const settingsMap = new Map(kindSettings.map((setting) => [setting.kind, setting]));
383
388
  const categoryDefs = buildApplicableCategories(entityType, kindSettings);
384
- const loadedCategories = [];
385
- for (const categoryDef of categoryDefs) {
386
- if (categoryDef.source === "tags") {
387
- loadedCategories.push({
388
- ...categoryDef,
389
- label: t(categoryDef.labelKey, categoryDef.labelFallback),
390
- description: t(categoryDef.descriptionKey, categoryDef.descriptionFallback),
391
- entries: sortOptions(selectedTagEntries),
392
- selectionMode: categoryDef.selectionMode ?? "multi"
393
- });
394
- continue;
395
- }
396
- if (categoryDef.source === "labels") {
397
- loadedCategories.push({
398
- ...categoryDef,
399
- label: t(categoryDef.labelKey, categoryDef.labelFallback),
400
- description: t(categoryDef.descriptionKey, categoryDef.descriptionFallback),
401
- entries: sortOptions(selectedLabelEntries),
402
- selectionMode: categoryDef.selectionMode ?? "multi"
403
- });
404
- continue;
405
- }
389
+ const loadDictionaryCategory = async (categoryDef) => {
406
390
  try {
407
391
  const dictionaryUrl = new URL(`/api/customers/dictionaries/${categoryDef.routeKind}`, "http://localhost");
408
392
  if (entityOrganizationId) {
@@ -431,7 +415,7 @@ function EntityTagsDialog({
431
415
  color: null
432
416
  });
433
417
  });
434
- loadedCategories.push({
418
+ return {
435
419
  ...categoryDef,
436
420
  label: categoryDef.labelKey ? t(categoryDef.labelKey, categoryDef.labelFallback) : categoryDef.labelFallback,
437
421
  description: categoryDef.descriptionKey ? t(
@@ -441,7 +425,7 @@ function EntityTagsDialog({
441
425
  ) : categoryDef.descriptionFallback,
442
426
  entries: sortOptions(entries),
443
427
  selectionMode
444
- });
428
+ };
445
429
  } catch {
446
430
  const setting = categoryDef.settingKind ? settingsMap.get(categoryDef.settingKind) : void 0;
447
431
  const selectionMode = setting?.selectionMode ?? categoryDef.selectionMode ?? "single";
@@ -451,7 +435,7 @@ function EntityTagsDialog({
451
435
  label: value,
452
436
  color: null
453
437
  }));
454
- loadedCategories.push({
438
+ return {
455
439
  ...categoryDef,
456
440
  label: categoryDef.labelKey ? t(categoryDef.labelKey, categoryDef.labelFallback) : categoryDef.labelFallback,
457
441
  description: categoryDef.descriptionKey ? t(
@@ -461,9 +445,34 @@ function EntityTagsDialog({
461
445
  ) : categoryDef.descriptionFallback,
462
446
  entries: fallbackEntries,
463
447
  selectionMode
464
- });
448
+ };
465
449
  }
466
- }
450
+ };
451
+ const loadedCategories = await Promise.all(
452
+ categoryDefs.map(async (categoryDef) => {
453
+ if (categoryDef.source === "tags") {
454
+ return {
455
+ ...categoryDef,
456
+ label: t(categoryDef.labelKey, categoryDef.labelFallback),
457
+ description: t(categoryDef.descriptionKey, categoryDef.descriptionFallback),
458
+ entries: sortOptions(selectedTagEntries),
459
+ selectionMode: categoryDef.selectionMode ?? "multi"
460
+ };
461
+ }
462
+ if (categoryDef.source === "labels") {
463
+ const { selectedLabelEntries: selectedLabelEntries2 } = await labelDataPromise;
464
+ return {
465
+ ...categoryDef,
466
+ label: t(categoryDef.labelKey, categoryDef.labelFallback),
467
+ description: t(categoryDef.descriptionKey, categoryDef.descriptionFallback),
468
+ entries: sortOptions(selectedLabelEntries2),
469
+ selectionMode: categoryDef.selectionMode ?? "multi"
470
+ };
471
+ }
472
+ return loadDictionaryCategory(categoryDef);
473
+ })
474
+ );
475
+ const { assignedLabelIds, selectedLabelEntries } = await labelDataPromise;
467
476
  loadedCategories.sort((left, right) => {
468
477
  const leftSortOrder = left.settingKind && settingsMap.has(left.settingKind) ? settingsMap.get(left.settingKind)?.sortOrder ?? 1e3 : 1e3 + CATEGORY_DEFS.findIndex((category) => category.kind === left.kind);
469
478
  const rightSortOrder = right.settingKind && settingsMap.has(right.settingKind) ? settingsMap.get(right.settingKind)?.sortOrder ?? 1e3 : 1e3 + CATEGORY_DEFS.findIndex((category) => category.kind === right.kind);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/components/detail/EntityTagsDialog.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Check, Plus, Search, SearchX, SlidersHorizontal, Tag, X } from 'lucide-react'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { VisuallyHidden } from '@radix-ui/react-visually-hidden'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn, slugifyTagLabel } from '@open-mercato/shared/lib/utils'\nimport { apiCall, apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport {\n Dialog,\n DialogContent,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport type { TagSummary } from './types'\nimport { ManageTagsDialog } from './ManageTagsDialog'\n\ntype DictEntry = { id: string; value: string; label: string; color?: string | null }\n\ntype LabelItem = { id: string; slug: string; label: string }\n\ntype KindSetting = {\n kind: string\n selectionMode: 'single' | 'multi'\n visibleInTags: boolean\n sortOrder: number\n}\n\ntype CategorySource = 'dictionary' | 'tags' | 'labels'\n\ntype EntityTagData = {\n status?: string | null\n lifecycleStage?: string | null\n source?: string | null\n temperature?: string | null\n renewalQuarter?: string | null\n jobTitle?: string | null\n industry?: string | null\n customFields?: Record<string, unknown>\n tags?: TagSummary[]\n}\n\ntype CategoryOption = {\n id: string\n value: string\n label: string\n color?: string | null\n}\n\ntype CategoryDef = {\n kind: string\n source: CategorySource\n supportedEntityTypes: Array<'person' | 'company'>\n labelKey: string\n labelFallback: string\n descriptionKey: string\n descriptionFallback: string\n routeKind?: string\n settingKind?: string\n entityField?: keyof EntityTagData\n customFieldKey?: string\n selectionMode?: 'single' | 'multi'\n hasColorDots: boolean\n supportsCreate?: boolean\n}\n\ntype CategorySection = CategoryDef & {\n label: string\n description: string\n entries: CategoryOption[]\n selectionMode: 'single' | 'multi'\n}\n\nexport type EntityTagsDialogProps = {\n open: boolean\n onClose: () => void\n entityId: string\n entityType: 'person' | 'company'\n entityOrganizationId: string | null\n entityData: EntityTagData\n onSaved?: () => void\n}\n\nconst CATEGORY_DEFS: CategoryDef[] = [\n {\n kind: 'tags',\n source: 'tags',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.tags',\n labelFallback: 'Tags',\n descriptionKey: 'customers.personTags.description.tags',\n descriptionFallback: 'Shared CRM tags that can be assigned to many records.',\n selectionMode: 'multi',\n hasColorDots: true,\n supportsCreate: true,\n },\n {\n kind: 'labels',\n source: 'labels',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.labels',\n labelFallback: 'Labels',\n descriptionKey: 'customers.personTags.description.labels',\n descriptionFallback: 'Quick labels you can create inline for this record.',\n selectionMode: 'multi',\n hasColorDots: false,\n supportsCreate: true,\n },\n {\n kind: 'statuses',\n source: 'dictionary',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.statuses',\n labelFallback: 'Status',\n descriptionKey: 'customers.personTags.description.statuses',\n descriptionFallback: 'Primary CRM status shown in the header badges.',\n routeKind: 'statuses',\n settingKind: 'status',\n entityField: 'status',\n selectionMode: 'single',\n hasColorDots: true,\n },\n {\n kind: 'lifecycle-stages',\n source: 'dictionary',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.lifecycle-stages',\n labelFallback: 'Lifecycle',\n descriptionKey: 'customers.personTags.description.lifecycleStages',\n descriptionFallback: 'Lifecycle stage used across CRM detail views.',\n routeKind: 'lifecycle-stages',\n settingKind: 'lifecycle_stage',\n entityField: 'lifecycleStage',\n selectionMode: 'single',\n hasColorDots: true,\n },\n {\n kind: 'sources',\n source: 'dictionary',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.sources',\n labelFallback: 'Source',\n descriptionKey: 'customers.personTags.description.sources',\n descriptionFallback: 'How this record entered the pipeline.',\n routeKind: 'sources',\n settingKind: 'source',\n entityField: 'source',\n selectionMode: 'single',\n hasColorDots: true,\n },\n {\n kind: 'temperature',\n source: 'dictionary',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.temperature',\n labelFallback: 'Temperature',\n descriptionKey: 'customers.personTags.description.temperature',\n descriptionFallback: 'Sales temperature or engagement level.',\n routeKind: 'temperature',\n settingKind: 'temperature',\n entityField: 'temperature',\n selectionMode: 'single',\n hasColorDots: true,\n },\n {\n kind: 'renewal-quarters',\n source: 'dictionary',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.renewal-quarters',\n labelFallback: 'Renewal quarter',\n descriptionKey: 'customers.personTags.description.renewalQuarters',\n descriptionFallback: 'Quarter used for renewal planning and badges.',\n routeKind: 'renewal-quarters',\n settingKind: 'renewal_quarter',\n entityField: 'renewalQuarter',\n selectionMode: 'single',\n hasColorDots: true,\n },\n {\n kind: 'job-titles',\n source: 'dictionary',\n supportedEntityTypes: ['person'],\n labelKey: 'customers.personTags.category.job-titles',\n labelFallback: 'Job title',\n descriptionKey: 'customers.personTags.description.jobTitles',\n descriptionFallback: 'The role or title used for this person.',\n routeKind: 'job-titles',\n settingKind: 'job_title',\n entityField: 'jobTitle',\n selectionMode: 'single',\n hasColorDots: true,\n },\n {\n kind: 'industries',\n source: 'dictionary',\n supportedEntityTypes: ['company'],\n labelKey: 'customers.personTags.category.industries',\n labelFallback: 'Industry',\n descriptionKey: 'customers.personTags.description.industries',\n descriptionFallback: 'The industry used to classify this company.',\n routeKind: 'industries',\n settingKind: 'industry',\n entityField: 'industry',\n selectionMode: 'single',\n hasColorDots: true,\n },\n]\n\nconst REMOTE_CATEGORY_PAGE_SIZE = 50\nconst CUSTOM_CATEGORY_FIELD_PREFIX = 'crmTagCategory:'\n\nfunction cloneSelectionMap(values: Record<string, Set<string>>): Record<string, Set<string>> {\n return Object.fromEntries(\n Object.entries(values).map(([key, selection]) => [key, new Set(selection)]),\n )\n}\n\nfunction sortOptions(entries: CategoryOption[]): CategoryOption[] {\n return [...entries].sort((left, right) =>\n left.label.localeCompare(right.label, undefined, { sensitivity: 'base' }),\n )\n}\n\nfunction mergeOptions(...groups: CategoryOption[][]): CategoryOption[] {\n const merged = new Map<string, CategoryOption>()\n groups.flat().forEach((entry) => {\n merged.set(entry.value, entry)\n })\n return sortOptions(Array.from(merged.values()))\n}\n\nfunction humanizeCategoryKind(kind: string): string {\n return kind\n .split(/[-_]+/)\n .filter((part) => part.trim().length > 0)\n .map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)\n .join(' ')\n}\n\nfunction resolveCustomCategoryFieldKey(kind: string): string {\n return `${CUSTOM_CATEGORY_FIELD_PREFIX}${kind}`\n}\n\nfunction createCustomCategoryDef(kind: string, selectionMode: 'single' | 'multi'): CategoryDef {\n const label = humanizeCategoryKind(kind)\n return {\n kind,\n source: 'dictionary',\n supportedEntityTypes: ['person', 'company'],\n labelKey: '',\n labelFallback: label,\n descriptionKey: 'customers.personTags.description.customCategory',\n descriptionFallback: `Custom CRM category: ${label}.`,\n routeKind: kind,\n settingKind: kind,\n customFieldKey: resolveCustomCategoryFieldKey(kind),\n selectionMode,\n hasColorDots: true,\n }\n}\n\nfunction normalizeSelectionValues(\n value: unknown,\n selectionMode: 'single' | 'multi',\n): string[] {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n return trimmed.length > 0 ? [trimmed] : []\n }\n if (Array.isArray(value)) {\n const normalized = value\n .filter((entry): entry is string => typeof entry === 'string')\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0)\n if (selectionMode === 'single') {\n return normalized.length > 0 ? [normalized[0]] : []\n }\n return normalized\n }\n return []\n}\n\nfunction readCategorySelectionValues(\n category: CategoryDef,\n entityData: EntityTagData,\n selectionMode: 'single' | 'multi',\n): string[] {\n if (category.entityField) {\n return normalizeSelectionValues(entityData[category.entityField], selectionMode)\n }\n if (category.customFieldKey) {\n return normalizeSelectionValues(entityData.customFields?.[category.customFieldKey], selectionMode)\n }\n return []\n}\n\nfunction areSelectionsEqual(left: Set<string>, right: Set<string>): boolean {\n if (left.size !== right.size) return false\n for (const value of left) {\n if (!right.has(value)) return false\n }\n return true\n}\n\nfunction TagChip({\n label,\n color,\n active,\n showColorDot,\n onClick,\n}: {\n label: string\n color?: string | null\n active: boolean\n showColorDot: boolean\n onClick: () => void\n}) {\n const activeColorStyle: React.CSSProperties | undefined =\n active && color\n ? { color, borderColor: color, backgroundColor: `${color}1A` }\n : undefined\n return (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={onClick}\n className={cn(\n 'inline-flex h-auto items-center gap-1 rounded-full border px-2.5 py-1.5 transition-colors',\n active\n ? activeColorStyle\n ? 'font-semibold hover:opacity-90'\n : 'border-transparent bg-muted font-semibold text-foreground hover:bg-muted'\n : 'border-border bg-transparent font-normal text-muted-foreground hover:bg-muted/60 hover:text-foreground',\n )}\n style={activeColorStyle}\n >\n {showColorDot && color ? (\n <span\n className=\"inline-block size-2 shrink-0 rounded-full\"\n style={{ backgroundColor: color }}\n />\n ) : null}\n <span className=\"text-xs\">{label}</span>\n {active ? <X className=\"size-2.5 shrink-0\" /> : null}\n </Button>\n )\n}\n\nfunction buildApplicableCategories(\n entityType: 'person' | 'company',\n kindSettings: KindSetting[],\n) {\n const baseCategories = CATEGORY_DEFS.filter((category) => category.supportedEntityTypes.includes(entityType))\n const customCategories = kindSettings\n .filter((setting) => setting.visibleInTags)\n .filter((setting) => !CATEGORY_DEFS.some((category) => category.kind === setting.kind || category.settingKind === setting.kind))\n .map((setting) => createCustomCategoryDef(setting.kind, setting.selectionMode))\n return [...baseCategories, ...customCategories]\n}\n\nexport function EntityTagsDialog({\n open,\n onClose,\n entityId,\n entityType,\n entityOrganizationId,\n entityData,\n onSaved,\n}: EntityTagsDialogProps) {\n const t = useT()\n const [loading, setLoading] = React.useState(true)\n const [saving, setSaving] = React.useState(false)\n const [searchValue, setSearchValue] = React.useState('')\n const [categories, setCategories] = React.useState<CategorySection[]>([])\n const [selectedEntrySeeds, setSelectedEntrySeeds] = React.useState<Record<string, CategoryOption[]>>({})\n const [selectedValues, setSelectedValues] = React.useState<Record<string, Set<string>>>({})\n const [originalValues, setOriginalValues] = React.useState<Record<string, Set<string>>>({})\n const [activeCategoryKind, setActiveCategoryKind] = React.useState<string | null>(null)\n const [newEntryInputByKind, setNewEntryInputByKind] = React.useState<Record<string, string | null>>({})\n const [creatingKind, setCreatingKind] = React.useState<string | null>(null)\n const [manageTagsOpen, setManageTagsOpen] = React.useState(false)\n const [activeCategoryPage, setActiveCategoryPage] = React.useState(1)\n const [activeCategoryTotalPages, setActiveCategoryTotalPages] = React.useState(1)\n const [activeCategoryLoading, setActiveCategoryLoading] = React.useState(false)\n const creationInFlightRef = React.useRef<string | null>(null)\n const mutationContextId = React.useMemo(\n () => `customer-tags:${entityType}:${entityId}`,\n [entityId, entityType],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n entityType: 'person' | 'company'\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const mutationContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n resourceKind: entityType === 'person' ? 'customers.person' : 'customers.company',\n resourceId: entityId,\n entityType,\n retryLastMutation,\n }),\n [entityId, entityType, mutationContextId, retryLastMutation],\n )\n const runGuardedMutation = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload: Record<string, unknown>) =>\n runMutation({\n operation,\n mutationPayload,\n context: mutationContext,\n }),\n [mutationContext, runMutation],\n )\n\n const updateCategoryEntries = React.useCallback(\n (kind: string, updater: (entries: CategoryOption[]) => CategoryOption[]) => {\n setCategories((previous) =>\n previous.map((category) =>\n category.kind === kind\n ? { ...category, entries: sortOptions(updater(category.entries)) }\n : category,\n ),\n )\n },\n [],\n )\n\n const loadData = React.useCallback(async () => {\n setLoading(true)\n try {\n let kindSettings: KindSetting[] = []\n const scopedQuery = new URLSearchParams()\n if (entityOrganizationId) {\n scopedQuery.set('organizationId', entityOrganizationId)\n }\n try {\n const settingsCall = await apiCall<{ items?: KindSetting[] }>(\n `/api/customers/dictionaries/kind-settings${scopedQuery.size ? `?${scopedQuery.toString()}` : ''}`,\n { cache: 'no-store', headers: { 'x-om-unauthorized-redirect': '0' } },\n )\n if (settingsCall.ok && settingsCall.result?.items) {\n kindSettings = settingsCall.result.items\n }\n } catch {\n // Default category order works without explicit settings rows.\n }\n\n const settingsMap = new Map(kindSettings.map((setting) => [setting.kind, setting]))\n\n const selectedTagEntries = Array.isArray(entityData.tags)\n ? entityData.tags.map((tag) => ({\n id: tag.id,\n value: tag.id,\n label: tag.label,\n color: tag.color ?? null,\n }))\n : []\n\n let assignedLabelIds: string[] = []\n let selectedLabelEntries: CategoryOption[] = []\n try {\n const labelsQuery = new URLSearchParams()\n labelsQuery.set('entityId', entityId)\n labelsQuery.set('pageSize', '1')\n if (entityOrganizationId) {\n labelsQuery.set('organizationId', entityOrganizationId)\n }\n const labelsCall = await apiCall<{\n items?: LabelItem[]\n assignedIds?: string[]\n }>(`/api/customers/labels?${labelsQuery.toString()}`, {\n cache: 'no-store',\n headers: { 'x-om-unauthorized-redirect': '0' },\n })\n const labelsData = labelsCall.ok ? labelsCall.result : null\n assignedLabelIds = labelsData?.assignedIds ?? []\n if (assignedLabelIds.length > 0) {\n const detailQuery = new URLSearchParams({\n ids: assignedLabelIds.join(','),\n pageSize: String(Math.min(assignedLabelIds.length, 100)),\n })\n if (entityOrganizationId) {\n detailQuery.set('organizationId', entityOrganizationId)\n }\n const selectedLabelsCall = await apiCall<{ items?: LabelItem[] }>(\n `/api/customers/labels?${detailQuery.toString()}`,\n {\n cache: 'no-store',\n headers: { 'x-om-unauthorized-redirect': '0' },\n },\n )\n const selectedLabels = selectedLabelsCall.ok ? selectedLabelsCall.result?.items ?? [] : []\n selectedLabelEntries = selectedLabels.map((label) => ({\n id: label.id,\n value: label.id,\n label: label.label,\n color: null,\n }))\n }\n } catch {\n assignedLabelIds = []\n selectedLabelEntries = []\n }\n\n const categoryDefs = buildApplicableCategories(entityType, kindSettings)\n const loadedCategories: CategorySection[] = []\n\n for (const categoryDef of categoryDefs) {\n if (categoryDef.source === 'tags') {\n loadedCategories.push({\n ...categoryDef,\n label: t(categoryDef.labelKey, categoryDef.labelFallback),\n description: t(categoryDef.descriptionKey, categoryDef.descriptionFallback),\n entries: sortOptions(selectedTagEntries),\n selectionMode: categoryDef.selectionMode ?? 'multi',\n })\n continue\n }\n\n if (categoryDef.source === 'labels') {\n loadedCategories.push({\n ...categoryDef,\n label: t(categoryDef.labelKey, categoryDef.labelFallback),\n description: t(categoryDef.descriptionKey, categoryDef.descriptionFallback),\n entries: sortOptions(selectedLabelEntries),\n selectionMode: categoryDef.selectionMode ?? 'multi',\n })\n continue\n }\n\n try {\n const dictionaryUrl = new URL(`/api/customers/dictionaries/${categoryDef.routeKind}`, 'http://localhost')\n if (entityOrganizationId) {\n dictionaryUrl.searchParams.set('organizationId', entityOrganizationId)\n }\n const dictionaryCall = await apiCall<{ items?: DictEntry[] }>(\n `${dictionaryUrl.pathname}${dictionaryUrl.search}`,\n { cache: 'no-store', headers: { 'x-om-unauthorized-redirect': '0' } },\n )\n const dictionaryItems = dictionaryCall.ok ? dictionaryCall.result?.items ?? [] : []\n const entries = dictionaryItems.map((entry) => ({\n id: entry.id,\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n }))\n const setting = categoryDef.settingKind\n ? settingsMap.get(categoryDef.settingKind)\n : undefined\n const selectionMode = setting?.selectionMode ?? categoryDef.selectionMode ?? 'single'\n const currentValues = readCategorySelectionValues(categoryDef, entityData, selectionMode)\n currentValues.forEach((currentValue) => {\n if (entries.some((entry) => entry.value === currentValue)) return\n entries.push({\n id: `current:${categoryDef.kind}:${currentValue}`,\n value: currentValue,\n label: currentValue,\n color: null,\n })\n })\n loadedCategories.push({\n ...categoryDef,\n label: categoryDef.labelKey\n ? t(categoryDef.labelKey, categoryDef.labelFallback)\n : categoryDef.labelFallback,\n description: categoryDef.descriptionKey\n ? t(\n categoryDef.descriptionKey,\n categoryDef.descriptionFallback,\n categoryDef.customFieldKey ? { name: categoryDef.labelFallback } : undefined,\n )\n : categoryDef.descriptionFallback,\n entries: sortOptions(entries),\n selectionMode,\n })\n } catch {\n const setting = categoryDef.settingKind\n ? settingsMap.get(categoryDef.settingKind)\n : undefined\n const selectionMode = setting?.selectionMode ?? categoryDef.selectionMode ?? 'single'\n const fallbackEntries = readCategorySelectionValues(categoryDef, entityData, selectionMode).map((value) => ({\n id: `current:${categoryDef.kind}:${value}`,\n value,\n label: value,\n color: null,\n }))\n loadedCategories.push({\n ...categoryDef,\n label: categoryDef.labelKey\n ? t(categoryDef.labelKey, categoryDef.labelFallback)\n : categoryDef.labelFallback,\n description: categoryDef.descriptionKey\n ? t(\n categoryDef.descriptionKey,\n categoryDef.descriptionFallback,\n categoryDef.customFieldKey ? { name: categoryDef.labelFallback } : undefined,\n )\n : categoryDef.descriptionFallback,\n entries: fallbackEntries,\n selectionMode,\n })\n }\n }\n\n loadedCategories.sort((left, right) => {\n const leftSortOrder =\n left.settingKind && settingsMap.has(left.settingKind)\n ? settingsMap.get(left.settingKind)?.sortOrder ?? 1000\n : 1000 + CATEGORY_DEFS.findIndex((category) => category.kind === left.kind)\n const rightSortOrder =\n right.settingKind && settingsMap.has(right.settingKind)\n ? settingsMap.get(right.settingKind)?.sortOrder ?? 1000\n : 1000 + CATEGORY_DEFS.findIndex((category) => category.kind === right.kind)\n return leftSortOrder - rightSortOrder\n })\n\n const initialValues: Record<string, Set<string>> = {}\n for (const category of loadedCategories) {\n if (category.source === 'dictionary' && (category.entityField || category.customFieldKey)) {\n initialValues[category.kind] = new Set(\n readCategorySelectionValues(category, entityData, category.selectionMode),\n )\n continue\n }\n if (category.source === 'tags') {\n const availableTagIds = new Set(category.entries.map((entry) => entry.value))\n const assignedTagIds = Array.isArray(entityData.tags)\n ? entityData.tags\n .map((tag) => tag.id)\n .filter((tagId) => availableTagIds.has(tagId))\n : []\n initialValues[category.kind] = new Set(assignedTagIds)\n continue\n }\n if (category.source === 'labels') {\n const availableLabelIds = new Set(category.entries.map((entry) => entry.value))\n initialValues[category.kind] = new Set(\n assignedLabelIds.filter((labelId) => availableLabelIds.has(labelId)),\n )\n continue\n }\n initialValues[category.kind] = new Set()\n }\n\n setCategories(loadedCategories)\n setSelectedEntrySeeds({\n tags: selectedTagEntries,\n labels: selectedLabelEntries,\n })\n setSelectedValues(initialValues)\n setOriginalValues(cloneSelectionMap(initialValues))\n setActiveCategoryKind((previous) => {\n if (previous && loadedCategories.some((category) => category.kind === previous)) {\n return previous\n }\n return loadedCategories[0]?.kind ?? null\n })\n } finally {\n setLoading(false)\n }\n }, [entityData, entityId, entityOrganizationId, entityType, t])\n\n React.useEffect(() => {\n if (!open) return\n setSearchValue('')\n setNewEntryInputByKind({})\n loadData().catch((err) => console.warn('[EntityTagsDialog] loadData failed', err))\n }, [loadData, open])\n\n React.useEffect(() => {\n if (open) return\n setManageTagsOpen(false)\n }, [open])\n\n const activeCategory = React.useMemo(() => {\n if (!categories.length) return null\n return categories.find((category) => category.kind === activeCategoryKind) ?? categories[0]\n }, [activeCategoryKind, categories])\n const activeCategoryKindValue = activeCategory?.kind ?? null\n const activeCategorySource = activeCategory?.source ?? null\n\n React.useEffect(() => {\n if (!open) return\n setActiveCategoryPage(1)\n }, [activeCategoryKind, open, searchValue])\n\n React.useEffect(() => {\n if (!open || !activeCategoryKindValue || (activeCategorySource !== 'tags' && activeCategorySource !== 'labels')) {\n setActiveCategoryLoading(false)\n setActiveCategoryTotalPages(1)\n return\n }\n\n let cancelled = false\n const params = new URLSearchParams({\n page: String(activeCategoryPage),\n pageSize: String(REMOTE_CATEGORY_PAGE_SIZE),\n })\n if (searchValue.trim().length > 0) {\n params.set('search', searchValue.trim())\n }\n if (activeCategorySource === 'labels') {\n params.set('entityId', entityId)\n if (entityOrganizationId) {\n params.set('organizationId', entityOrganizationId)\n }\n }\n\n const endpoint =\n activeCategorySource === 'tags'\n ? `/api/customers/tags?${params.toString()}`\n : `/api/customers/labels?${params.toString()}`\n const seedEntries = searchValue.trim().length > 0 ? [] : selectedEntrySeeds[activeCategoryKindValue] ?? []\n\n const mapEntries = (items: Array<DictEntry | LabelItem>): CategoryOption[] =>\n items.map((entry) => ({\n id: entry.id,\n value: entry.id,\n label: entry.label,\n color: activeCategorySource === 'tags' && 'color' in entry ? entry.color ?? null : null,\n }))\n\n setActiveCategoryLoading(true)\n void apiCall<{ items?: Array<DictEntry | LabelItem>; totalPages?: number }>(endpoint, {\n cache: 'no-store',\n headers: { 'x-om-unauthorized-redirect': '0' },\n })\n .then((response) => {\n if (!response.ok || cancelled) return\n const fetchedEntries = mapEntries(Array.isArray(response.result?.items) ? response.result.items : [])\n setActiveCategoryTotalPages(\n typeof response.result?.totalPages === 'number' ? response.result.totalPages : 1,\n )\n updateCategoryEntries(activeCategoryKindValue, (currentEntries) =>\n activeCategoryPage <= 1\n ? mergeOptions(seedEntries, fetchedEntries)\n : mergeOptions(currentEntries, seedEntries, fetchedEntries),\n )\n })\n .catch(() => {\n if (cancelled) return\n setActiveCategoryTotalPages(1)\n updateCategoryEntries(activeCategoryKindValue, () => seedEntries)\n })\n .finally(() => {\n if (!cancelled) {\n setActiveCategoryLoading(false)\n }\n })\n\n return () => {\n cancelled = true\n }\n }, [\n activeCategoryKindValue,\n activeCategoryPage,\n activeCategorySource,\n entityId,\n entityOrganizationId,\n open,\n searchValue,\n selectedEntrySeeds,\n updateCategoryEntries,\n ])\n\n const activeCount = React.useMemo(\n () => Object.values(selectedValues).reduce((count, values) => count + values.size, 0),\n [selectedValues],\n )\n\n const hasChanges = React.useMemo(() => {\n const kinds = new Set([\n ...Object.keys(selectedValues),\n ...Object.keys(originalValues),\n ])\n for (const kind of kinds) {\n const current = selectedValues[kind] ?? new Set<string>()\n const original = originalValues[kind] ?? new Set<string>()\n if (current.size !== original.size) return true\n for (const value of current) {\n if (!original.has(value)) return true\n }\n }\n return false\n }, [originalValues, selectedValues])\n\n const filteredEntries = React.useMemo(() => {\n if (!activeCategory) return []\n const query = searchValue.trim().toLowerCase()\n if (!query) return activeCategory.entries\n return activeCategory.entries.filter((entry) =>\n entry.label.toLowerCase().includes(query) || entry.value.toLowerCase().includes(query),\n )\n }, [activeCategory, searchValue])\n\n const toggleValue = React.useCallback(\n (kind: string, value: string, selectionMode: 'single' | 'multi') => {\n setSelectedValues((previous) => {\n const next = new Set(previous[kind] ?? [])\n if (next.has(value)) {\n next.delete(value)\n } else {\n if (selectionMode === 'single') {\n next.clear()\n }\n next.add(value)\n }\n return { ...previous, [kind]: next }\n })\n },\n [],\n )\n\n const handleCreateEntry = React.useCallback(async () => {\n if (!activeCategory || !activeCategory.supportsCreate) return\n const draftValue = newEntryInputByKind[activeCategory.kind] ?? ''\n const trimmed = draftValue.trim()\n if (!trimmed || creatingKind || creationInFlightRef.current) {\n if (!trimmed) {\n setNewEntryInputByKind((previous) => ({ ...previous, [activeCategory.kind]: null }))\n }\n return\n }\n\n const existingEntry = activeCategory.entries.find(\n (entry) => entry.label.trim().toLowerCase() === trimmed.toLowerCase(),\n )\n if (existingEntry) {\n setSelectedValues((previous) => {\n const current = new Set(previous[activeCategory.kind] ?? [])\n current.add(existingEntry.value)\n return { ...previous, [activeCategory.kind]: current }\n })\n setNewEntryInputByKind((previous) => ({ ...previous, [activeCategory.kind]: null }))\n return\n }\n\n creationInFlightRef.current = activeCategory.kind\n setCreatingKind(activeCategory.kind)\n try {\n if (activeCategory.source === 'tags') {\n const result = await runGuardedMutation(\n () =>\n readApiResultOrThrow<Record<string, unknown>>(\n '/api/customers/tags',\n {\n // optimistic-lock-exempt: tag dictionary create-only\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n label: trimmed,\n slug: slugifyTagLabel(trimmed),\n }),\n },\n ),\n { categoryKind: activeCategory.kind, operation: 'createTag', label: trimmed },\n )\n const id = typeof result?.id === 'string' ? result.id : ''\n if (!id) {\n throw new Error(t('customers.people.detail.tags.createError', 'Failed to create tag.'))\n }\n const option: CategoryOption = {\n id,\n value: id,\n label: trimmed,\n color: typeof result?.color === 'string' ? result.color : null,\n }\n updateCategoryEntries(activeCategory.kind, (entries) => [...entries, option])\n setSelectedEntrySeeds((previous) => ({\n ...previous,\n [activeCategory.kind]: mergeOptions(previous[activeCategory.kind] ?? [], [option]),\n }))\n setSelectedValues((previous) => ({\n ...previous,\n [activeCategory.kind]: new Set([...(previous[activeCategory.kind] ?? []), option.value]),\n }))\n } else if (activeCategory.source === 'labels') {\n const payload = entityOrganizationId\n ? { label: trimmed, organizationId: entityOrganizationId }\n : { label: trimmed }\n const result = await runGuardedMutation(\n () =>\n readApiResultOrThrow<{ id: string; slug: string; label: string }>(\n '/api/customers/labels',\n {\n // optimistic-lock-exempt: label dictionary create-only\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n ),\n { categoryKind: activeCategory.kind, operation: 'createLabel', label: trimmed },\n )\n const option: CategoryOption = {\n id: result.id,\n value: result.id,\n label: result.label,\n color: null,\n }\n updateCategoryEntries(activeCategory.kind, (entries) => [...entries, option])\n setSelectedEntrySeeds((previous) => ({\n ...previous,\n [activeCategory.kind]: mergeOptions(previous[activeCategory.kind] ?? [], [option]),\n }))\n setSelectedValues((previous) => ({\n ...previous,\n [activeCategory.kind]: new Set([...(previous[activeCategory.kind] ?? []), option.value]),\n }))\n }\n setNewEntryInputByKind((previous) => ({ ...previous, [activeCategory.kind]: null }))\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : t('customers.personTags.createLabelError', 'Failed to create label')\n flash(message, 'error')\n } finally {\n creationInFlightRef.current = null\n setCreatingKind(null)\n }\n }, [activeCategory, creatingKind, entityOrganizationId, newEntryInputByKind, runGuardedMutation, t, updateCategoryEntries])\n\n const handleSave = React.useCallback(async () => {\n if (saving) return\n setSaving(true)\n try {\n const entityUpdate: Record<string, string | null> = {}\n const customFieldUpdate: Record<string, unknown> = {}\n categories.forEach((category) => {\n if (category.source !== 'dictionary') return\n const currentSelection = selectedValues[category.kind] ?? new Set<string>()\n const originalSelection = originalValues[category.kind] ?? new Set<string>()\n if (areSelectionsEqual(currentSelection, originalSelection)) return\n if (category.entityField) {\n const currentValue = currentSelection.size > 0 ? Array.from(currentSelection)[0] ?? null : null\n entityUpdate[category.entityField] = currentValue\n return\n }\n if (category.customFieldKey) {\n customFieldUpdate[category.customFieldKey] =\n category.selectionMode === 'single'\n ? Array.from(currentSelection)[0] ?? null\n : Array.from(currentSelection)\n }\n })\n\n if (Object.keys(entityUpdate).length > 0 || Object.keys(customFieldUpdate).length > 0) {\n await runGuardedMutation(\n () =>\n apiCallOrThrow(`/api/customers/${entityType === 'person' ? 'people' : 'companies'}`, {\n // optimistic-lock-exempt: tag/label dictionary + custom-field selection write (assignment add/remove)\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n id: entityId,\n ...entityUpdate,\n ...(Object.keys(customFieldUpdate).length > 0\n ? {\n customFields: {\n ...(entityData.customFields ?? {}),\n ...customFieldUpdate,\n },\n }\n : {}),\n }),\n }),\n { operation: 'updateEntityTags', entityUpdate, customFieldUpdate },\n )\n }\n\n const currentTags = selectedValues.tags ?? new Set<string>()\n const originalTags = originalValues.tags ?? new Set<string>()\n const addedTags = Array.from(currentTags).filter((tagId) => !originalTags.has(tagId))\n const removedTags = Array.from(originalTags).filter((tagId) => !currentTags.has(tagId))\n\n for (const tagId of addedTags) {\n await runGuardedMutation(\n () =>\n apiCallOrThrow('/api/customers/tags/assign', {\n // optimistic-lock-exempt: tag assignment add/remove\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ tagId, entityId }),\n }),\n { operation: 'assignTag', tagId },\n )\n }\n\n for (const tagId of removedTags) {\n await runGuardedMutation(\n () =>\n apiCallOrThrow('/api/customers/tags/unassign', {\n // optimistic-lock-exempt: tag assignment add/remove\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ tagId, entityId }),\n }),\n { operation: 'unassignTag', tagId },\n )\n }\n\n const currentLabels = selectedValues.labels ?? new Set<string>()\n const originalLabels = originalValues.labels ?? new Set<string>()\n const addedLabels = Array.from(currentLabels).filter((labelId) => !originalLabels.has(labelId))\n const removedLabels = Array.from(originalLabels).filter((labelId) => !currentLabels.has(labelId))\n\n for (const labelId of addedLabels) {\n const payload = entityOrganizationId\n ? { labelId, entityId, organizationId: entityOrganizationId }\n : { labelId, entityId }\n await runGuardedMutation(\n () =>\n apiCallOrThrow('/api/customers/labels/assign', {\n // optimistic-lock-exempt: label assignment add/remove\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n }),\n { operation: 'assignLabel', labelId },\n )\n }\n\n for (const labelId of removedLabels) {\n const payload = entityOrganizationId\n ? { labelId, entityId, organizationId: entityOrganizationId }\n : { labelId, entityId }\n await runGuardedMutation(\n () =>\n apiCallOrThrow('/api/customers/labels/unassign', {\n // optimistic-lock-exempt: label assignment add/remove\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n }),\n { operation: 'unassignLabel', labelId },\n )\n }\n\n flash(t('customers.personTags.saveSuccess', 'Tags updated.'), 'success')\n onSaved?.()\n onClose()\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : t('customers.personTags.saveError', 'Failed to save tags')\n flash(message, 'error')\n } finally {\n setSaving(false)\n }\n }, [\n categories,\n entityId,\n entityOrganizationId,\n entityType,\n onClose,\n onSaved,\n originalValues,\n saving,\n selectedValues,\n runGuardedMutation,\n t,\n ])\n\n React.useEffect(() => {\n if (!open) return\n const handler = (event: KeyboardEvent) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n void handleSave()\n }\n }\n window.addEventListener('keydown', handler)\n return () => window.removeEventListener('keydown', handler)\n }, [handleSave, open])\n\n React.useEffect(() => {\n if (!open) return\n setSearchValue('')\n }, [activeCategoryKind, open])\n\n const activeSelection = activeCategory\n ? selectedValues[activeCategory.kind] ?? new Set<string>()\n : new Set<string>()\n\n return (\n <Dialog open={open} onOpenChange={(next) => { if (!next) onClose() }}>\n <DialogContent\n className=\"flex max-h-[85vh] flex-col overflow-hidden border-border bg-background p-0 shadow-[0px_16px_40px_0px_rgba(0,0,0,0.14)] sm:max-w-[760px] sm:rounded-xl [&>[data-dialog-close]]:hidden\"\n aria-describedby={undefined}\n >\n <VisuallyHidden>\n <DialogTitle>{t('customers.personTags.title', 'Edit tags')}</DialogTitle>\n </VisuallyHidden>\n\n <div className=\"flex shrink-0 items-center justify-between border-b border-border bg-card px-5 py-4\">\n <div className=\"flex items-center gap-2\">\n <Tag className=\"size-4 text-foreground\" />\n <span className=\"text-sm font-bold text-foreground\">\n {t('customers.personTags.title', 'Edit tags')}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-auto gap-2 rounded-lg px-3.5 py-2 text-sm font-medium\"\n onClick={() => setManageTagsOpen(true)}\n >\n <SlidersHorizontal className=\"size-3.5\" />\n {t('customers.personTags.settingsButton', 'Tag settings')}\n </Button>\n <IconButton\n type=\"button\"\n variant=\"outline\"\n size=\"xs\"\n className=\"size-7 rounded-sm border-border bg-background\"\n onClick={onClose}\n >\n <X className=\"size-3.5\" />\n </IconButton>\n </div>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-hidden bg-background\">\n {loading ? (\n <div className=\"flex h-full items-center justify-center px-6 py-8 text-center text-sm text-muted-foreground\">\n {t('customers.personTags.loading', 'Loading...')}\n </div>\n ) : (\n <div className=\"flex h-full flex-col gap-4 px-5 py-4 md:flex-row\">\n <div className=\"flex gap-2 overflow-x-auto pb-1 md:w-[220px] md:shrink-0 md:flex-col md:overflow-x-visible md:pb-0\">\n {categories.map((category) => {\n const count = selectedValues[category.kind]?.size ?? 0\n const isActive = activeCategory?.kind === category.kind\n return (\n <Button\n key={category.kind}\n type=\"button\"\n variant={isActive ? 'secondary' : 'ghost'}\n size=\"sm\"\n className={cn(\n 'h-auto min-w-[140px] justify-between rounded-lg px-3 py-2 text-left md:w-full',\n isActive ? 'border border-border bg-muted text-foreground' : 'border border-transparent text-muted-foreground',\n )}\n onClick={() => setActiveCategoryKind(category.kind)}\n >\n <span className=\"truncate text-xs font-medium\">\n {category.label}\n </span>\n <span className=\"ml-3 shrink-0 rounded-full bg-background px-2 py-0.5 text-xs font-semibold text-muted-foreground\">\n {count}\n </span>\n </Button>\n )\n })}\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto rounded-xl border border-border bg-card\">\n {activeCategory ? (\n <div className=\"flex min-h-full flex-col\">\n <div className=\"border-b border-border px-4 py-4\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"space-y-1\">\n <h3 className=\"text-sm font-semibold text-foreground\">\n {activeCategory.label}\n </h3>\n <p className=\"max-w-[520px] text-xs leading-5 text-muted-foreground\">\n {activeCategory.description}\n </p>\n </div>\n <div className=\"shrink-0 rounded-full border border-border bg-background px-3 py-1 text-xs font-medium text-muted-foreground\">\n {t('customers.personTags.activeCount', '{{count}} selected', {\n count: activeSelection.size,\n })}\n </div>\n </div>\n </div>\n\n <div className=\"flex-1 space-y-4 overflow-y-auto px-4 py-4\">\n <div className=\"flex items-center gap-2 rounded-lg border border-input bg-background px-3 py-2\">\n <Search className=\"size-3.5 shrink-0 text-muted-foreground\" />\n <input\n type=\"text\"\n value={searchValue}\n onChange={(event) => setSearchValue(event.target.value)}\n placeholder={t(\n 'customers.personTags.searchPlaceholder',\n 'Search {{category}}...',\n { category: activeCategory.label.toLowerCase() },\n )}\n className=\"flex-1 bg-transparent text-sm text-foreground outline-none placeholder:text-muted-foreground\"\n />\n </div>\n\n {filteredEntries.length > 0 ? (\n <div className=\"space-y-3\">\n <div className=\"flex flex-wrap gap-x-1.5 gap-y-2\">\n {filteredEntries.map((entry) => (\n <TagChip\n key={`${activeCategory.kind}:${entry.value}`}\n label={entry.label}\n color={entry.color}\n active={activeSelection.has(entry.value)}\n showColorDot={activeCategory.hasColorDots}\n onClick={() =>\n toggleValue(\n activeCategory.kind,\n entry.value,\n activeCategory.selectionMode,\n )\n }\n />\n ))}\n </div>\n {activeCategoryLoading ? (\n <div className=\"text-xs text-muted-foreground\">\n {t('customers.personTags.loading', 'Loading...')}\n </div>\n ) : null}\n {(activeCategory.source === 'tags' || activeCategory.source === 'labels') && activeCategoryPage < activeCategoryTotalPages ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"rounded-lg px-3 text-xs\"\n onClick={() => setActiveCategoryPage((current) => current + 1)}\n >\n {t('customers.activities.loadMore', 'Load more')}\n </Button>\n ) : null}\n </div>\n ) : activeCategoryLoading ? (\n <div className=\"rounded-lg border border-dashed border-border bg-background px-4 py-6 text-center text-sm text-muted-foreground\">\n {t('customers.personTags.loading', 'Loading...')}\n </div>\n ) : (\n <EmptyState\n size=\"sm\"\n icon={<SearchX className=\"h-8 w-8\" aria-hidden=\"true\" />}\n title={\n searchValue.trim().length > 0\n ? t('customers.personTags.emptySearchResults', 'No options match the current search.')\n : activeCategory.source === 'dictionary'\n ? t('customers.personTags.emptyDictionaryCategory', 'No options are configured for this category yet.')\n : t('customers.personTags.emptyCategory', 'No items have been added for this category yet.')\n }\n />\n )}\n\n {activeCategory.supportsCreate ? (\n <div>\n {newEntryInputByKind[activeCategory.kind] !== null ? (\n <div className=\"inline-flex items-center rounded-full border border-dashed border-status-success-border bg-status-success-bg/70 px-2.5 py-1\">\n <input\n type=\"text\"\n autoFocus\n value={newEntryInputByKind[activeCategory.kind] ?? ''}\n disabled={creatingKind === activeCategory.kind}\n onChange={(event) =>\n setNewEntryInputByKind((previous) => ({\n ...previous,\n [activeCategory.kind]: event.target.value,\n }))\n }\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault()\n void handleCreateEntry()\n }\n if (event.key === 'Escape') {\n setNewEntryInputByKind((previous) => ({\n ...previous,\n [activeCategory.kind]: null,\n }))\n }\n }}\n onBlur={() => {\n const value = newEntryInputByKind[activeCategory.kind] ?? ''\n if (creationInFlightRef.current === activeCategory.kind) {\n return\n }\n if (value.trim()) {\n void handleCreateEntry()\n } else {\n setNewEntryInputByKind((previous) => ({\n ...previous,\n [activeCategory.kind]: null,\n }))\n }\n }}\n placeholder={\n activeCategory.kind === 'tags'\n ? t('customers.people.detail.tags.placeholder', 'Type to add tags')\n : t('customers.personTags.newLabelPlaceholder', 'Label name...')\n }\n className=\"w-[150px] bg-transparent text-xs font-semibold text-status-success-text outline-none placeholder:text-status-success-text/60 disabled:cursor-wait disabled:opacity-70\"\n />\n </div>\n ) : (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={creatingKind === activeCategory.kind}\n onClick={() =>\n setNewEntryInputByKind((previous) => ({\n ...previous,\n [activeCategory.kind]: '',\n }))\n }\n className=\"inline-flex h-auto items-center gap-1 rounded-full border border-dashed border-status-success-border bg-transparent px-2.5 py-1.5 font-semibold text-status-success-text hover:bg-status-success-bg disabled:opacity-60\"\n >\n <Plus className=\"size-2.5\" />\n <span className=\"text-xs\">\n {activeCategory.kind === 'tags'\n ? t('customers.personTags.newTag', 'New tag')\n : t('customers.personTags.newLabel', 'New label')}\n </span>\n </Button>\n )}\n </div>\n ) : null}\n </div>\n </div>\n ) : (\n <div className=\"flex h-full items-center justify-center px-6 py-8 text-center text-sm text-muted-foreground\">\n {t('customers.personTags.emptyCategory', 'No items have been added for this category yet.')}\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n\n <div className=\"flex shrink-0 items-center justify-between border-t border-border bg-muted/20 px-5 py-3.5\">\n <span className=\"text-xs text-muted-foreground\">\n {t('customers.personTags.activeCount', '{{count}} selected', { count: activeCount })}\n </span>\n <div className=\"flex items-center gap-6\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onClose}\n className=\"rounded-md border-border bg-background px-4 py-2 text-sm font-semibold text-foreground\"\n >\n {t('customers.personTags.cancel', 'Cancel')}\n </Button>\n <Button\n type=\"button\"\n onClick={() => { void handleSave() }}\n disabled={saving || !hasChanges}\n className=\"rounded-md bg-foreground px-4 py-2 text-sm font-semibold text-background hover:bg-foreground/90\"\n >\n <Check className=\"mr-2 size-3.5\" />\n {saving\n ? t('customers.personTags.saving', 'Saving...')\n : t('customers.personTags.save', 'Save')}\n </Button>\n </div>\n </div>\n </DialogContent>\n\n <ManageTagsDialog\n open={manageTagsOpen}\n onClose={() => {\n setManageTagsOpen(false)\n void loadData()\n }}\n />\n </Dialog>\n )\n}\n"],
5
- "mappings": "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",
6
- "names": []
4
+ "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Check, Plus, Search, SearchX, SlidersHorizontal, Tag, X } from 'lucide-react'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { VisuallyHidden } from '@radix-ui/react-visually-hidden'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn, slugifyTagLabel } from '@open-mercato/shared/lib/utils'\nimport { apiCall, apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport {\n Dialog,\n DialogContent,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport type { TagSummary } from './types'\nimport { ManageTagsDialog } from './ManageTagsDialog'\n\ntype DictEntry = { id: string; value: string; label: string; color?: string | null }\n\ntype LabelItem = { id: string; slug: string; label: string }\n\ntype KindSetting = {\n kind: string\n selectionMode: 'single' | 'multi'\n visibleInTags: boolean\n sortOrder: number\n}\n\ntype CategorySource = 'dictionary' | 'tags' | 'labels'\n\ntype EntityTagData = {\n status?: string | null\n lifecycleStage?: string | null\n source?: string | null\n temperature?: string | null\n renewalQuarter?: string | null\n jobTitle?: string | null\n industry?: string | null\n customFields?: Record<string, unknown>\n tags?: TagSummary[]\n}\n\ntype CategoryOption = {\n id: string\n value: string\n label: string\n color?: string | null\n}\n\ntype CategoryDef = {\n kind: string\n source: CategorySource\n supportedEntityTypes: Array<'person' | 'company'>\n labelKey: string\n labelFallback: string\n descriptionKey: string\n descriptionFallback: string\n routeKind?: string\n settingKind?: string\n entityField?: keyof EntityTagData\n customFieldKey?: string\n selectionMode?: 'single' | 'multi'\n hasColorDots: boolean\n supportsCreate?: boolean\n}\n\ntype CategorySection = CategoryDef & {\n label: string\n description: string\n entries: CategoryOption[]\n selectionMode: 'single' | 'multi'\n}\n\nexport type EntityTagsDialogProps = {\n open: boolean\n onClose: () => void\n entityId: string\n entityType: 'person' | 'company'\n entityOrganizationId: string | null\n entityData: EntityTagData\n onSaved?: () => void\n}\n\nconst CATEGORY_DEFS: CategoryDef[] = [\n {\n kind: 'tags',\n source: 'tags',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.tags',\n labelFallback: 'Tags',\n descriptionKey: 'customers.personTags.description.tags',\n descriptionFallback: 'Shared CRM tags that can be assigned to many records.',\n selectionMode: 'multi',\n hasColorDots: true,\n supportsCreate: true,\n },\n {\n kind: 'labels',\n source: 'labels',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.labels',\n labelFallback: 'Labels',\n descriptionKey: 'customers.personTags.description.labels',\n descriptionFallback: 'Quick labels you can create inline for this record.',\n selectionMode: 'multi',\n hasColorDots: false,\n supportsCreate: true,\n },\n {\n kind: 'statuses',\n source: 'dictionary',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.statuses',\n labelFallback: 'Status',\n descriptionKey: 'customers.personTags.description.statuses',\n descriptionFallback: 'Primary CRM status shown in the header badges.',\n routeKind: 'statuses',\n settingKind: 'status',\n entityField: 'status',\n selectionMode: 'single',\n hasColorDots: true,\n },\n {\n kind: 'lifecycle-stages',\n source: 'dictionary',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.lifecycle-stages',\n labelFallback: 'Lifecycle',\n descriptionKey: 'customers.personTags.description.lifecycleStages',\n descriptionFallback: 'Lifecycle stage used across CRM detail views.',\n routeKind: 'lifecycle-stages',\n settingKind: 'lifecycle_stage',\n entityField: 'lifecycleStage',\n selectionMode: 'single',\n hasColorDots: true,\n },\n {\n kind: 'sources',\n source: 'dictionary',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.sources',\n labelFallback: 'Source',\n descriptionKey: 'customers.personTags.description.sources',\n descriptionFallback: 'How this record entered the pipeline.',\n routeKind: 'sources',\n settingKind: 'source',\n entityField: 'source',\n selectionMode: 'single',\n hasColorDots: true,\n },\n {\n kind: 'temperature',\n source: 'dictionary',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.temperature',\n labelFallback: 'Temperature',\n descriptionKey: 'customers.personTags.description.temperature',\n descriptionFallback: 'Sales temperature or engagement level.',\n routeKind: 'temperature',\n settingKind: 'temperature',\n entityField: 'temperature',\n selectionMode: 'single',\n hasColorDots: true,\n },\n {\n kind: 'renewal-quarters',\n source: 'dictionary',\n supportedEntityTypes: ['person', 'company'],\n labelKey: 'customers.personTags.category.renewal-quarters',\n labelFallback: 'Renewal quarter',\n descriptionKey: 'customers.personTags.description.renewalQuarters',\n descriptionFallback: 'Quarter used for renewal planning and badges.',\n routeKind: 'renewal-quarters',\n settingKind: 'renewal_quarter',\n entityField: 'renewalQuarter',\n selectionMode: 'single',\n hasColorDots: true,\n },\n {\n kind: 'job-titles',\n source: 'dictionary',\n supportedEntityTypes: ['person'],\n labelKey: 'customers.personTags.category.job-titles',\n labelFallback: 'Job title',\n descriptionKey: 'customers.personTags.description.jobTitles',\n descriptionFallback: 'The role or title used for this person.',\n routeKind: 'job-titles',\n settingKind: 'job_title',\n entityField: 'jobTitle',\n selectionMode: 'single',\n hasColorDots: true,\n },\n {\n kind: 'industries',\n source: 'dictionary',\n supportedEntityTypes: ['company'],\n labelKey: 'customers.personTags.category.industries',\n labelFallback: 'Industry',\n descriptionKey: 'customers.personTags.description.industries',\n descriptionFallback: 'The industry used to classify this company.',\n routeKind: 'industries',\n settingKind: 'industry',\n entityField: 'industry',\n selectionMode: 'single',\n hasColorDots: true,\n },\n]\n\nconst REMOTE_CATEGORY_PAGE_SIZE = 50\nconst CUSTOM_CATEGORY_FIELD_PREFIX = 'crmTagCategory:'\n\nfunction cloneSelectionMap(values: Record<string, Set<string>>): Record<string, Set<string>> {\n return Object.fromEntries(\n Object.entries(values).map(([key, selection]) => [key, new Set(selection)]),\n )\n}\n\nfunction sortOptions(entries: CategoryOption[]): CategoryOption[] {\n return [...entries].sort((left, right) =>\n left.label.localeCompare(right.label, undefined, { sensitivity: 'base' }),\n )\n}\n\nfunction mergeOptions(...groups: CategoryOption[][]): CategoryOption[] {\n const merged = new Map<string, CategoryOption>()\n groups.flat().forEach((entry) => {\n merged.set(entry.value, entry)\n })\n return sortOptions(Array.from(merged.values()))\n}\n\nfunction humanizeCategoryKind(kind: string): string {\n return kind\n .split(/[-_]+/)\n .filter((part) => part.trim().length > 0)\n .map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)\n .join(' ')\n}\n\nfunction resolveCustomCategoryFieldKey(kind: string): string {\n return `${CUSTOM_CATEGORY_FIELD_PREFIX}${kind}`\n}\n\nfunction createCustomCategoryDef(kind: string, selectionMode: 'single' | 'multi'): CategoryDef {\n const label = humanizeCategoryKind(kind)\n return {\n kind,\n source: 'dictionary',\n supportedEntityTypes: ['person', 'company'],\n labelKey: '',\n labelFallback: label,\n descriptionKey: 'customers.personTags.description.customCategory',\n descriptionFallback: `Custom CRM category: ${label}.`,\n routeKind: kind,\n settingKind: kind,\n customFieldKey: resolveCustomCategoryFieldKey(kind),\n selectionMode,\n hasColorDots: true,\n }\n}\n\nfunction normalizeSelectionValues(\n value: unknown,\n selectionMode: 'single' | 'multi',\n): string[] {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n return trimmed.length > 0 ? [trimmed] : []\n }\n if (Array.isArray(value)) {\n const normalized = value\n .filter((entry): entry is string => typeof entry === 'string')\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0)\n if (selectionMode === 'single') {\n return normalized.length > 0 ? [normalized[0]] : []\n }\n return normalized\n }\n return []\n}\n\nfunction readCategorySelectionValues(\n category: CategoryDef,\n entityData: EntityTagData,\n selectionMode: 'single' | 'multi',\n): string[] {\n if (category.entityField) {\n return normalizeSelectionValues(entityData[category.entityField], selectionMode)\n }\n if (category.customFieldKey) {\n return normalizeSelectionValues(entityData.customFields?.[category.customFieldKey], selectionMode)\n }\n return []\n}\n\nfunction areSelectionsEqual(left: Set<string>, right: Set<string>): boolean {\n if (left.size !== right.size) return false\n for (const value of left) {\n if (!right.has(value)) return false\n }\n return true\n}\n\nfunction TagChip({\n label,\n color,\n active,\n showColorDot,\n onClick,\n}: {\n label: string\n color?: string | null\n active: boolean\n showColorDot: boolean\n onClick: () => void\n}) {\n const activeColorStyle: React.CSSProperties | undefined =\n active && color\n ? { color, borderColor: color, backgroundColor: `${color}1A` }\n : undefined\n return (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={onClick}\n className={cn(\n 'inline-flex h-auto items-center gap-1 rounded-full border px-2.5 py-1.5 transition-colors',\n active\n ? activeColorStyle\n ? 'font-semibold hover:opacity-90'\n : 'border-transparent bg-muted font-semibold text-foreground hover:bg-muted'\n : 'border-border bg-transparent font-normal text-muted-foreground hover:bg-muted/60 hover:text-foreground',\n )}\n style={activeColorStyle}\n >\n {showColorDot && color ? (\n <span\n className=\"inline-block size-2 shrink-0 rounded-full\"\n style={{ backgroundColor: color }}\n />\n ) : null}\n <span className=\"text-xs\">{label}</span>\n {active ? <X className=\"size-2.5 shrink-0\" /> : null}\n </Button>\n )\n}\n\nfunction buildApplicableCategories(\n entityType: 'person' | 'company',\n kindSettings: KindSetting[],\n) {\n const baseCategories = CATEGORY_DEFS.filter((category) => category.supportedEntityTypes.includes(entityType))\n const customCategories = kindSettings\n .filter((setting) => setting.visibleInTags)\n .filter((setting) => !CATEGORY_DEFS.some((category) => category.kind === setting.kind || category.settingKind === setting.kind))\n .map((setting) => createCustomCategoryDef(setting.kind, setting.selectionMode))\n return [...baseCategories, ...customCategories]\n}\n\nexport function EntityTagsDialog({\n open,\n onClose,\n entityId,\n entityType,\n entityOrganizationId,\n entityData,\n onSaved,\n}: EntityTagsDialogProps) {\n const t = useT()\n const [loading, setLoading] = React.useState(true)\n const [saving, setSaving] = React.useState(false)\n const [searchValue, setSearchValue] = React.useState('')\n const [categories, setCategories] = React.useState<CategorySection[]>([])\n const [selectedEntrySeeds, setSelectedEntrySeeds] = React.useState<Record<string, CategoryOption[]>>({})\n const [selectedValues, setSelectedValues] = React.useState<Record<string, Set<string>>>({})\n const [originalValues, setOriginalValues] = React.useState<Record<string, Set<string>>>({})\n const [activeCategoryKind, setActiveCategoryKind] = React.useState<string | null>(null)\n const [newEntryInputByKind, setNewEntryInputByKind] = React.useState<Record<string, string | null>>({})\n const [creatingKind, setCreatingKind] = React.useState<string | null>(null)\n const [manageTagsOpen, setManageTagsOpen] = React.useState(false)\n const [activeCategoryPage, setActiveCategoryPage] = React.useState(1)\n const [activeCategoryTotalPages, setActiveCategoryTotalPages] = React.useState(1)\n const [activeCategoryLoading, setActiveCategoryLoading] = React.useState(false)\n const creationInFlightRef = React.useRef<string | null>(null)\n const mutationContextId = React.useMemo(\n () => `customer-tags:${entityType}:${entityId}`,\n [entityId, entityType],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n entityType: 'person' | 'company'\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const mutationContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n resourceKind: entityType === 'person' ? 'customers.person' : 'customers.company',\n resourceId: entityId,\n entityType,\n retryLastMutation,\n }),\n [entityId, entityType, mutationContextId, retryLastMutation],\n )\n const runGuardedMutation = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload: Record<string, unknown>) =>\n runMutation({\n operation,\n mutationPayload,\n context: mutationContext,\n }),\n [mutationContext, runMutation],\n )\n\n const updateCategoryEntries = React.useCallback(\n (kind: string, updater: (entries: CategoryOption[]) => CategoryOption[]) => {\n setCategories((previous) =>\n previous.map((category) =>\n category.kind === kind\n ? { ...category, entries: sortOptions(updater(category.entries)) }\n : category,\n ),\n )\n },\n [],\n )\n\n const loadData = React.useCallback(async () => {\n setLoading(true)\n try {\n const scopedQuery = new URLSearchParams()\n if (entityOrganizationId) {\n scopedQuery.set('organizationId', entityOrganizationId)\n }\n\n const loadKindSettings = async (): Promise<KindSetting[]> => {\n try {\n const settingsCall = await apiCall<{ items?: KindSetting[] }>(\n `/api/customers/dictionaries/kind-settings${scopedQuery.size ? `?${scopedQuery.toString()}` : ''}`,\n { cache: 'no-store', headers: { 'x-om-unauthorized-redirect': '0' } },\n )\n if (settingsCall.ok && settingsCall.result?.items) {\n return settingsCall.result.items\n }\n } catch {\n // Default category order works without explicit settings rows.\n }\n return []\n }\n\n const loadLabelData = async (): Promise<{\n assignedLabelIds: string[]\n selectedLabelEntries: CategoryOption[]\n }> => {\n try {\n const labelsQuery = new URLSearchParams()\n labelsQuery.set('entityId', entityId)\n labelsQuery.set('pageSize', '1')\n if (entityOrganizationId) {\n labelsQuery.set('organizationId', entityOrganizationId)\n }\n const labelsCall = await apiCall<{\n items?: LabelItem[]\n assignedIds?: string[]\n }>(`/api/customers/labels?${labelsQuery.toString()}`, {\n cache: 'no-store',\n headers: { 'x-om-unauthorized-redirect': '0' },\n })\n const labelsData = labelsCall.ok ? labelsCall.result : null\n const assignedLabelIds = labelsData?.assignedIds ?? []\n if (assignedLabelIds.length === 0) {\n return { assignedLabelIds, selectedLabelEntries: [] }\n }\n const detailQuery = new URLSearchParams({\n ids: assignedLabelIds.join(','),\n pageSize: String(Math.min(assignedLabelIds.length, 100)),\n })\n if (entityOrganizationId) {\n detailQuery.set('organizationId', entityOrganizationId)\n }\n const selectedLabelsCall = await apiCall<{ items?: LabelItem[] }>(\n `/api/customers/labels?${detailQuery.toString()}`,\n {\n cache: 'no-store',\n headers: { 'x-om-unauthorized-redirect': '0' },\n },\n )\n const selectedLabels = selectedLabelsCall.ok ? selectedLabelsCall.result?.items ?? [] : []\n const selectedLabelEntries = selectedLabels.map((label) => ({\n id: label.id,\n value: label.id,\n label: label.label,\n color: null,\n }))\n return { assignedLabelIds, selectedLabelEntries }\n } catch {\n return { assignedLabelIds: [], selectedLabelEntries: [] }\n }\n }\n\n const selectedTagEntries = Array.isArray(entityData.tags)\n ? entityData.tags.map((tag) => ({\n id: tag.id,\n value: tag.id,\n label: tag.label,\n color: tag.color ?? null,\n }))\n : []\n\n // The label chain is independent of kind settings and the dictionary\n // fan-out, so kick it off immediately and let it resolve in parallel.\n const labelDataPromise = loadLabelData()\n\n const kindSettings = await loadKindSettings()\n const settingsMap = new Map(kindSettings.map((setting) => [setting.kind, setting]))\n const categoryDefs = buildApplicableCategories(entityType, kindSettings)\n\n const loadDictionaryCategory = async (categoryDef: CategoryDef): Promise<CategorySection> => {\n try {\n const dictionaryUrl = new URL(`/api/customers/dictionaries/${categoryDef.routeKind}`, 'http://localhost')\n if (entityOrganizationId) {\n dictionaryUrl.searchParams.set('organizationId', entityOrganizationId)\n }\n const dictionaryCall = await apiCall<{ items?: DictEntry[] }>(\n `${dictionaryUrl.pathname}${dictionaryUrl.search}`,\n { cache: 'no-store', headers: { 'x-om-unauthorized-redirect': '0' } },\n )\n const dictionaryItems = dictionaryCall.ok ? dictionaryCall.result?.items ?? [] : []\n const entries = dictionaryItems.map((entry) => ({\n id: entry.id,\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n }))\n const setting = categoryDef.settingKind\n ? settingsMap.get(categoryDef.settingKind)\n : undefined\n const selectionMode = setting?.selectionMode ?? categoryDef.selectionMode ?? 'single'\n const currentValues = readCategorySelectionValues(categoryDef, entityData, selectionMode)\n currentValues.forEach((currentValue) => {\n if (entries.some((entry) => entry.value === currentValue)) return\n entries.push({\n id: `current:${categoryDef.kind}:${currentValue}`,\n value: currentValue,\n label: currentValue,\n color: null,\n })\n })\n return {\n ...categoryDef,\n label: categoryDef.labelKey\n ? t(categoryDef.labelKey, categoryDef.labelFallback)\n : categoryDef.labelFallback,\n description: categoryDef.descriptionKey\n ? t(\n categoryDef.descriptionKey,\n categoryDef.descriptionFallback,\n categoryDef.customFieldKey ? { name: categoryDef.labelFallback } : undefined,\n )\n : categoryDef.descriptionFallback,\n entries: sortOptions(entries),\n selectionMode,\n }\n } catch {\n const setting = categoryDef.settingKind\n ? settingsMap.get(categoryDef.settingKind)\n : undefined\n const selectionMode = setting?.selectionMode ?? categoryDef.selectionMode ?? 'single'\n const fallbackEntries = readCategorySelectionValues(categoryDef, entityData, selectionMode).map((value) => ({\n id: `current:${categoryDef.kind}:${value}`,\n value,\n label: value,\n color: null,\n }))\n return {\n ...categoryDef,\n label: categoryDef.labelKey\n ? t(categoryDef.labelKey, categoryDef.labelFallback)\n : categoryDef.labelFallback,\n description: categoryDef.descriptionKey\n ? t(\n categoryDef.descriptionKey,\n categoryDef.descriptionFallback,\n categoryDef.customFieldKey ? { name: categoryDef.labelFallback } : undefined,\n )\n : categoryDef.descriptionFallback,\n entries: fallbackEntries,\n selectionMode,\n }\n }\n }\n\n // Independent dictionary requests fan out together instead of awaiting\n // each one sequentially; Promise.all preserves categoryDefs order so the\n // subsequent sort and selection initialization stay stable.\n const loadedCategories = await Promise.all(\n categoryDefs.map(async (categoryDef): Promise<CategorySection> => {\n if (categoryDef.source === 'tags') {\n return {\n ...categoryDef,\n label: t(categoryDef.labelKey, categoryDef.labelFallback),\n description: t(categoryDef.descriptionKey, categoryDef.descriptionFallback),\n entries: sortOptions(selectedTagEntries),\n selectionMode: categoryDef.selectionMode ?? 'multi',\n }\n }\n if (categoryDef.source === 'labels') {\n const { selectedLabelEntries } = await labelDataPromise\n return {\n ...categoryDef,\n label: t(categoryDef.labelKey, categoryDef.labelFallback),\n description: t(categoryDef.descriptionKey, categoryDef.descriptionFallback),\n entries: sortOptions(selectedLabelEntries),\n selectionMode: categoryDef.selectionMode ?? 'multi',\n }\n }\n return loadDictionaryCategory(categoryDef)\n }),\n )\n\n const { assignedLabelIds, selectedLabelEntries } = await labelDataPromise\n\n loadedCategories.sort((left, right) => {\n const leftSortOrder =\n left.settingKind && settingsMap.has(left.settingKind)\n ? settingsMap.get(left.settingKind)?.sortOrder ?? 1000\n : 1000 + CATEGORY_DEFS.findIndex((category) => category.kind === left.kind)\n const rightSortOrder =\n right.settingKind && settingsMap.has(right.settingKind)\n ? settingsMap.get(right.settingKind)?.sortOrder ?? 1000\n : 1000 + CATEGORY_DEFS.findIndex((category) => category.kind === right.kind)\n return leftSortOrder - rightSortOrder\n })\n\n const initialValues: Record<string, Set<string>> = {}\n for (const category of loadedCategories) {\n if (category.source === 'dictionary' && (category.entityField || category.customFieldKey)) {\n initialValues[category.kind] = new Set(\n readCategorySelectionValues(category, entityData, category.selectionMode),\n )\n continue\n }\n if (category.source === 'tags') {\n const availableTagIds = new Set(category.entries.map((entry) => entry.value))\n const assignedTagIds = Array.isArray(entityData.tags)\n ? entityData.tags\n .map((tag) => tag.id)\n .filter((tagId) => availableTagIds.has(tagId))\n : []\n initialValues[category.kind] = new Set(assignedTagIds)\n continue\n }\n if (category.source === 'labels') {\n const availableLabelIds = new Set(category.entries.map((entry) => entry.value))\n initialValues[category.kind] = new Set(\n assignedLabelIds.filter((labelId) => availableLabelIds.has(labelId)),\n )\n continue\n }\n initialValues[category.kind] = new Set()\n }\n\n setCategories(loadedCategories)\n setSelectedEntrySeeds({\n tags: selectedTagEntries,\n labels: selectedLabelEntries,\n })\n setSelectedValues(initialValues)\n setOriginalValues(cloneSelectionMap(initialValues))\n setActiveCategoryKind((previous) => {\n if (previous && loadedCategories.some((category) => category.kind === previous)) {\n return previous\n }\n return loadedCategories[0]?.kind ?? null\n })\n } finally {\n setLoading(false)\n }\n }, [entityData, entityId, entityOrganizationId, entityType, t])\n\n React.useEffect(() => {\n if (!open) return\n setSearchValue('')\n setNewEntryInputByKind({})\n loadData().catch((err) => console.warn('[EntityTagsDialog] loadData failed', err))\n }, [loadData, open])\n\n React.useEffect(() => {\n if (open) return\n setManageTagsOpen(false)\n }, [open])\n\n const activeCategory = React.useMemo(() => {\n if (!categories.length) return null\n return categories.find((category) => category.kind === activeCategoryKind) ?? categories[0]\n }, [activeCategoryKind, categories])\n const activeCategoryKindValue = activeCategory?.kind ?? null\n const activeCategorySource = activeCategory?.source ?? null\n\n React.useEffect(() => {\n if (!open) return\n setActiveCategoryPage(1)\n }, [activeCategoryKind, open, searchValue])\n\n React.useEffect(() => {\n if (!open || !activeCategoryKindValue || (activeCategorySource !== 'tags' && activeCategorySource !== 'labels')) {\n setActiveCategoryLoading(false)\n setActiveCategoryTotalPages(1)\n return\n }\n\n let cancelled = false\n const params = new URLSearchParams({\n page: String(activeCategoryPage),\n pageSize: String(REMOTE_CATEGORY_PAGE_SIZE),\n })\n if (searchValue.trim().length > 0) {\n params.set('search', searchValue.trim())\n }\n if (activeCategorySource === 'labels') {\n params.set('entityId', entityId)\n if (entityOrganizationId) {\n params.set('organizationId', entityOrganizationId)\n }\n }\n\n const endpoint =\n activeCategorySource === 'tags'\n ? `/api/customers/tags?${params.toString()}`\n : `/api/customers/labels?${params.toString()}`\n const seedEntries = searchValue.trim().length > 0 ? [] : selectedEntrySeeds[activeCategoryKindValue] ?? []\n\n const mapEntries = (items: Array<DictEntry | LabelItem>): CategoryOption[] =>\n items.map((entry) => ({\n id: entry.id,\n value: entry.id,\n label: entry.label,\n color: activeCategorySource === 'tags' && 'color' in entry ? entry.color ?? null : null,\n }))\n\n setActiveCategoryLoading(true)\n void apiCall<{ items?: Array<DictEntry | LabelItem>; totalPages?: number }>(endpoint, {\n cache: 'no-store',\n headers: { 'x-om-unauthorized-redirect': '0' },\n })\n .then((response) => {\n if (!response.ok || cancelled) return\n const fetchedEntries = mapEntries(Array.isArray(response.result?.items) ? response.result.items : [])\n setActiveCategoryTotalPages(\n typeof response.result?.totalPages === 'number' ? response.result.totalPages : 1,\n )\n updateCategoryEntries(activeCategoryKindValue, (currentEntries) =>\n activeCategoryPage <= 1\n ? mergeOptions(seedEntries, fetchedEntries)\n : mergeOptions(currentEntries, seedEntries, fetchedEntries),\n )\n })\n .catch(() => {\n if (cancelled) return\n setActiveCategoryTotalPages(1)\n updateCategoryEntries(activeCategoryKindValue, () => seedEntries)\n })\n .finally(() => {\n if (!cancelled) {\n setActiveCategoryLoading(false)\n }\n })\n\n return () => {\n cancelled = true\n }\n }, [\n activeCategoryKindValue,\n activeCategoryPage,\n activeCategorySource,\n entityId,\n entityOrganizationId,\n open,\n searchValue,\n selectedEntrySeeds,\n updateCategoryEntries,\n ])\n\n const activeCount = React.useMemo(\n () => Object.values(selectedValues).reduce((count, values) => count + values.size, 0),\n [selectedValues],\n )\n\n const hasChanges = React.useMemo(() => {\n const kinds = new Set([\n ...Object.keys(selectedValues),\n ...Object.keys(originalValues),\n ])\n for (const kind of kinds) {\n const current = selectedValues[kind] ?? new Set<string>()\n const original = originalValues[kind] ?? new Set<string>()\n if (current.size !== original.size) return true\n for (const value of current) {\n if (!original.has(value)) return true\n }\n }\n return false\n }, [originalValues, selectedValues])\n\n const filteredEntries = React.useMemo(() => {\n if (!activeCategory) return []\n const query = searchValue.trim().toLowerCase()\n if (!query) return activeCategory.entries\n return activeCategory.entries.filter((entry) =>\n entry.label.toLowerCase().includes(query) || entry.value.toLowerCase().includes(query),\n )\n }, [activeCategory, searchValue])\n\n const toggleValue = React.useCallback(\n (kind: string, value: string, selectionMode: 'single' | 'multi') => {\n setSelectedValues((previous) => {\n const next = new Set(previous[kind] ?? [])\n if (next.has(value)) {\n next.delete(value)\n } else {\n if (selectionMode === 'single') {\n next.clear()\n }\n next.add(value)\n }\n return { ...previous, [kind]: next }\n })\n },\n [],\n )\n\n const handleCreateEntry = React.useCallback(async () => {\n if (!activeCategory || !activeCategory.supportsCreate) return\n const draftValue = newEntryInputByKind[activeCategory.kind] ?? ''\n const trimmed = draftValue.trim()\n if (!trimmed || creatingKind || creationInFlightRef.current) {\n if (!trimmed) {\n setNewEntryInputByKind((previous) => ({ ...previous, [activeCategory.kind]: null }))\n }\n return\n }\n\n const existingEntry = activeCategory.entries.find(\n (entry) => entry.label.trim().toLowerCase() === trimmed.toLowerCase(),\n )\n if (existingEntry) {\n setSelectedValues((previous) => {\n const current = new Set(previous[activeCategory.kind] ?? [])\n current.add(existingEntry.value)\n return { ...previous, [activeCategory.kind]: current }\n })\n setNewEntryInputByKind((previous) => ({ ...previous, [activeCategory.kind]: null }))\n return\n }\n\n creationInFlightRef.current = activeCategory.kind\n setCreatingKind(activeCategory.kind)\n try {\n if (activeCategory.source === 'tags') {\n const result = await runGuardedMutation(\n () =>\n readApiResultOrThrow<Record<string, unknown>>(\n '/api/customers/tags',\n {\n // optimistic-lock-exempt: tag dictionary create-only\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n label: trimmed,\n slug: slugifyTagLabel(trimmed),\n }),\n },\n ),\n { categoryKind: activeCategory.kind, operation: 'createTag', label: trimmed },\n )\n const id = typeof result?.id === 'string' ? result.id : ''\n if (!id) {\n throw new Error(t('customers.people.detail.tags.createError', 'Failed to create tag.'))\n }\n const option: CategoryOption = {\n id,\n value: id,\n label: trimmed,\n color: typeof result?.color === 'string' ? result.color : null,\n }\n updateCategoryEntries(activeCategory.kind, (entries) => [...entries, option])\n setSelectedEntrySeeds((previous) => ({\n ...previous,\n [activeCategory.kind]: mergeOptions(previous[activeCategory.kind] ?? [], [option]),\n }))\n setSelectedValues((previous) => ({\n ...previous,\n [activeCategory.kind]: new Set([...(previous[activeCategory.kind] ?? []), option.value]),\n }))\n } else if (activeCategory.source === 'labels') {\n const payload = entityOrganizationId\n ? { label: trimmed, organizationId: entityOrganizationId }\n : { label: trimmed }\n const result = await runGuardedMutation(\n () =>\n readApiResultOrThrow<{ id: string; slug: string; label: string }>(\n '/api/customers/labels',\n {\n // optimistic-lock-exempt: label dictionary create-only\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n ),\n { categoryKind: activeCategory.kind, operation: 'createLabel', label: trimmed },\n )\n const option: CategoryOption = {\n id: result.id,\n value: result.id,\n label: result.label,\n color: null,\n }\n updateCategoryEntries(activeCategory.kind, (entries) => [...entries, option])\n setSelectedEntrySeeds((previous) => ({\n ...previous,\n [activeCategory.kind]: mergeOptions(previous[activeCategory.kind] ?? [], [option]),\n }))\n setSelectedValues((previous) => ({\n ...previous,\n [activeCategory.kind]: new Set([...(previous[activeCategory.kind] ?? []), option.value]),\n }))\n }\n setNewEntryInputByKind((previous) => ({ ...previous, [activeCategory.kind]: null }))\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : t('customers.personTags.createLabelError', 'Failed to create label')\n flash(message, 'error')\n } finally {\n creationInFlightRef.current = null\n setCreatingKind(null)\n }\n }, [activeCategory, creatingKind, entityOrganizationId, newEntryInputByKind, runGuardedMutation, t, updateCategoryEntries])\n\n const handleSave = React.useCallback(async () => {\n if (saving) return\n setSaving(true)\n try {\n const entityUpdate: Record<string, string | null> = {}\n const customFieldUpdate: Record<string, unknown> = {}\n categories.forEach((category) => {\n if (category.source !== 'dictionary') return\n const currentSelection = selectedValues[category.kind] ?? new Set<string>()\n const originalSelection = originalValues[category.kind] ?? new Set<string>()\n if (areSelectionsEqual(currentSelection, originalSelection)) return\n if (category.entityField) {\n const currentValue = currentSelection.size > 0 ? Array.from(currentSelection)[0] ?? null : null\n entityUpdate[category.entityField] = currentValue\n return\n }\n if (category.customFieldKey) {\n customFieldUpdate[category.customFieldKey] =\n category.selectionMode === 'single'\n ? Array.from(currentSelection)[0] ?? null\n : Array.from(currentSelection)\n }\n })\n\n if (Object.keys(entityUpdate).length > 0 || Object.keys(customFieldUpdate).length > 0) {\n await runGuardedMutation(\n () =>\n apiCallOrThrow(`/api/customers/${entityType === 'person' ? 'people' : 'companies'}`, {\n // optimistic-lock-exempt: tag/label dictionary + custom-field selection write (assignment add/remove)\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n id: entityId,\n ...entityUpdate,\n ...(Object.keys(customFieldUpdate).length > 0\n ? {\n customFields: {\n ...(entityData.customFields ?? {}),\n ...customFieldUpdate,\n },\n }\n : {}),\n }),\n }),\n { operation: 'updateEntityTags', entityUpdate, customFieldUpdate },\n )\n }\n\n const currentTags = selectedValues.tags ?? new Set<string>()\n const originalTags = originalValues.tags ?? new Set<string>()\n const addedTags = Array.from(currentTags).filter((tagId) => !originalTags.has(tagId))\n const removedTags = Array.from(originalTags).filter((tagId) => !currentTags.has(tagId))\n\n for (const tagId of addedTags) {\n await runGuardedMutation(\n () =>\n apiCallOrThrow('/api/customers/tags/assign', {\n // optimistic-lock-exempt: tag assignment add/remove\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ tagId, entityId }),\n }),\n { operation: 'assignTag', tagId },\n )\n }\n\n for (const tagId of removedTags) {\n await runGuardedMutation(\n () =>\n apiCallOrThrow('/api/customers/tags/unassign', {\n // optimistic-lock-exempt: tag assignment add/remove\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ tagId, entityId }),\n }),\n { operation: 'unassignTag', tagId },\n )\n }\n\n const currentLabels = selectedValues.labels ?? new Set<string>()\n const originalLabels = originalValues.labels ?? new Set<string>()\n const addedLabels = Array.from(currentLabels).filter((labelId) => !originalLabels.has(labelId))\n const removedLabels = Array.from(originalLabels).filter((labelId) => !currentLabels.has(labelId))\n\n for (const labelId of addedLabels) {\n const payload = entityOrganizationId\n ? { labelId, entityId, organizationId: entityOrganizationId }\n : { labelId, entityId }\n await runGuardedMutation(\n () =>\n apiCallOrThrow('/api/customers/labels/assign', {\n // optimistic-lock-exempt: label assignment add/remove\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n }),\n { operation: 'assignLabel', labelId },\n )\n }\n\n for (const labelId of removedLabels) {\n const payload = entityOrganizationId\n ? { labelId, entityId, organizationId: entityOrganizationId }\n : { labelId, entityId }\n await runGuardedMutation(\n () =>\n apiCallOrThrow('/api/customers/labels/unassign', {\n // optimistic-lock-exempt: label assignment add/remove\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n }),\n { operation: 'unassignLabel', labelId },\n )\n }\n\n flash(t('customers.personTags.saveSuccess', 'Tags updated.'), 'success')\n onSaved?.()\n onClose()\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : t('customers.personTags.saveError', 'Failed to save tags')\n flash(message, 'error')\n } finally {\n setSaving(false)\n }\n }, [\n categories,\n entityId,\n entityOrganizationId,\n entityType,\n onClose,\n onSaved,\n originalValues,\n saving,\n selectedValues,\n runGuardedMutation,\n t,\n ])\n\n React.useEffect(() => {\n if (!open) return\n const handler = (event: KeyboardEvent) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n void handleSave()\n }\n }\n window.addEventListener('keydown', handler)\n return () => window.removeEventListener('keydown', handler)\n }, [handleSave, open])\n\n React.useEffect(() => {\n if (!open) return\n setSearchValue('')\n }, [activeCategoryKind, open])\n\n const activeSelection = activeCategory\n ? selectedValues[activeCategory.kind] ?? new Set<string>()\n : new Set<string>()\n\n return (\n <Dialog open={open} onOpenChange={(next) => { if (!next) onClose() }}>\n <DialogContent\n className=\"flex max-h-[85vh] flex-col overflow-hidden border-border bg-background p-0 shadow-[0px_16px_40px_0px_rgba(0,0,0,0.14)] sm:max-w-[760px] sm:rounded-xl [&>[data-dialog-close]]:hidden\"\n aria-describedby={undefined}\n >\n <VisuallyHidden>\n <DialogTitle>{t('customers.personTags.title', 'Edit tags')}</DialogTitle>\n </VisuallyHidden>\n\n <div className=\"flex shrink-0 items-center justify-between border-b border-border bg-card px-5 py-4\">\n <div className=\"flex items-center gap-2\">\n <Tag className=\"size-4 text-foreground\" />\n <span className=\"text-sm font-bold text-foreground\">\n {t('customers.personTags.title', 'Edit tags')}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-auto gap-2 rounded-lg px-3.5 py-2 text-sm font-medium\"\n onClick={() => setManageTagsOpen(true)}\n >\n <SlidersHorizontal className=\"size-3.5\" />\n {t('customers.personTags.settingsButton', 'Tag settings')}\n </Button>\n <IconButton\n type=\"button\"\n variant=\"outline\"\n size=\"xs\"\n className=\"size-7 rounded-sm border-border bg-background\"\n onClick={onClose}\n >\n <X className=\"size-3.5\" />\n </IconButton>\n </div>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-hidden bg-background\">\n {loading ? (\n <div className=\"flex h-full items-center justify-center px-6 py-8 text-center text-sm text-muted-foreground\">\n {t('customers.personTags.loading', 'Loading...')}\n </div>\n ) : (\n <div className=\"flex h-full flex-col gap-4 px-5 py-4 md:flex-row\">\n <div className=\"flex gap-2 overflow-x-auto pb-1 md:w-[220px] md:shrink-0 md:flex-col md:overflow-x-visible md:pb-0\">\n {categories.map((category) => {\n const count = selectedValues[category.kind]?.size ?? 0\n const isActive = activeCategory?.kind === category.kind\n return (\n <Button\n key={category.kind}\n type=\"button\"\n variant={isActive ? 'secondary' : 'ghost'}\n size=\"sm\"\n className={cn(\n 'h-auto min-w-[140px] justify-between rounded-lg px-3 py-2 text-left md:w-full',\n isActive ? 'border border-border bg-muted text-foreground' : 'border border-transparent text-muted-foreground',\n )}\n onClick={() => setActiveCategoryKind(category.kind)}\n >\n <span className=\"truncate text-xs font-medium\">\n {category.label}\n </span>\n <span className=\"ml-3 shrink-0 rounded-full bg-background px-2 py-0.5 text-xs font-semibold text-muted-foreground\">\n {count}\n </span>\n </Button>\n )\n })}\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto rounded-xl border border-border bg-card\">\n {activeCategory ? (\n <div className=\"flex min-h-full flex-col\">\n <div className=\"border-b border-border px-4 py-4\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"space-y-1\">\n <h3 className=\"text-sm font-semibold text-foreground\">\n {activeCategory.label}\n </h3>\n <p className=\"max-w-[520px] text-xs leading-5 text-muted-foreground\">\n {activeCategory.description}\n </p>\n </div>\n <div className=\"shrink-0 rounded-full border border-border bg-background px-3 py-1 text-xs font-medium text-muted-foreground\">\n {t('customers.personTags.activeCount', '{{count}} selected', {\n count: activeSelection.size,\n })}\n </div>\n </div>\n </div>\n\n <div className=\"flex-1 space-y-4 overflow-y-auto px-4 py-4\">\n <div className=\"flex items-center gap-2 rounded-lg border border-input bg-background px-3 py-2\">\n <Search className=\"size-3.5 shrink-0 text-muted-foreground\" />\n <input\n type=\"text\"\n value={searchValue}\n onChange={(event) => setSearchValue(event.target.value)}\n placeholder={t(\n 'customers.personTags.searchPlaceholder',\n 'Search {{category}}...',\n { category: activeCategory.label.toLowerCase() },\n )}\n className=\"flex-1 bg-transparent text-sm text-foreground outline-none placeholder:text-muted-foreground\"\n />\n </div>\n\n {filteredEntries.length > 0 ? (\n <div className=\"space-y-3\">\n <div className=\"flex flex-wrap gap-x-1.5 gap-y-2\">\n {filteredEntries.map((entry) => (\n <TagChip\n key={`${activeCategory.kind}:${entry.value}`}\n label={entry.label}\n color={entry.color}\n active={activeSelection.has(entry.value)}\n showColorDot={activeCategory.hasColorDots}\n onClick={() =>\n toggleValue(\n activeCategory.kind,\n entry.value,\n activeCategory.selectionMode,\n )\n }\n />\n ))}\n </div>\n {activeCategoryLoading ? (\n <div className=\"text-xs text-muted-foreground\">\n {t('customers.personTags.loading', 'Loading...')}\n </div>\n ) : null}\n {(activeCategory.source === 'tags' || activeCategory.source === 'labels') && activeCategoryPage < activeCategoryTotalPages ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"rounded-lg px-3 text-xs\"\n onClick={() => setActiveCategoryPage((current) => current + 1)}\n >\n {t('customers.activities.loadMore', 'Load more')}\n </Button>\n ) : null}\n </div>\n ) : activeCategoryLoading ? (\n <div className=\"rounded-lg border border-dashed border-border bg-background px-4 py-6 text-center text-sm text-muted-foreground\">\n {t('customers.personTags.loading', 'Loading...')}\n </div>\n ) : (\n <EmptyState\n size=\"sm\"\n icon={<SearchX className=\"h-8 w-8\" aria-hidden=\"true\" />}\n title={\n searchValue.trim().length > 0\n ? t('customers.personTags.emptySearchResults', 'No options match the current search.')\n : activeCategory.source === 'dictionary'\n ? t('customers.personTags.emptyDictionaryCategory', 'No options are configured for this category yet.')\n : t('customers.personTags.emptyCategory', 'No items have been added for this category yet.')\n }\n />\n )}\n\n {activeCategory.supportsCreate ? (\n <div>\n {newEntryInputByKind[activeCategory.kind] !== null ? (\n <div className=\"inline-flex items-center rounded-full border border-dashed border-status-success-border bg-status-success-bg/70 px-2.5 py-1\">\n <input\n type=\"text\"\n autoFocus\n value={newEntryInputByKind[activeCategory.kind] ?? ''}\n disabled={creatingKind === activeCategory.kind}\n onChange={(event) =>\n setNewEntryInputByKind((previous) => ({\n ...previous,\n [activeCategory.kind]: event.target.value,\n }))\n }\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault()\n void handleCreateEntry()\n }\n if (event.key === 'Escape') {\n setNewEntryInputByKind((previous) => ({\n ...previous,\n [activeCategory.kind]: null,\n }))\n }\n }}\n onBlur={() => {\n const value = newEntryInputByKind[activeCategory.kind] ?? ''\n if (creationInFlightRef.current === activeCategory.kind) {\n return\n }\n if (value.trim()) {\n void handleCreateEntry()\n } else {\n setNewEntryInputByKind((previous) => ({\n ...previous,\n [activeCategory.kind]: null,\n }))\n }\n }}\n placeholder={\n activeCategory.kind === 'tags'\n ? t('customers.people.detail.tags.placeholder', 'Type to add tags')\n : t('customers.personTags.newLabelPlaceholder', 'Label name...')\n }\n className=\"w-[150px] bg-transparent text-xs font-semibold text-status-success-text outline-none placeholder:text-status-success-text/60 disabled:cursor-wait disabled:opacity-70\"\n />\n </div>\n ) : (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={creatingKind === activeCategory.kind}\n onClick={() =>\n setNewEntryInputByKind((previous) => ({\n ...previous,\n [activeCategory.kind]: '',\n }))\n }\n className=\"inline-flex h-auto items-center gap-1 rounded-full border border-dashed border-status-success-border bg-transparent px-2.5 py-1.5 font-semibold text-status-success-text hover:bg-status-success-bg disabled:opacity-60\"\n >\n <Plus className=\"size-2.5\" />\n <span className=\"text-xs\">\n {activeCategory.kind === 'tags'\n ? t('customers.personTags.newTag', 'New tag')\n : t('customers.personTags.newLabel', 'New label')}\n </span>\n </Button>\n )}\n </div>\n ) : null}\n </div>\n </div>\n ) : (\n <div className=\"flex h-full items-center justify-center px-6 py-8 text-center text-sm text-muted-foreground\">\n {t('customers.personTags.emptyCategory', 'No items have been added for this category yet.')}\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n\n <div className=\"flex shrink-0 items-center justify-between border-t border-border bg-muted/20 px-5 py-3.5\">\n <span className=\"text-xs text-muted-foreground\">\n {t('customers.personTags.activeCount', '{{count}} selected', { count: activeCount })}\n </span>\n <div className=\"flex items-center gap-6\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onClose}\n className=\"rounded-md border-border bg-background px-4 py-2 text-sm font-semibold text-foreground\"\n >\n {t('customers.personTags.cancel', 'Cancel')}\n </Button>\n <Button\n type=\"button\"\n onClick={() => { void handleSave() }}\n disabled={saving || !hasChanges}\n className=\"rounded-md bg-foreground px-4 py-2 text-sm font-semibold text-background hover:bg-foreground/90\"\n >\n <Check className=\"mr-2 size-3.5\" />\n {saving\n ? t('customers.personTags.saving', 'Saving...')\n : t('customers.personTags.save', 'Save')}\n </Button>\n </div>\n </div>\n </DialogContent>\n\n <ManageTagsDialog\n open={manageTagsOpen}\n onClose={() => {\n setManageTagsOpen(false)\n void loadData()\n }}\n />\n </Dialog>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["assignedLabelIds", "selectedLabelEntries"]
7
7
  }