@open-mercato/core 0.10.1-develop.7761.1.9dfaf470ed → 0.10.1-develop.7763.1.caea616ebf

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 (92) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/auth/api/profile/route.js +16 -2
  3. package/dist/modules/auth/api/profile/route.js.map +2 -2
  4. package/dist/modules/auth/lib/userDataSubject.js +26 -0
  5. package/dist/modules/auth/lib/userDataSubject.js.map +7 -0
  6. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +1 -0
  7. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
  8. package/dist/modules/customers/api/companies/[id]/route.js +3 -2
  9. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  10. package/dist/modules/customers/api/deals/[id]/route.js +11 -12
  11. package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
  12. package/dist/modules/customers/api/people/[id]/route.js +3 -2
  13. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  14. package/dist/modules/customers/backend/customers/companies/create/page.js +6 -0
  15. package/dist/modules/customers/backend/customers/companies/create/page.js.map +2 -2
  16. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +25 -25
  17. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  18. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js +8 -27
  19. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js.map +2 -2
  20. package/dist/modules/customers/backend/customers/deals/[id]/page.js +175 -171
  21. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  22. package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js +25 -24
  23. package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js.map +2 -2
  24. package/dist/modules/customers/backend/customers/people/create/page.js +9 -0
  25. package/dist/modules/customers/backend/customers/people/create/page.js.map +2 -2
  26. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +140 -144
  27. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  28. package/dist/modules/customers/components/detail/CompanyDetailHeader.js +2 -0
  29. package/dist/modules/customers/components/detail/CompanyDetailHeader.js.map +2 -2
  30. package/dist/modules/customers/components/detail/CompanyDetailTabs.js +13 -4
  31. package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
  32. package/dist/modules/customers/components/detail/CreatePersonDialog.js +13 -3
  33. package/dist/modules/customers/components/detail/CreatePersonDialog.js.map +2 -2
  34. package/dist/modules/customers/components/detail/CustomerDetailSidebar.js +29 -0
  35. package/dist/modules/customers/components/detail/CustomerDetailSidebar.js.map +7 -0
  36. package/dist/modules/customers/components/detail/DealDetailHeader.js +4 -2
  37. package/dist/modules/customers/components/detail/DealDetailHeader.js.map +2 -2
  38. package/dist/modules/customers/components/detail/DealDetailTabs.js +9 -1
  39. package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
  40. package/dist/modules/customers/components/detail/DealForm.js +5 -0
  41. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  42. package/dist/modules/customers/components/detail/PersonDetailHeader.js +2 -0
  43. package/dist/modules/customers/components/detail/PersonDetailHeader.js.map +2 -2
  44. package/dist/modules/customers/components/detail/PersonDetailTabs.js +9 -1
  45. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  46. package/dist/modules/customers/components/detail/create/CreateDealForm.js +160 -176
  47. package/dist/modules/customers/components/detail/create/CreateDealForm.js.map +2 -2
  48. package/dist/modules/customers/components/detail/useCustomerInjectedTabs.js +47 -0
  49. package/dist/modules/customers/components/detail/useCustomerInjectedTabs.js.map +7 -0
  50. package/dist/modules/customers/components/formConfig.js +3 -0
  51. package/dist/modules/customers/components/formConfig.js.map +2 -2
  52. package/dist/modules/customers/extension-points.js +14 -4
  53. package/dist/modules/customers/extension-points.js.map +2 -2
  54. package/dist/modules/customers/lib/detailResponseEnrichment.js +38 -0
  55. package/dist/modules/customers/lib/detailResponseEnrichment.js.map +7 -0
  56. package/dist/modules/dashboards/api/layout/[itemId]/route.js +11 -4
  57. package/dist/modules/dashboards/api/layout/[itemId]/route.js.map +2 -2
  58. package/dist/modules/dashboards/api/layout/route.js +25 -13
  59. package/dist/modules/dashboards/api/layout/route.js.map +2 -2
  60. package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js +4 -4
  61. package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js.map +2 -2
  62. package/package.json +7 -7
  63. package/src/modules/auth/api/profile/route.ts +15 -1
  64. package/src/modules/auth/lib/userDataSubject.ts +30 -0
  65. package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +2 -0
  66. package/src/modules/customers/api/companies/[id]/route.ts +3 -2
  67. package/src/modules/customers/api/deals/[id]/route.ts +12 -12
  68. package/src/modules/customers/api/people/[id]/route.ts +3 -2
  69. package/src/modules/customers/backend/customers/companies/create/page.tsx +6 -0
  70. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +27 -30
  71. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.tsx +9 -44
  72. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +7 -3
  73. package/src/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.tsx +25 -27
  74. package/src/modules/customers/backend/customers/people/create/page.tsx +9 -0
  75. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +21 -33
  76. package/src/modules/customers/components/detail/CompanyDetailHeader.tsx +3 -0
  77. package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +15 -4
  78. package/src/modules/customers/components/detail/CreatePersonDialog.tsx +15 -4
  79. package/src/modules/customers/components/detail/CustomerDetailSidebar.tsx +41 -0
  80. package/src/modules/customers/components/detail/DealDetailHeader.tsx +4 -1
  81. package/src/modules/customers/components/detail/DealDetailTabs.tsx +11 -1
  82. package/src/modules/customers/components/detail/DealForm.tsx +5 -0
  83. package/src/modules/customers/components/detail/PersonDetailHeader.tsx +3 -0
  84. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +11 -1
  85. package/src/modules/customers/components/detail/create/CreateDealForm.tsx +126 -209
  86. package/src/modules/customers/components/detail/useCustomerInjectedTabs.tsx +64 -0
  87. package/src/modules/customers/components/formConfig.tsx +3 -0
  88. package/src/modules/customers/extension-points.ts +14 -4
  89. package/src/modules/customers/lib/detailResponseEnrichment.ts +53 -0
  90. package/src/modules/dashboards/api/layout/[itemId]/route.ts +12 -4
  91. package/src/modules/dashboards/api/layout/route.ts +25 -12
  92. package/src/modules/integrations/widgets/injection/external-ids/widget.client.tsx +4 -4
@@ -10,6 +10,7 @@ import { Page, PageBody } from "@open-mercato/ui/backend/Page";
10
10
  import { Button } from "@open-mercato/ui/primitives/button";
11
11
  import { AttachmentsSection, ErrorMessage, LoadingMessage, NotesSection, RecordNotFoundState } from "@open-mercato/ui/backend/detail";
12
12
  import { InjectionSpot } from "@open-mercato/ui/backend/injection/InjectionSpot";
13
+ import { CustomerDetailSidebar } from "../../../../components/detail/CustomerDetailSidebar.js";
13
14
  import { buildRecordInjectionContext, useSetCurrentRecordInjectionContext } from "@open-mercato/ui/backend/injection/recordContext";
14
15
  import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
15
16
  import { CollapsibleZoneLayout } from "@open-mercato/ui/backend/crud/CollapsibleZoneLayout";
@@ -86,7 +87,7 @@ function DealDetailPage({ params }) {
86
87
  () => createCustomerNotesAdapter(detailTranslator, { runMutation: runMutationWithContext }),
87
88
  [detailTranslator, runMutationWithContext]
88
89
  );
89
- const { injectedTabs, injectedTabMap } = useDealInjectedTabs({
90
+ const { injectedTabs, injectedTabMap, loading: injectedTabsLoading } = useDealInjectedTabs({
90
91
  injectionContext,
91
92
  data,
92
93
  setData
@@ -348,193 +349,195 @@ function DealDetailPage({ params }) {
348
349
  onDelete: handleDelete
349
350
  }
350
351
  ) });
351
- const zone2Content = /* @__PURE__ */ jsx("div", { className: "rounded-[10px] border border-border bg-card px-5 py-5", children: (() => {
352
- const injected = injectedTabMap.get(activeTab);
353
- if (injected) return injected();
354
- if (activeTab === "activities") {
355
- const activityEntitySelection = activityEntities.length > 1 ? /* @__PURE__ */ jsxs("div", { className: "rounded-[10px] border border-border bg-muted/20 px-5 py-5", children: [
356
- /* @__PURE__ */ jsx("label", { htmlFor: "deal-activity-entity", className: "text-sm font-semibold text-foreground", children: t("customers.deals.detail.activities.selectEntityLabel", "Choose customer record") }),
357
- /* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-muted-foreground", children: t(
358
- "customers.deals.detail.activities.selectEntityDescription",
359
- "Pick the person or company that should own new deal activities and follow-ups."
360
- ) }),
361
- /* @__PURE__ */ jsxs(
362
- "select",
363
- {
364
- id: "deal-activity-entity",
365
- "aria-label": t("customers.deals.detail.activities.selectEntityLabel", "Choose customer record"),
366
- className: "mt-4 h-9 w-full rounded border border-muted-foreground/40 bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
367
- value: selectedActivityEntityId ?? "",
368
- onChange: (event) => setSelectedActivityEntityId(event.target.value || null),
369
- children: [
370
- /* @__PURE__ */ jsx("option", { value: "", children: t("customers.deals.detail.activities.selectEntityPlaceholder", "Select a person or company") }),
371
- activityEntities.map((entry) => /* @__PURE__ */ jsx("option", { value: entry.id, children: entry.label }, entry.id))
372
- ]
373
- }
374
- )
375
- ] }) : null;
376
- return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
377
- activityEntities.length > 1 ? activityEntitySelection : null,
378
- activityEntities.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-[10px] border border-border bg-muted/20 px-5 py-5", children: [
379
- /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold text-foreground", children: t("customers.deals.detail.activities.linkEntityTitle", "Link a person or company first") }),
380
- /* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-muted-foreground", children: t("customers.deals.detail.activities.linkEntityDescription", "Activities on a deal still need a customer record for timeline ownership.") }),
381
- /* @__PURE__ */ jsxs("div", { className: "mt-4 flex gap-2", children: [
382
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => handleTabChange("people"), children: t("customers.deals.detail.tabs.people", "People") }),
383
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => handleTabChange("companies"), children: t("customers.deals.detail.tabs.companies", "Companies") })
384
- ] })
385
- ] }) : selectedActivityEntity ? /* @__PURE__ */ jsx(
386
- InlineActivityComposer,
352
+ const zone2Content = /* @__PURE__ */ jsxs("div", { className: "rounded-[10px] border border-border bg-card px-5 py-5", children: [
353
+ (() => {
354
+ if (activeTab === "activities") {
355
+ const activityEntitySelection = activityEntities.length > 1 ? /* @__PURE__ */ jsxs("div", { className: "rounded-[10px] border border-border bg-muted/20 px-5 py-5", children: [
356
+ /* @__PURE__ */ jsx("label", { htmlFor: "deal-activity-entity", className: "text-sm font-semibold text-foreground", children: t("customers.deals.detail.activities.selectEntityLabel", "Choose customer record") }),
357
+ /* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-muted-foreground", children: t(
358
+ "customers.deals.detail.activities.selectEntityDescription",
359
+ "Pick the person or company that should own new deal activities and follow-ups."
360
+ ) }),
361
+ /* @__PURE__ */ jsxs(
362
+ "select",
363
+ {
364
+ id: "deal-activity-entity",
365
+ "aria-label": t("customers.deals.detail.activities.selectEntityLabel", "Choose customer record"),
366
+ className: "mt-4 h-9 w-full rounded border border-muted-foreground/40 bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
367
+ value: selectedActivityEntityId ?? "",
368
+ onChange: (event) => setSelectedActivityEntityId(event.target.value || null),
369
+ children: [
370
+ /* @__PURE__ */ jsx("option", { value: "", children: t("customers.deals.detail.activities.selectEntityPlaceholder", "Select a person or company") }),
371
+ activityEntities.map((entry) => /* @__PURE__ */ jsx("option", { value: entry.id, children: entry.label }, entry.id))
372
+ ]
373
+ }
374
+ )
375
+ ] }) : null;
376
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
377
+ activityEntities.length > 1 ? activityEntitySelection : null,
378
+ activityEntities.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-[10px] border border-border bg-muted/20 px-5 py-5", children: [
379
+ /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold text-foreground", children: t("customers.deals.detail.activities.linkEntityTitle", "Link a person or company first") }),
380
+ /* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-muted-foreground", children: t("customers.deals.detail.activities.linkEntityDescription", "Activities on a deal still need a customer record for timeline ownership.") }),
381
+ /* @__PURE__ */ jsxs("div", { className: "mt-4 flex gap-2", children: [
382
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => handleTabChange("people"), children: t("customers.deals.detail.tabs.people", "People") }),
383
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => handleTabChange("companies"), children: t("customers.deals.detail.tabs.companies", "Companies") })
384
+ ] })
385
+ ] }) : selectedActivityEntity ? /* @__PURE__ */ jsx(
386
+ InlineActivityComposer,
387
+ {
388
+ entityType: selectedActivityEntity.kind,
389
+ entityId: selectedActivityEntity.id,
390
+ dealId: data.deal.id,
391
+ onActivityCreated: () => {
392
+ void handleActivityCreated();
393
+ },
394
+ runGuardedMutation: runMutationWithContext,
395
+ onScheduleRequested: openSchedule
396
+ }
397
+ ) : /* @__PURE__ */ jsx(
398
+ EmptyState,
399
+ {
400
+ size: "sm",
401
+ icon: /* @__PURE__ */ jsx(UserSearch, { className: "h-8 w-8", "aria-hidden": "true" }),
402
+ title: t("customers.deals.detail.activities.selectEntityRequiredTitle", "Choose a person or company to continue"),
403
+ description: t(
404
+ "customers.deals.detail.activities.selectEntityRequiredDescription",
405
+ "Select the customer record that should receive new deal activities before logging or scheduling anything."
406
+ )
407
+ }
408
+ ),
409
+ /* @__PURE__ */ jsx(
410
+ PlannedActivitiesSection,
411
+ {
412
+ activities: plannedActivities,
413
+ onComplete: (interactionId) => {
414
+ void handleMarkDone(interactionId);
415
+ },
416
+ onSchedule: selectedActivityEntity ? openSchedule : void 0,
417
+ onEdit: handleEditActivity,
418
+ onCancel: (interactionId) => {
419
+ void handleCancelActivity(interactionId);
420
+ }
421
+ }
422
+ ),
423
+ selectedActivityEntity ? /* @__PURE__ */ jsx(
424
+ ActivitiesSection,
425
+ {
426
+ entityId: selectedActivityEntity.id,
427
+ entityName: selectedActivityEntity.label,
428
+ dealId: data.deal.id,
429
+ dealOptions,
430
+ entityOptions,
431
+ defaultEntityId: selectedActivityEntity.id,
432
+ addActionLabel: t("customers.deals.detail.activitiesAdd", "Log activity"),
433
+ emptyState: {
434
+ title: t("customers.deals.detail.activitiesEmptyTitle", "No activities yet"),
435
+ actionLabel: t("customers.deals.detail.activitiesEmptyAction", "Log activity")
436
+ },
437
+ runGuardedMutation: runMutationWithContext,
438
+ onDataRefresh: () => {
439
+ void handleActivityCreated();
440
+ },
441
+ refreshKey: activityRefreshKey,
442
+ onEditActivity: handleEditActivity
443
+ }
444
+ ) : null
445
+ ] });
446
+ }
447
+ if (activeTab === "people") {
448
+ return /* @__PURE__ */ jsx(
449
+ DealPeopleSection,
387
450
  {
388
- entityType: selectedActivityEntity.kind,
389
- entityId: selectedActivityEntity.id,
390
451
  dealId: data.deal.id,
391
- onActivityCreated: () => {
392
- void handleActivityCreated();
452
+ dealName,
453
+ selectedIds: peopleEditorIds,
454
+ onSaveSelection: (next) => handlePeopleAssociationsChange(next),
455
+ addActionLabel: t("customers.deals.detail.peopleAdd", "Add person"),
456
+ disabled: peopleSaving || isSaving,
457
+ emptyLabel: t("customers.deals.detail.peopleEmpty", "No people linked to this deal yet."),
458
+ emptyState: {
459
+ title: t("customers.deals.detail.peopleEmptyTitle", "Link the people involved"),
460
+ actionLabel: t("customers.deals.detail.peopleEmptyAction", "Add person")
393
461
  },
394
- runGuardedMutation: runMutationWithContext,
395
- onScheduleRequested: openSchedule
396
- }
397
- ) : /* @__PURE__ */ jsx(
398
- EmptyState,
399
- {
400
- size: "sm",
401
- icon: /* @__PURE__ */ jsx(UserSearch, { className: "h-8 w-8", "aria-hidden": "true" }),
402
- title: t("customers.deals.detail.activities.selectEntityRequiredTitle", "Choose a person or company to continue"),
403
- description: t(
404
- "customers.deals.detail.activities.selectEntityRequiredDescription",
405
- "Select the customer record that should receive new deal activities before logging or scheduling anything."
406
- )
462
+ translator: detailTranslator,
463
+ runGuardedMutation: runMutationWithContext
407
464
  }
408
- ),
409
- /* @__PURE__ */ jsx(
410
- PlannedActivitiesSection,
465
+ );
466
+ }
467
+ if (activeTab === "companies") {
468
+ return /* @__PURE__ */ jsx(
469
+ DealLinkedEntitiesTab,
411
470
  {
412
- activities: plannedActivities,
413
- onComplete: (interactionId) => {
414
- void handleMarkDone(interactionId);
415
- },
416
- onSchedule: selectedActivityEntity ? openSchedule : void 0,
417
- onEdit: handleEditActivity,
418
- onCancel: (interactionId) => {
419
- void handleCancelActivity(interactionId);
420
- }
471
+ entityLabel: t("customers.deals.detail.tabs.companySingular", "Company"),
472
+ entityLabelPlural: t("customers.deals.detail.tabs.companies", "Companies"),
473
+ manageLabel: t("customers.deals.detail.companiesEditorTitle", "Manage linked companies"),
474
+ searchPlaceholder: t("customers.deals.detail.companiesSearch", "Search linked companies\u2026"),
475
+ linkedItems: data.companies,
476
+ linkedCount: data.counts.companies,
477
+ selectedIds: companiesEditorIds,
478
+ disabled: companiesSaving || isSaving,
479
+ savePending: companiesSaving,
480
+ hrefBuilder: (companyId) => `/backend/customers/companies-v2/${encodeURIComponent(companyId)}`,
481
+ onSaveSelection: (next) => handleCompaniesAssociationsChange(next),
482
+ loadLinkedPage: loadLinkedCompaniesPage,
483
+ searchEntities: searchCompaniesPage,
484
+ fetchEntitiesByIds: fetchCompaniesByIds,
485
+ icon: /* @__PURE__ */ jsx(Building2, { className: "size-4" })
421
486
  }
422
- ),
423
- selectedActivityEntity ? /* @__PURE__ */ jsx(
424
- ActivitiesSection,
487
+ );
488
+ }
489
+ if (activeTab === "notes") {
490
+ return /* @__PURE__ */ jsx(
491
+ NotesSection,
425
492
  {
426
- entityId: selectedActivityEntity.id,
427
- entityName: selectedActivityEntity.label,
493
+ entityId: null,
428
494
  dealId: data.deal.id,
429
495
  dealOptions,
430
496
  entityOptions,
431
- defaultEntityId: selectedActivityEntity.id,
432
- addActionLabel: t("customers.deals.detail.activitiesAdd", "Log activity"),
497
+ emptyLabel: t("customers.deals.detail.notesEmpty", "No notes yet."),
498
+ viewerUserId: data.viewer?.userId ?? null,
499
+ viewerName: data.viewer?.name ?? null,
500
+ viewerEmail: data.viewer?.email ?? null,
501
+ addActionLabel: t("customers.deals.detail.notesAdd", "Add note"),
433
502
  emptyState: {
434
- title: t("customers.deals.detail.activitiesEmptyTitle", "No activities yet"),
435
- actionLabel: t("customers.deals.detail.activitiesEmptyAction", "Log activity")
436
- },
437
- runGuardedMutation: runMutationWithContext,
438
- onDataRefresh: () => {
439
- void handleActivityCreated();
503
+ title: t("customers.deals.detail.notesEmptyTitle", "Keep everyone in the loop"),
504
+ actionLabel: t("customers.deals.detail.notesEmptyAction", "Add a note")
440
505
  },
441
- refreshKey: activityRefreshKey,
442
- onEditActivity: handleEditActivity
506
+ translator: detailTranslator,
507
+ dataAdapter: notesAdapter,
508
+ renderIcon: renderDictionaryIcon,
509
+ renderColor: renderDictionaryColor,
510
+ iconSuggestions: ICON_SUGGESTIONS,
511
+ readMarkdownPreference: readMarkdownPreferenceCookie,
512
+ writeMarkdownPreference: writeMarkdownPreferenceCookie
443
513
  }
444
- ) : null
445
- ] });
446
- }
447
- if (activeTab === "people") {
448
- return /* @__PURE__ */ jsx(
449
- DealPeopleSection,
450
- {
451
- dealId: data.deal.id,
452
- dealName,
453
- selectedIds: peopleEditorIds,
454
- onSaveSelection: (next) => handlePeopleAssociationsChange(next),
455
- addActionLabel: t("customers.deals.detail.peopleAdd", "Add person"),
456
- disabled: peopleSaving || isSaving,
457
- emptyLabel: t("customers.deals.detail.peopleEmpty", "No people linked to this deal yet."),
458
- emptyState: {
459
- title: t("customers.deals.detail.peopleEmptyTitle", "Link the people involved"),
460
- actionLabel: t("customers.deals.detail.peopleEmptyAction", "Add person")
461
- },
462
- translator: detailTranslator,
463
- runGuardedMutation: runMutationWithContext
464
- }
465
- );
466
- }
467
- if (activeTab === "companies") {
468
- return /* @__PURE__ */ jsx(
469
- DealLinkedEntitiesTab,
470
- {
471
- entityLabel: t("customers.deals.detail.tabs.companySingular", "Company"),
472
- entityLabelPlural: t("customers.deals.detail.tabs.companies", "Companies"),
473
- manageLabel: t("customers.deals.detail.companiesEditorTitle", "Manage linked companies"),
474
- searchPlaceholder: t("customers.deals.detail.companiesSearch", "Search linked companies\u2026"),
475
- linkedItems: data.companies,
476
- linkedCount: data.counts.companies,
477
- selectedIds: companiesEditorIds,
478
- disabled: companiesSaving || isSaving,
479
- savePending: companiesSaving,
480
- hrefBuilder: (companyId) => `/backend/customers/companies-v2/${encodeURIComponent(companyId)}`,
481
- onSaveSelection: (next) => handleCompaniesAssociationsChange(next),
482
- loadLinkedPage: loadLinkedCompaniesPage,
483
- searchEntities: searchCompaniesPage,
484
- fetchEntitiesByIds: fetchCompaniesByIds,
485
- icon: /* @__PURE__ */ jsx(Building2, { className: "size-4" })
486
- }
487
- );
488
- }
489
- if (activeTab === "notes") {
490
- return /* @__PURE__ */ jsx(
491
- NotesSection,
492
- {
493
- entityId: null,
494
- dealId: data.deal.id,
495
- dealOptions,
496
- entityOptions,
497
- emptyLabel: t("customers.deals.detail.notesEmpty", "No notes yet."),
498
- viewerUserId: data.viewer?.userId ?? null,
499
- viewerName: data.viewer?.name ?? null,
500
- viewerEmail: data.viewer?.email ?? null,
501
- addActionLabel: t("customers.deals.detail.notesAdd", "Add note"),
502
- emptyState: {
503
- title: t("customers.deals.detail.notesEmptyTitle", "Keep everyone in the loop"),
504
- actionLabel: t("customers.deals.detail.notesEmptyAction", "Add a note")
505
- },
506
- translator: detailTranslator,
507
- dataAdapter: notesAdapter,
508
- renderIcon: renderDictionaryIcon,
509
- renderColor: renderDictionaryColor,
510
- iconSuggestions: ICON_SUGGESTIONS,
511
- readMarkdownPreference: readMarkdownPreferenceCookie,
512
- writeMarkdownPreference: writeMarkdownPreferenceCookie
513
- }
514
- );
515
- }
516
- if (activeTab === "files") {
517
- return /* @__PURE__ */ jsx(
518
- AttachmentsSection,
519
- {
520
- entityId: E.customers.customer_deal,
521
- recordId: data.deal.id,
522
- title: t("customers.deals.detail.tabs.files", "Files"),
523
- description: t("customers.deals.detail.files.subtitle", "Upload and manage files linked to this deal.")
524
- }
525
- );
526
- }
527
- if (activeTab === "changelog") {
528
- return /* @__PURE__ */ jsx(ChangelogTab, { entityId: data.deal.id, entityType: "deal" });
529
- }
530
- return null;
531
- })() });
514
+ );
515
+ }
516
+ if (activeTab === "files") {
517
+ return /* @__PURE__ */ jsx(
518
+ AttachmentsSection,
519
+ {
520
+ entityId: E.customers.customer_deal,
521
+ recordId: data.deal.id,
522
+ title: t("customers.deals.detail.tabs.files", "Files"),
523
+ description: t("customers.deals.detail.files.subtitle", "Upload and manage files linked to this deal.")
524
+ }
525
+ );
526
+ }
527
+ if (activeTab === "changelog") {
528
+ return /* @__PURE__ */ jsx(ChangelogTab, { entityId: data.deal.id, entityType: "deal" });
529
+ }
530
+ return null;
531
+ })(),
532
+ injectedTabMap.get(activeTab)?.()
533
+ ] });
532
534
  return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsxs(PageBody, { children: [
533
535
  /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
534
536
  /* @__PURE__ */ jsx(InjectionSpot, { spotId: extensionPoints.hosts.dealHeader.spotId, context: injectionContext, data }),
535
537
  /* @__PURE__ */ jsx(
536
538
  DealDetailHeader,
537
539
  {
540
+ actions: /* @__PURE__ */ jsx(InjectionSpot, { spotId: extensionPoints.hosts.dealHeaderActions.spotId, context: { ...injectionContext, isDirty, isSaving }, data, disabled: isSaving }),
538
541
  deal: data.deal,
539
542
  owner: data.owner,
540
543
  people: data.people,
@@ -572,9 +575,10 @@ function DealDetailPage({ params }) {
572
575
  )
573
576
  }
574
577
  ),
575
- /* @__PURE__ */ jsx(
578
+ /* @__PURE__ */ jsx(CustomerDetailSidebar, { spotId: extensionPoints.hosts.dealSidebar.spotId, context: injectionContext, data, onDataChange: setData, disabled: isSaving, children: /* @__PURE__ */ jsx(
576
579
  DealDetailTabs,
577
580
  {
581
+ isLoadingInjectedTabs: injectedTabsLoading,
578
582
  activeTab,
579
583
  onTabChange: handleTabChange,
580
584
  injectedTabs: injectedTabs.map((tab) => ({ id: tab.id, label: tab.label })),
@@ -593,7 +597,7 @@ function DealDetailPage({ params }) {
593
597
  }
594
598
  )
595
599
  }
596
- ),
600
+ ) }),
597
601
  /* @__PURE__ */ jsx(InjectionSpot, { spotId: extensionPoints.hosts.dealFooter.spotId, context: injectionContext, data })
598
602
  ] }),
599
603
  ConfirmDialogElement,