@open-mercato/core 0.6.3-develop.3635.1.e4a05c16e8 → 0.6.3-develop.3653.1.b8558737ae

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 (160) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities/customer_settings/index.js +2 -0
  3. package/dist/generated/entities/customer_settings/index.js.map +2 -2
  4. package/dist/generated/entity-fields-registry.js +1 -0
  5. package/dist/generated/entity-fields-registry.js.map +2 -2
  6. package/dist/modules/customers/api/deals/aggregate/route.js +332 -0
  7. package/dist/modules/customers/api/deals/aggregate/route.js.map +7 -0
  8. package/dist/modules/customers/api/deals/bulk-update-owner/route.js +188 -0
  9. package/dist/modules/customers/api/deals/bulk-update-owner/route.js.map +7 -0
  10. package/dist/modules/customers/api/deals/bulk-update-stage/route.js +188 -0
  11. package/dist/modules/customers/api/deals/bulk-update-stage/route.js.map +7 -0
  12. package/dist/modules/customers/api/deals/route.js +255 -122
  13. package/dist/modules/customers/api/deals/route.js.map +2 -2
  14. package/dist/modules/customers/api/settings/stuck-threshold/route.js +169 -0
  15. package/dist/modules/customers/api/settings/stuck-threshold/route.js.map +7 -0
  16. package/dist/modules/customers/backend/config/customers/deals/page.js +181 -0
  17. package/dist/modules/customers/backend/config/customers/deals/page.js.map +7 -0
  18. package/dist/modules/customers/backend/config/customers/deals/page.meta.js +38 -0
  19. package/dist/modules/customers/backend/config/customers/deals/page.meta.js.map +7 -0
  20. package/dist/modules/customers/backend/customers/deals/create/page.js +17 -6
  21. package/dist/modules/customers/backend/customers/deals/create/page.js.map +2 -2
  22. package/dist/modules/customers/backend/customers/deals/page.js +2 -0
  23. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  24. package/dist/modules/customers/backend/customers/deals/pipeline/components/ActivityComposerDialog.js +217 -0
  25. package/dist/modules/customers/backend/customers/deals/pipeline/components/ActivityComposerDialog.js.map +7 -0
  26. package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageDialog.js +335 -0
  27. package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageDialog.js.map +7 -0
  28. package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageLane.js +29 -0
  29. package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageLane.js.map +7 -0
  30. package/dist/modules/customers/backend/customers/deals/pipeline/components/BulkActionsBar.js +160 -0
  31. package/dist/modules/customers/backend/customers/deals/pipeline/components/BulkActionsBar.js.map +7 -0
  32. package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.js +157 -0
  33. package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.js.map +7 -0
  34. package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeStageDialog.js +114 -0
  35. package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeStageDialog.js.map +7 -0
  36. package/dist/modules/customers/backend/customers/deals/pipeline/components/ChipButton.js +36 -0
  37. package/dist/modules/customers/backend/customers/deals/pipeline/components/ChipButton.js.map +7 -0
  38. package/dist/modules/customers/backend/customers/deals/pipeline/components/CloseDateFilterPopover.js +199 -0
  39. package/dist/modules/customers/backend/customers/deals/pipeline/components/CloseDateFilterPopover.js.map +7 -0
  40. package/dist/modules/customers/backend/customers/deals/pipeline/components/CurrencyBreakdownTable.js +71 -0
  41. package/dist/modules/customers/backend/customers/deals/pipeline/components/CurrencyBreakdownTable.js.map +7 -0
  42. package/dist/modules/customers/backend/customers/deals/pipeline/components/CurrencyFilterPopover.js +233 -0
  43. package/dist/modules/customers/backend/customers/deals/pipeline/components/CurrencyFilterPopover.js.map +7 -0
  44. package/dist/modules/customers/backend/customers/deals/pipeline/components/CustomizeViewDialog.js +126 -0
  45. package/dist/modules/customers/backend/customers/deals/pipeline/components/CustomizeViewDialog.js.map +7 -0
  46. package/dist/modules/customers/backend/customers/deals/pipeline/components/DashedTileButton.js +31 -0
  47. package/dist/modules/customers/backend/customers/deals/pipeline/components/DashedTileButton.js.map +7 -0
  48. package/dist/modules/customers/backend/customers/deals/pipeline/components/DealCard.js +389 -0
  49. package/dist/modules/customers/backend/customers/deals/pipeline/components/DealCard.js.map +7 -0
  50. package/dist/modules/customers/backend/customers/deals/pipeline/components/DealCardMenu.js +181 -0
  51. package/dist/modules/customers/backend/customers/deals/pipeline/components/DealCardMenu.js.map +7 -0
  52. package/dist/modules/customers/backend/customers/deals/pipeline/components/EntityFilterPopover.js +199 -0
  53. package/dist/modules/customers/backend/customers/deals/pipeline/components/EntityFilterPopover.js.map +7 -0
  54. package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.js +44 -0
  55. package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.js.map +7 -0
  56. package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterPopoverShell.js +70 -0
  57. package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterPopoverShell.js.map +7 -0
  58. package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js +278 -0
  59. package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js.map +7 -0
  60. package/dist/modules/customers/backend/customers/deals/pipeline/components/LaneCurrencyBreakdown.js +135 -0
  61. package/dist/modules/customers/backend/customers/deals/pipeline/components/LaneCurrencyBreakdown.js.map +7 -0
  62. package/dist/modules/customers/backend/customers/deals/pipeline/components/LaneResizeHandle.js +83 -0
  63. package/dist/modules/customers/backend/customers/deals/pipeline/components/LaneResizeHandle.js.map +7 -0
  64. package/dist/modules/customers/backend/customers/deals/pipeline/components/PipelineFilterPopover.js +155 -0
  65. package/dist/modules/customers/backend/customers/deals/pipeline/components/PipelineFilterPopover.js.map +7 -0
  66. package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js +318 -0
  67. package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js.map +7 -0
  68. package/dist/modules/customers/backend/customers/deals/pipeline/components/SortByPopover.js +138 -0
  69. package/dist/modules/customers/backend/customers/deals/pipeline/components/SortByPopover.js.map +7 -0
  70. package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js +126 -0
  71. package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js.map +7 -0
  72. package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js +71 -0
  73. package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js.map +7 -0
  74. package/dist/modules/customers/backend/customers/deals/pipeline/components/constants.js +7 -0
  75. package/dist/modules/customers/backend/customers/deals/pipeline/components/constants.js.map +7 -0
  76. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +2330 -415
  77. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +3 -3
  78. package/dist/modules/customers/commands/deals.js +6 -0
  79. package/dist/modules/customers/commands/deals.js.map +2 -2
  80. package/dist/modules/customers/commands/pipeline-stages.js +48 -13
  81. package/dist/modules/customers/commands/pipeline-stages.js.map +3 -3
  82. package/dist/modules/customers/commands/settings.js +45 -5
  83. package/dist/modules/customers/commands/settings.js.map +2 -2
  84. package/dist/modules/customers/data/enrichers.js +130 -1
  85. package/dist/modules/customers/data/enrichers.js.map +2 -2
  86. package/dist/modules/customers/data/entities.js +4 -0
  87. package/dist/modules/customers/data/entities.js.map +2 -2
  88. package/dist/modules/customers/data/validators.js +29 -2
  89. package/dist/modules/customers/data/validators.js.map +2 -2
  90. package/dist/modules/customers/lib/bulkDeals.js +150 -0
  91. package/dist/modules/customers/lib/bulkDeals.js.map +7 -0
  92. package/dist/modules/customers/lib/kysely.js +12 -0
  93. package/dist/modules/customers/lib/kysely.js.map +7 -0
  94. package/dist/modules/customers/lib/stuckDeals.js +32 -0
  95. package/dist/modules/customers/lib/stuckDeals.js.map +7 -0
  96. package/dist/modules/customers/migrations/Migration20260513203311_customers.js +13 -0
  97. package/dist/modules/customers/migrations/Migration20260513203311_customers.js.map +7 -0
  98. package/dist/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.js +52 -0
  99. package/dist/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.js.map +7 -0
  100. package/dist/modules/customers/workers/deals-bulk-update-owner.js +41 -0
  101. package/dist/modules/customers/workers/deals-bulk-update-owner.js.map +7 -0
  102. package/dist/modules/customers/workers/deals-bulk-update-stage.js +41 -0
  103. package/dist/modules/customers/workers/deals-bulk-update-stage.js.map +7 -0
  104. package/generated/entities/customer_settings/index.ts +1 -0
  105. package/generated/entity-fields-registry.ts +1 -0
  106. package/package.json +7 -7
  107. package/src/modules/customers/api/deals/aggregate/route.ts +438 -0
  108. package/src/modules/customers/api/deals/bulk-update-owner/route.ts +216 -0
  109. package/src/modules/customers/api/deals/bulk-update-stage/route.ts +228 -0
  110. package/src/modules/customers/api/deals/route.ts +330 -135
  111. package/src/modules/customers/api/settings/stuck-threshold/route.ts +195 -0
  112. package/src/modules/customers/backend/config/customers/deals/page.meta.ts +36 -0
  113. package/src/modules/customers/backend/config/customers/deals/page.tsx +205 -0
  114. package/src/modules/customers/backend/customers/deals/create/page.tsx +25 -6
  115. package/src/modules/customers/backend/customers/deals/page.tsx +2 -0
  116. package/src/modules/customers/backend/customers/deals/pipeline/components/ActivityComposerDialog.tsx +277 -0
  117. package/src/modules/customers/backend/customers/deals/pipeline/components/AddStageDialog.tsx +425 -0
  118. package/src/modules/customers/backend/customers/deals/pipeline/components/AddStageLane.tsx +31 -0
  119. package/src/modules/customers/backend/customers/deals/pipeline/components/BulkActionsBar.tsx +171 -0
  120. package/src/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.tsx +196 -0
  121. package/src/modules/customers/backend/customers/deals/pipeline/components/ChangeStageDialog.tsx +138 -0
  122. package/src/modules/customers/backend/customers/deals/pipeline/components/ChipButton.tsx +47 -0
  123. package/src/modules/customers/backend/customers/deals/pipeline/components/CloseDateFilterPopover.tsx +232 -0
  124. package/src/modules/customers/backend/customers/deals/pipeline/components/CurrencyBreakdownTable.tsx +110 -0
  125. package/src/modules/customers/backend/customers/deals/pipeline/components/CurrencyFilterPopover.tsx +310 -0
  126. package/src/modules/customers/backend/customers/deals/pipeline/components/CustomizeViewDialog.tsx +169 -0
  127. package/src/modules/customers/backend/customers/deals/pipeline/components/DashedTileButton.tsx +54 -0
  128. package/src/modules/customers/backend/customers/deals/pipeline/components/DealCard.tsx +562 -0
  129. package/src/modules/customers/backend/customers/deals/pipeline/components/DealCardMenu.tsx +214 -0
  130. package/src/modules/customers/backend/customers/deals/pipeline/components/EntityFilterPopover.tsx +257 -0
  131. package/src/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.tsx +62 -0
  132. package/src/modules/customers/backend/customers/deals/pipeline/components/FilterPopoverShell.tsx +101 -0
  133. package/src/modules/customers/backend/customers/deals/pipeline/components/Lane.tsx +378 -0
  134. package/src/modules/customers/backend/customers/deals/pipeline/components/LaneCurrencyBreakdown.tsx +192 -0
  135. package/src/modules/customers/backend/customers/deals/pipeline/components/LaneResizeHandle.tsx +107 -0
  136. package/src/modules/customers/backend/customers/deals/pipeline/components/PipelineFilterPopover.tsx +196 -0
  137. package/src/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.tsx +408 -0
  138. package/src/modules/customers/backend/customers/deals/pipeline/components/SortByPopover.tsx +164 -0
  139. package/src/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.tsx +171 -0
  140. package/src/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.tsx +84 -0
  141. package/src/modules/customers/backend/customers/deals/pipeline/components/constants.ts +16 -0
  142. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +2841 -550
  143. package/src/modules/customers/commands/deals.ts +19 -0
  144. package/src/modules/customers/commands/pipeline-stages.ts +68 -13
  145. package/src/modules/customers/commands/settings.ts +64 -5
  146. package/src/modules/customers/data/enrichers.ts +209 -2
  147. package/src/modules/customers/data/entities.ts +4 -1
  148. package/src/modules/customers/data/validators.ts +36 -2
  149. package/src/modules/customers/i18n/de.json +244 -0
  150. package/src/modules/customers/i18n/en.json +244 -0
  151. package/src/modules/customers/i18n/es.json +244 -0
  152. package/src/modules/customers/i18n/pl.json +244 -0
  153. package/src/modules/customers/lib/bulkDeals.ts +231 -0
  154. package/src/modules/customers/lib/kysely.ts +60 -0
  155. package/src/modules/customers/lib/stuckDeals.ts +88 -0
  156. package/src/modules/customers/migrations/.snapshot-open-mercato.json +16 -0
  157. package/src/modules/customers/migrations/Migration20260513203311_customers.ts +13 -0
  158. package/src/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.ts +71 -0
  159. package/src/modules/customers/workers/deals-bulk-update-owner.ts +46 -0
  160. package/src/modules/customers/workers/deals-bulk-update-stage.ts +46 -0
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
4
+ import { translateWithFallback } from "@open-mercato/shared/lib/i18n/translate";
5
+ import { DashedTileButton } from "./DashedTileButton.js";
6
+ import { LANE_WIDTH_CLASS } from "./constants.js";
7
+ function AddStageLane({ onClick, disabled = false }) {
8
+ const t = useT();
9
+ const label = translateWithFallback(t, "customers.deals.kanban.cta.newStage", "New stage");
10
+ return /* @__PURE__ */ jsxs(
11
+ DashedTileButton,
12
+ {
13
+ onClick,
14
+ disabled,
15
+ ariaLabel: label,
16
+ className: `${LANE_WIDTH_CLASS} flex-none flex-col rounded-xl px-3.5 py-5 text-muted-foreground hover:text-foreground min-h-[60vh]`,
17
+ children: [
18
+ /* @__PURE__ */ jsx("span", { className: "text-3xl font-bold leading-none", children: "+" }),
19
+ /* @__PURE__ */ jsx("span", { className: "text-base font-semibold leading-normal", children: label })
20
+ ]
21
+ }
22
+ );
23
+ }
24
+ var AddStageLane_default = AddStageLane;
25
+ export {
26
+ AddStageLane,
27
+ AddStageLane_default as default
28
+ };
29
+ //# sourceMappingURL=AddStageLane.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../src/modules/customers/backend/customers/deals/pipeline/components/AddStageLane.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { DashedTileButton } from './DashedTileButton'\nimport { LANE_WIDTH_CLASS } from './constants'\n\ntype AddStageLaneProps = {\n onClick: () => void\n disabled?: boolean\n}\n\nexport function AddStageLane({ onClick, disabled = false }: AddStageLaneProps): React.ReactElement {\n const t = useT()\n const label = translateWithFallback(t, 'customers.deals.kanban.cta.newStage', 'New stage')\n\n return (\n <DashedTileButton\n onClick={onClick}\n disabled={disabled}\n ariaLabel={label}\n className={`${LANE_WIDTH_CLASS} flex-none flex-col rounded-xl px-3.5 py-5 text-muted-foreground hover:text-foreground min-h-[60vh]`}\n >\n <span className=\"text-3xl font-bold leading-none\">+</span>\n <span className=\"text-base font-semibold leading-normal\">{label}</span>\n </DashedTileButton>\n )\n}\n\nexport default AddStageLane\n"],
5
+ "mappings": ";AAkBI,SAME,KANF;AAfJ,SAAS,YAAY;AACrB,SAAS,6BAA6B;AACtC,SAAS,wBAAwB;AACjC,SAAS,wBAAwB;AAO1B,SAAS,aAAa,EAAE,SAAS,WAAW,MAAM,GAA0C;AACjG,QAAM,IAAI,KAAK;AACf,QAAM,QAAQ,sBAAsB,GAAG,uCAAuC,WAAW;AAEzF,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX,WAAW,GAAG,gBAAgB;AAAA,MAE9B;AAAA,4BAAC,UAAK,WAAU,mCAAkC,eAAC;AAAA,QACnD,oBAAC,UAAK,WAAU,0CAA0C,iBAAM;AAAA;AAAA;AAAA,EAClE;AAEJ;AAEA,IAAO,uBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,160 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Download, Trash2, Workflow, UserCircle2, X } from "lucide-react";
5
+ import { Button } from "@open-mercato/ui/primitives/button";
6
+ import { IconButton } from "@open-mercato/ui/primitives/icon-button";
7
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
8
+ import { translateWithFallback } from "@open-mercato/shared/lib/i18n/translate";
9
+ function BulkActionsBar({
10
+ count,
11
+ totalLabel,
12
+ onChangeStage,
13
+ onChangeOwner,
14
+ onExportCsv,
15
+ onDelete,
16
+ onClear
17
+ }) {
18
+ const t = useT();
19
+ React.useEffect(() => {
20
+ if (count === 0) return;
21
+ const onKey = (event) => {
22
+ if (event.key !== "Escape") return;
23
+ const active = document.activeElement;
24
+ if (active) {
25
+ const tag = active.tagName;
26
+ if (tag === "INPUT" || tag === "TEXTAREA" || active.isContentEditable) return;
27
+ }
28
+ event.preventDefault();
29
+ onClear();
30
+ };
31
+ document.addEventListener("keydown", onKey);
32
+ return () => document.removeEventListener("keydown", onKey);
33
+ }, [count, onClear]);
34
+ if (count === 0) return null;
35
+ return /* @__PURE__ */ jsxs(
36
+ "div",
37
+ {
38
+ role: "region",
39
+ "aria-label": translateWithFallback(
40
+ t,
41
+ "customers.deals.kanban.bulk.aria.bar",
42
+ "Bulk actions"
43
+ ),
44
+ className: "fixed bottom-6 left-1/2 z-toast flex w-[min(960px,calc(100%-2rem))] -translate-x-1/2 items-center gap-3 rounded-lg bg-foreground px-4 py-3 text-background shadow-xl",
45
+ children: [
46
+ /* @__PURE__ */ jsx(
47
+ IconButton,
48
+ {
49
+ variant: "ghost",
50
+ size: "xs",
51
+ onClick: onClear,
52
+ "aria-label": translateWithFallback(
53
+ t,
54
+ "customers.deals.kanban.bulk.aria.clear",
55
+ "Clear selection"
56
+ ),
57
+ className: "inline-flex size-6 items-center justify-center rounded-md transition-colors hover:bg-background/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-foreground",
58
+ children: /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" })
59
+ }
60
+ ),
61
+ /* @__PURE__ */ jsx("span", { className: "inline-flex size-7 items-center justify-center rounded-md bg-background/10 text-xs font-semibold", children: count }),
62
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: translateWithFallback(
63
+ t,
64
+ "customers.deals.kanban.bulk.selectedCount",
65
+ "selected"
66
+ ) }),
67
+ totalLabel ? /* @__PURE__ */ jsxs("span", { className: "hidden text-sm text-background/80 sm:inline", children: [
68
+ "\xB7",
69
+ " ",
70
+ translateWithFallback(
71
+ t,
72
+ "customers.deals.kanban.bulk.totalValue",
73
+ "Total {value}",
74
+ { value: totalLabel }
75
+ )
76
+ ] }) : null,
77
+ /* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-1", children: [
78
+ /* @__PURE__ */ jsxs(
79
+ Button,
80
+ {
81
+ variant: "ghost",
82
+ size: "sm",
83
+ type: "button",
84
+ onClick: onChangeStage,
85
+ className: "inline-flex items-center gap-1 rounded-md px-3 py-1 text-sm transition-colors hover:bg-background/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-foreground",
86
+ children: [
87
+ /* @__PURE__ */ jsx(Workflow, { className: "size-4", "aria-hidden": "true" }),
88
+ /* @__PURE__ */ jsx("span", { children: translateWithFallback(
89
+ t,
90
+ "customers.deals.kanban.bulk.changeStage",
91
+ "Change stage"
92
+ ) })
93
+ ]
94
+ }
95
+ ),
96
+ /* @__PURE__ */ jsxs(
97
+ Button,
98
+ {
99
+ variant: "ghost",
100
+ size: "sm",
101
+ type: "button",
102
+ onClick: onChangeOwner,
103
+ className: "inline-flex items-center gap-1 rounded-md px-3 py-1 text-sm transition-colors hover:bg-background/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-foreground",
104
+ children: [
105
+ /* @__PURE__ */ jsx(UserCircle2, { className: "size-4", "aria-hidden": "true" }),
106
+ /* @__PURE__ */ jsx("span", { children: translateWithFallback(
107
+ t,
108
+ "customers.deals.kanban.bulk.changeOwner",
109
+ "Change owner"
110
+ ) })
111
+ ]
112
+ }
113
+ ),
114
+ /* @__PURE__ */ jsxs(
115
+ Button,
116
+ {
117
+ variant: "ghost",
118
+ size: "sm",
119
+ type: "button",
120
+ onClick: onExportCsv,
121
+ className: "inline-flex items-center gap-1 rounded-md px-3 py-1 text-sm transition-colors hover:bg-background/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-foreground",
122
+ children: [
123
+ /* @__PURE__ */ jsx(Download, { className: "size-4", "aria-hidden": "true" }),
124
+ /* @__PURE__ */ jsx("span", { children: translateWithFallback(
125
+ t,
126
+ "customers.deals.kanban.bulk.exportCsv",
127
+ "Export CSV"
128
+ ) })
129
+ ]
130
+ }
131
+ ),
132
+ /* @__PURE__ */ jsxs(
133
+ Button,
134
+ {
135
+ variant: "destructive-ghost",
136
+ size: "sm",
137
+ type: "button",
138
+ onClick: onDelete,
139
+ className: "inline-flex items-center gap-1 rounded-md px-3 py-1 text-sm text-status-error-text transition-colors hover:bg-status-error-bg/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-foreground",
140
+ children: [
141
+ /* @__PURE__ */ jsx(Trash2, { className: "size-4", "aria-hidden": "true" }),
142
+ /* @__PURE__ */ jsx("span", { children: translateWithFallback(
143
+ t,
144
+ "customers.deals.kanban.bulk.delete",
145
+ "Delete"
146
+ ) })
147
+ ]
148
+ }
149
+ )
150
+ ] })
151
+ ]
152
+ }
153
+ );
154
+ }
155
+ var BulkActionsBar_default = BulkActionsBar;
156
+ export {
157
+ BulkActionsBar,
158
+ BulkActionsBar_default as default
159
+ };
160
+ //# sourceMappingURL=BulkActionsBar.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../src/modules/customers/backend/customers/deals/pipeline/components/BulkActionsBar.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Download, Trash2, Workflow, UserCircle2, X } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\ntype BulkActionsBarProps = {\n count: number\n totalLabel: string | null\n onChangeStage: () => void\n onChangeOwner: () => void\n onExportCsv: () => void\n onDelete: () => void\n onClear: () => void\n}\n\nexport function BulkActionsBar({\n count,\n totalLabel,\n onChangeStage,\n onChangeOwner,\n onExportCsv,\n onDelete,\n onClear,\n}: BulkActionsBarProps): React.ReactElement | null {\n const t = useT()\n // Global ESC clears the selection \u2014 matches the Gmail/Asana/Notion convention. The\n // listener is only mounted while at least one deal is selected so we don't intercept\n // ESC anywhere else on the kanban (e.g. inside dialogs/popovers, which all stopPropagation\n // before their own ESC handlers fire). `count` is the only thing that gates \"is the bar\n // currently rendered?\", and `onClear` is the page-level handler that empties the Set.\n React.useEffect(() => {\n if (count === 0) return\n const onKey = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return\n // Defer if the focus is inside an editable surface \u2014 typing ESC to abort a value\n // edit shouldn't also clear the bulk selection.\n const active = document.activeElement as HTMLElement | null\n if (active) {\n const tag = active.tagName\n if (tag === 'INPUT' || tag === 'TEXTAREA' || active.isContentEditable) return\n }\n event.preventDefault()\n onClear()\n }\n document.addEventListener('keydown', onKey)\n return () => document.removeEventListener('keydown', onKey)\n }, [count, onClear])\n\n if (count === 0) return null\n\n return (\n <div\n role=\"region\"\n aria-label={translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.aria.bar',\n 'Bulk actions',\n )}\n className=\"fixed bottom-6 left-1/2 z-toast flex w-[min(960px,calc(100%-2rem))] -translate-x-1/2 items-center gap-3 rounded-lg bg-foreground px-4 py-3 text-background shadow-xl\"\n >\n <IconButton\n variant=\"ghost\"\n size=\"xs\"\n onClick={onClear}\n aria-label={translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.aria.clear',\n 'Clear selection',\n )}\n className=\"inline-flex size-6 items-center justify-center rounded-md transition-colors hover:bg-background/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-foreground\"\n >\n <X className=\"size-4\" aria-hidden=\"true\" />\n </IconButton>\n\n <span className=\"inline-flex size-7 items-center justify-center rounded-md bg-background/10 text-xs font-semibold\">\n {count}\n </span>\n <span className=\"text-sm font-medium\">\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.selectedCount',\n 'selected',\n )}\n </span>\n {totalLabel ? (\n <span className=\"hidden text-sm text-background/80 sm:inline\">\n \u00B7{' '}\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.totalValue',\n 'Total {value}',\n { value: totalLabel },\n )}\n </span>\n ) : null}\n\n <div className=\"ml-auto flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n type=\"button\"\n onClick={onChangeStage}\n className=\"inline-flex items-center gap-1 rounded-md px-3 py-1 text-sm transition-colors hover:bg-background/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-foreground\"\n >\n <Workflow className=\"size-4\" aria-hidden=\"true\" />\n <span>\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.changeStage',\n 'Change stage',\n )}\n </span>\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n type=\"button\"\n onClick={onChangeOwner}\n className=\"inline-flex items-center gap-1 rounded-md px-3 py-1 text-sm transition-colors hover:bg-background/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-foreground\"\n >\n <UserCircle2 className=\"size-4\" aria-hidden=\"true\" />\n <span>\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.changeOwner',\n 'Change owner',\n )}\n </span>\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n type=\"button\"\n onClick={onExportCsv}\n className=\"inline-flex items-center gap-1 rounded-md px-3 py-1 text-sm transition-colors hover:bg-background/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-foreground\"\n >\n <Download className=\"size-4\" aria-hidden=\"true\" />\n <span>\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.exportCsv',\n 'Export CSV',\n )}\n </span>\n </Button>\n <Button\n variant=\"destructive-ghost\"\n size=\"sm\"\n type=\"button\"\n onClick={onDelete}\n className=\"inline-flex items-center gap-1 rounded-md px-3 py-1 text-sm text-status-error-text transition-colors hover:bg-status-error-bg/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-foreground\"\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n <span>\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.delete',\n 'Delete',\n )}\n </span>\n </Button>\n </div>\n </div>\n )\n}\n\nexport default BulkActionsBar\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,157 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { UserCircle2 } from "lucide-react";
5
+ import {
6
+ Dialog,
7
+ DialogContent,
8
+ DialogDescription,
9
+ DialogFooter,
10
+ DialogHeader,
11
+ DialogTitle
12
+ } from "@open-mercato/ui/primitives/dialog";
13
+ import { Button } from "@open-mercato/ui/primitives/button";
14
+ import { Input } from "@open-mercato/ui/primitives/input";
15
+ import { Avatar } from "@open-mercato/ui/primitives/avatar";
16
+ import { Spinner } from "@open-mercato/ui/primitives/spinner";
17
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
18
+ import { translateWithFallback } from "@open-mercato/shared/lib/i18n/translate";
19
+ import {
20
+ fetchAssignableStaffMembers
21
+ } from "../../../../../components/detail/assignableStaff.js";
22
+ function ChangeOwnerDialog({
23
+ open,
24
+ selectedCount,
25
+ isSubmitting,
26
+ onClose,
27
+ onConfirm
28
+ }) {
29
+ const t = useT();
30
+ const [query, setQuery] = React.useState("");
31
+ const [items, setItems] = React.useState([]);
32
+ const [isLoading, setIsLoading] = React.useState(false);
33
+ const [selectedUserId, setSelectedUserId] = React.useState(null);
34
+ React.useEffect(() => {
35
+ if (!open) return;
36
+ setQuery("");
37
+ setSelectedUserId(null);
38
+ }, [open]);
39
+ React.useEffect(() => {
40
+ if (!open) return;
41
+ let cancelled = false;
42
+ const controller = new AbortController();
43
+ setIsLoading(true);
44
+ fetchAssignableStaffMembers(query, { pageSize: 50, signal: controller.signal }).then((next) => {
45
+ if (cancelled) return;
46
+ setItems(next);
47
+ if (!selectedUserId && next.length > 0) setSelectedUserId(next[0].userId);
48
+ }).catch(() => {
49
+ if (!cancelled) setItems([]);
50
+ }).finally(() => {
51
+ if (!cancelled) setIsLoading(false);
52
+ });
53
+ return () => {
54
+ cancelled = true;
55
+ controller.abort();
56
+ };
57
+ }, [open, query]);
58
+ const handleConfirm = () => {
59
+ onConfirm(selectedUserId);
60
+ };
61
+ const handleKeyDown = (event) => {
62
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
63
+ event.preventDefault();
64
+ handleConfirm();
65
+ }
66
+ };
67
+ return /* @__PURE__ */ jsx(
68
+ Dialog,
69
+ {
70
+ open,
71
+ onOpenChange: (next) => {
72
+ if (!next && !isSubmitting) onClose();
73
+ },
74
+ children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", onKeyDown: handleKeyDown, children: [
75
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
76
+ /* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
77
+ /* @__PURE__ */ jsx(UserCircle2, { className: "size-4", "aria-hidden": "true" }),
78
+ translateWithFallback(
79
+ t,
80
+ "customers.deals.kanban.bulk.changeOwner.title",
81
+ "Change owner for {count} deals",
82
+ { count: selectedCount }
83
+ )
84
+ ] }),
85
+ /* @__PURE__ */ jsx(DialogDescription, { children: translateWithFallback(
86
+ t,
87
+ "customers.deals.kanban.bulk.changeOwner.helper",
88
+ "Pick a staff member who will own all selected deals."
89
+ ) })
90
+ ] }),
91
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
92
+ /* @__PURE__ */ jsx(
93
+ Input,
94
+ {
95
+ value: query,
96
+ onChange: (event) => setQuery(event.target.value),
97
+ placeholder: translateWithFallback(
98
+ t,
99
+ "customers.deals.kanban.bulk.changeOwner.search",
100
+ "Search by name or email\u2026"
101
+ ),
102
+ autoFocus: true
103
+ }
104
+ ),
105
+ /* @__PURE__ */ jsx("div", { className: "flex max-h-72 flex-col gap-1 overflow-y-auto pr-1", children: isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-4", children: /* @__PURE__ */ jsx(Spinner, {}) }) : items.length === 0 ? /* @__PURE__ */ jsx("span", { className: "px-3 py-2 text-sm text-muted-foreground", children: translateWithFallback(
106
+ t,
107
+ "customers.deals.kanban.bulk.changeOwner.empty",
108
+ "No staff members found."
109
+ ) }) : items.map((member) => {
110
+ const isSelected = selectedUserId === member.userId;
111
+ return /* @__PURE__ */ jsxs(
112
+ Button,
113
+ {
114
+ variant: "ghost",
115
+ size: "default",
116
+ type: "button",
117
+ onClick: () => setSelectedUserId(member.userId),
118
+ className: `flex h-auto w-full items-center justify-start gap-3 whitespace-normal rounded-md px-3 py-2 text-left transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ${isSelected ? "bg-muted" : ""}`,
119
+ children: [
120
+ /* @__PURE__ */ jsx(Avatar, { label: member.displayName, size: "sm" }),
121
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 flex-col items-start", children: [
122
+ /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-medium text-foreground", children: member.displayName }),
123
+ member.email ? /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: member.email }) : null
124
+ ] })
125
+ ]
126
+ },
127
+ member.teamMemberId
128
+ );
129
+ }) })
130
+ ] }),
131
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
132
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onClose, type: "button", disabled: isSubmitting, children: translateWithFallback(t, "customers.deals.kanban.filter.cancel", "Cancel") }),
133
+ /* @__PURE__ */ jsx(
134
+ Button,
135
+ {
136
+ type: "button",
137
+ onClick: handleConfirm,
138
+ disabled: !selectedUserId || isSubmitting,
139
+ children: translateWithFallback(
140
+ t,
141
+ "customers.deals.kanban.bulk.changeOwner.confirm",
142
+ "Reassign {count} deals",
143
+ { count: selectedCount }
144
+ )
145
+ }
146
+ )
147
+ ] })
148
+ ] })
149
+ }
150
+ );
151
+ }
152
+ var ChangeOwnerDialog_default = ChangeOwnerDialog;
153
+ export {
154
+ ChangeOwnerDialog,
155
+ ChangeOwnerDialog_default as default
156
+ };
157
+ //# sourceMappingURL=ChangeOwnerDialog.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../src/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { UserCircle2 } from 'lucide-react'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Avatar } from '@open-mercato/ui/primitives/avatar'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport {\n fetchAssignableStaffMembers,\n type AssignableStaffMember,\n} from '../../../../../components/detail/assignableStaff'\n\ntype ChangeOwnerDialogProps = {\n open: boolean\n selectedCount: number\n isSubmitting: boolean\n onClose: () => void\n onConfirm: (userId: string | null) => void\n}\n\nexport function ChangeOwnerDialog({\n open,\n selectedCount,\n isSubmitting,\n onClose,\n onConfirm,\n}: ChangeOwnerDialogProps): React.ReactElement {\n const t = useT()\n const [query, setQuery] = React.useState('')\n const [items, setItems] = React.useState<AssignableStaffMember[]>([])\n const [isLoading, setIsLoading] = React.useState(false)\n const [selectedUserId, setSelectedUserId] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n if (!open) return\n setQuery('')\n setSelectedUserId(null)\n }, [open])\n\n React.useEffect(() => {\n if (!open) return\n let cancelled = false\n const controller = new AbortController()\n setIsLoading(true)\n fetchAssignableStaffMembers(query, { pageSize: 50, signal: controller.signal })\n .then((next) => {\n if (cancelled) return\n setItems(next)\n if (!selectedUserId && next.length > 0) setSelectedUserId(next[0].userId)\n })\n .catch(() => {\n if (!cancelled) setItems([])\n })\n .finally(() => {\n if (!cancelled) setIsLoading(false)\n })\n return () => {\n cancelled = true\n controller.abort()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, query])\n\n const handleConfirm = () => {\n onConfirm(selectedUserId)\n }\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n handleConfirm()\n }\n }\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n if (!next && !isSubmitting) onClose()\n }}\n >\n <DialogContent className=\"sm:max-w-md\" onKeyDown={handleKeyDown}>\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <UserCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.changeOwner.title',\n 'Change owner for {count} deals',\n { count: selectedCount },\n )}\n </DialogTitle>\n <DialogDescription>\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.changeOwner.helper',\n 'Pick a staff member who will own all selected deals.',\n )}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"flex flex-col gap-3\">\n <Input\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n placeholder={translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.changeOwner.search',\n 'Search by name or email\u2026',\n )}\n autoFocus\n />\n <div className=\"flex max-h-72 flex-col gap-1 overflow-y-auto pr-1\">\n {isLoading ? (\n <div className=\"flex justify-center py-4\">\n <Spinner />\n </div>\n ) : items.length === 0 ? (\n <span className=\"px-3 py-2 text-sm text-muted-foreground\">\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.changeOwner.empty',\n 'No staff members found.',\n )}\n </span>\n ) : (\n items.map((member) => {\n const isSelected = selectedUserId === member.userId\n return (\n <Button\n variant=\"ghost\"\n size=\"default\"\n key={member.teamMemberId}\n type=\"button\"\n onClick={() => setSelectedUserId(member.userId)}\n // Overrides on the Button base class:\n // - `flex w-full` \u2192 row spans the dialog width (default Button is `inline-flex` and content-sized)\n // - `h-auto` \u2192 fit avatar + two stacked text lines (default `h-9` clips and leaves the background only covering the first line \u2014 that's the \"uneven\" symptom)\n // - `justify-start` \u2192 left-align contents (default Button is `justify-center`, which pushes the avatar+name toward the middle)\n // - `whitespace-normal` \u2192 allow long emails to wrap instead of overflowing the button box (default Button is `whitespace-nowrap`)\n className={`flex h-auto w-full items-center justify-start gap-3 whitespace-normal rounded-md px-3 py-2 text-left transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ${\n isSelected ? 'bg-muted' : ''\n }`}\n >\n <Avatar label={member.displayName} size=\"sm\" />\n <span className=\"flex min-w-0 flex-1 flex-col items-start\">\n <span className=\"truncate text-sm font-medium text-foreground\">\n {member.displayName}\n </span>\n {member.email ? (\n <span className=\"truncate text-xs text-muted-foreground\">\n {member.email}\n </span>\n ) : null}\n </span>\n </Button>\n )\n })\n )}\n </div>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={onClose} type=\"button\" disabled={isSubmitting}>\n {translateWithFallback(t, 'customers.deals.kanban.filter.cancel', 'Cancel')}\n </Button>\n <Button\n type=\"button\"\n onClick={handleConfirm}\n disabled={!selectedUserId || isSubmitting}\n >\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.changeOwner.confirm',\n 'Reassign {count} deals',\n { count: selectedCount },\n )}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\nexport default ChangeOwnerDialog\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,114 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Workflow } from "lucide-react";
5
+ import {
6
+ Dialog,
7
+ DialogContent,
8
+ DialogDescription,
9
+ DialogFooter,
10
+ DialogHeader,
11
+ DialogTitle
12
+ } from "@open-mercato/ui/primitives/dialog";
13
+ import { Button } from "@open-mercato/ui/primitives/button";
14
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
15
+ import { translateWithFallback } from "@open-mercato/shared/lib/i18n/translate";
16
+ function ChangeStageDialog({
17
+ open,
18
+ selectedCount,
19
+ pipelineName,
20
+ stages,
21
+ isSubmitting,
22
+ onClose,
23
+ onConfirm
24
+ }) {
25
+ const t = useT();
26
+ const [draftStageId, setDraftStageId] = React.useState(stages[0]?.id ?? null);
27
+ React.useEffect(() => {
28
+ if (open) setDraftStageId(stages[0]?.id ?? null);
29
+ }, [open, stages]);
30
+ const handleConfirm = () => {
31
+ if (draftStageId) onConfirm(draftStageId);
32
+ };
33
+ const handleKeyDown = (event) => {
34
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
35
+ event.preventDefault();
36
+ handleConfirm();
37
+ }
38
+ };
39
+ return /* @__PURE__ */ jsx(
40
+ Dialog,
41
+ {
42
+ open,
43
+ onOpenChange: (next) => {
44
+ if (!next && !isSubmitting) onClose();
45
+ },
46
+ children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", onKeyDown: handleKeyDown, children: [
47
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
48
+ /* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
49
+ /* @__PURE__ */ jsx(Workflow, { className: "size-4", "aria-hidden": "true" }),
50
+ translateWithFallback(
51
+ t,
52
+ "customers.deals.kanban.bulk.changeStage.title",
53
+ "Change stage for {count} deals",
54
+ { count: selectedCount }
55
+ )
56
+ ] }),
57
+ /* @__PURE__ */ jsx(DialogDescription, { children: translateWithFallback(
58
+ t,
59
+ "customers.deals.kanban.bulk.changeStage.context",
60
+ "Pipeline: {pipeline}",
61
+ { pipeline: pipelineName }
62
+ ) })
63
+ ] }),
64
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1 py-1", children: stages.map((stage) => {
65
+ const isSelected = draftStageId === stage.id;
66
+ return /* @__PURE__ */ jsxs(
67
+ Button,
68
+ {
69
+ variant: "ghost",
70
+ type: "button",
71
+ onClick: () => setDraftStageId(stage.id),
72
+ className: `flex w-full items-center justify-between rounded-md px-3 py-2 text-sm transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ${isSelected ? "bg-muted" : ""}`,
73
+ children: [
74
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: stage.label }),
75
+ /* @__PURE__ */ jsx(
76
+ "span",
77
+ {
78
+ className: `inline-flex size-4 items-center justify-center rounded-full border ${isSelected ? "border-primary bg-primary" : "border-input"}`,
79
+ "aria-hidden": "true",
80
+ children: isSelected ? /* @__PURE__ */ jsx("span", { className: "size-1.5 rounded-full bg-primary-foreground" }) : null
81
+ }
82
+ )
83
+ ]
84
+ },
85
+ stage.id
86
+ );
87
+ }) }),
88
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
89
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onClose, type: "button", disabled: isSubmitting, children: translateWithFallback(t, "customers.deals.kanban.filter.cancel", "Cancel") }),
90
+ /* @__PURE__ */ jsx(
91
+ Button,
92
+ {
93
+ type: "button",
94
+ onClick: handleConfirm,
95
+ disabled: !draftStageId || isSubmitting || stages.length === 0,
96
+ children: translateWithFallback(
97
+ t,
98
+ "customers.deals.kanban.bulk.changeStage.confirm",
99
+ "Move {count} deals",
100
+ { count: selectedCount }
101
+ )
102
+ }
103
+ )
104
+ ] })
105
+ ] })
106
+ }
107
+ );
108
+ }
109
+ var ChangeStageDialog_default = ChangeStageDialog;
110
+ export {
111
+ ChangeStageDialog,
112
+ ChangeStageDialog_default as default
113
+ };
114
+ //# sourceMappingURL=ChangeStageDialog.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../src/modules/customers/backend/customers/deals/pipeline/components/ChangeStageDialog.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Workflow } from 'lucide-react'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nexport type ChangeStageOption = {\n id: string\n label: string\n}\n\ntype ChangeStageDialogProps = {\n open: boolean\n selectedCount: number\n pipelineName: string\n stages: ChangeStageOption[]\n isSubmitting: boolean\n onClose: () => void\n onConfirm: (stageId: string) => void\n}\n\nexport function ChangeStageDialog({\n open,\n selectedCount,\n pipelineName,\n stages,\n isSubmitting,\n onClose,\n onConfirm,\n}: ChangeStageDialogProps): React.ReactElement {\n const t = useT()\n const [draftStageId, setDraftStageId] = React.useState<string | null>(stages[0]?.id ?? null)\n\n React.useEffect(() => {\n if (open) setDraftStageId(stages[0]?.id ?? null)\n }, [open, stages])\n\n const handleConfirm = () => {\n if (draftStageId) onConfirm(draftStageId)\n }\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n handleConfirm()\n }\n }\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n if (!next && !isSubmitting) onClose()\n }}\n >\n <DialogContent className=\"sm:max-w-md\" onKeyDown={handleKeyDown}>\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <Workflow className=\"size-4\" aria-hidden=\"true\" />\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.changeStage.title',\n 'Change stage for {count} deals',\n { count: selectedCount },\n )}\n </DialogTitle>\n <DialogDescription>\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.changeStage.context',\n 'Pipeline: {pipeline}',\n { pipeline: pipelineName },\n )}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"flex flex-col gap-1 py-1\">\n {stages.map((stage) => {\n const isSelected = draftStageId === stage.id\n return (\n <Button\n variant=\"ghost\"\n key={stage.id}\n type=\"button\"\n onClick={() => setDraftStageId(stage.id)}\n className={`flex w-full items-center justify-between rounded-md px-3 py-2 text-sm transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ${\n isSelected ? 'bg-muted' : ''\n }`}\n >\n <span className=\"font-medium text-foreground\">{stage.label}</span>\n <span\n className={`inline-flex size-4 items-center justify-center rounded-full border ${\n isSelected ? 'border-primary bg-primary' : 'border-input'\n }`}\n aria-hidden=\"true\"\n >\n {isSelected ? (\n <span className=\"size-1.5 rounded-full bg-primary-foreground\" />\n ) : null}\n </span>\n </Button>\n )\n })}\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={onClose} type=\"button\" disabled={isSubmitting}>\n {translateWithFallback(t, 'customers.deals.kanban.filter.cancel', 'Cancel')}\n </Button>\n <Button\n type=\"button\"\n onClick={handleConfirm}\n disabled={!draftStageId || isSubmitting || stages.length === 0}\n >\n {translateWithFallback(\n t,\n 'customers.deals.kanban.bulk.changeStage.confirm',\n 'Move {count} deals',\n { count: selectedCount },\n )}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\nexport default ChangeStageDialog\n"],
5
+ "mappings": ";AAmEU,SACE,KADF;AAjEV,YAAY,WAAW;AACvB,SAAS,gBAAgB;AACzB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,6BAA6B;AAiB/B,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA+C;AAC7C,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAwB,OAAO,CAAC,GAAG,MAAM,IAAI;AAE3F,QAAM,UAAU,MAAM;AACpB,QAAI,KAAM,iBAAgB,OAAO,CAAC,GAAG,MAAM,IAAI;AAAA,EACjD,GAAG,CAAC,MAAM,MAAM,CAAC;AAEjB,QAAM,gBAAgB,MAAM;AAC1B,QAAI,aAAc,WAAU,YAAY;AAAA,EAC1C;AAEA,QAAM,gBAAgB,CAAC,UAA+B;AACpD,SAAK,MAAM,WAAW,MAAM,YAAY,MAAM,QAAQ,SAAS;AAC7D,YAAM,eAAe;AACrB,oBAAc;AAAA,IAChB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,cAAc,CAAC,SAAS;AACtB,YAAI,CAAC,QAAQ,CAAC,aAAc,SAAQ;AAAA,MACtC;AAAA,MAEA,+BAAC,iBAAc,WAAU,eAAc,WAAW,eAChD;AAAA,6BAAC,gBACC;AAAA,+BAAC,eAAY,WAAU,2BACrB;AAAA,gCAAC,YAAS,WAAU,UAAS,eAAY,QAAO;AAAA,YAC/C;AAAA,cACC;AAAA,cACA;AAAA,cACA;AAAA,cACA,EAAE,OAAO,cAAc;AAAA,YACzB;AAAA,aACF;AAAA,UACA,oBAAC,qBACE;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA,EAAE,UAAU,aAAa;AAAA,UAC3B,GACF;AAAA,WACF;AAAA,QAEA,oBAAC,SAAI,WAAU,4BACZ,iBAAO,IAAI,CAAC,UAAU;AACrB,gBAAM,aAAa,iBAAiB,MAAM;AAC1C,iBACE;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cAER,MAAK;AAAA,cACL,SAAS,MAAM,gBAAgB,MAAM,EAAE;AAAA,cACvC,WAAW,8MACT,aAAa,aAAa,EAC5B;AAAA,cAEA;AAAA,oCAAC,UAAK,WAAU,+BAA+B,gBAAM,OAAM;AAAA,gBAC3D;AAAA,kBAAC;AAAA;AAAA,oBACC,WAAW,sEACT,aAAa,8BAA8B,cAC7C;AAAA,oBACA,eAAY;AAAA,oBAEX,uBACC,oBAAC,UAAK,WAAU,+CAA8C,IAC5D;AAAA;AAAA,gBACN;AAAA;AAAA;AAAA,YAjBK,MAAM;AAAA,UAkBb;AAAA,QAEJ,CAAC,GACH;AAAA,QAEA,qBAAC,gBACC;AAAA,8BAAC,UAAO,SAAQ,WAAU,SAAS,SAAS,MAAK,UAAS,UAAU,cACjE,gCAAsB,GAAG,wCAAwC,QAAQ,GAC5E;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,UAAU,CAAC,gBAAgB,gBAAgB,OAAO,WAAW;AAAA,cAE5D;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA,EAAE,OAAO,cAAc;AAAA,cACzB;AAAA;AAAA,UACF;AAAA,WACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,4BAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,36 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { ChevronDown } from "lucide-react";
5
+ import { Button } from "@open-mercato/ui/primitives/button";
6
+ const ChipButton = React.forwardRef(
7
+ function ChipButton2({ label, value, active = false, ariaLabel, onClick, withChevron = true }, ref) {
8
+ return /* @__PURE__ */ jsxs(
9
+ Button,
10
+ {
11
+ variant: "ghost",
12
+ size: "sm",
13
+ ref,
14
+ type: "button",
15
+ onClick,
16
+ "aria-label": ariaLabel ?? (label ? `${label}: ${value}` : value),
17
+ "aria-pressed": active,
18
+ className: `inline-flex items-center gap-1.5 rounded-sm border border-border bg-card px-2.5 py-1.5 text-xs leading-normal transition-colors hover:bg-muted/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ${active ? "border-foreground/40 bg-muted text-foreground" : "text-foreground"}`,
19
+ children: [
20
+ label ? /* @__PURE__ */ jsxs("span", { className: "font-normal text-muted-foreground", children: [
21
+ label,
22
+ ":"
23
+ ] }) : null,
24
+ /* @__PURE__ */ jsx("span", { className: label ? "font-semibold text-foreground" : "font-normal text-foreground", children: value }),
25
+ withChevron ? /* @__PURE__ */ jsx(ChevronDown, { className: "size-3 text-muted-foreground", "aria-hidden": "true" }) : null
26
+ ]
27
+ }
28
+ );
29
+ }
30
+ );
31
+ var ChipButton_default = ChipButton;
32
+ export {
33
+ ChipButton,
34
+ ChipButton_default as default
35
+ };
36
+ //# sourceMappingURL=ChipButton.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../src/modules/customers/backend/customers/deals/pipeline/components/ChipButton.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { ChevronDown } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\n\nexport type ChipButtonProps = {\n label?: string\n value: string\n active?: boolean\n ariaLabel?: string\n onClick?: () => void\n /** Show the chevron-down affordance \u2014 true for popover-backed chips, false for plain chips like \"+ More\" */\n withChevron?: boolean\n}\n\nexport const ChipButton = React.forwardRef<HTMLButtonElement, ChipButtonProps>(\n function ChipButton(\n { label, value, active = false, ariaLabel, onClick, withChevron = true },\n ref,\n ) {\n return (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n ref={ref}\n type=\"button\"\n onClick={onClick}\n aria-label={ariaLabel ?? (label ? `${label}: ${value}` : value)}\n aria-pressed={active}\n className={`inline-flex items-center gap-1.5 rounded-sm border border-border bg-card px-2.5 py-1.5 text-xs leading-normal transition-colors hover:bg-muted/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ${\n active ? 'border-foreground/40 bg-muted text-foreground' : 'text-foreground'\n }`}\n >\n {label ? <span className=\"font-normal text-muted-foreground\">{label}:</span> : null}\n <span className={label ? 'font-semibold text-foreground' : 'font-normal text-foreground'}>\n {value}\n </span>\n {withChevron ? (\n <ChevronDown className=\"size-3 text-muted-foreground\" aria-hidden=\"true\" />\n ) : null}\n </Button>\n )\n },\n)\n\nexport default ChipButton\n"],
5
+ "mappings": ";AAkCiB,SACT,KADS;AAhCjB,YAAY,WAAW;AACvB,SAAS,mBAAmB;AAC5B,SAAS,cAAc;AAYhB,MAAM,aAAa,MAAM;AAAA,EAC9B,SAASA,YACP,EAAE,OAAO,OAAO,SAAS,OAAO,WAAW,SAAS,cAAc,KAAK,GACvE,KACA;AACA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,SAAQ;AAAA,QACR,MAAK;AAAA,QACL;AAAA,QACA,MAAK;AAAA,QACL;AAAA,QACA,cAAY,cAAc,QAAQ,GAAG,KAAK,KAAK,KAAK,KAAK;AAAA,QACzD,gBAAc;AAAA,QACd,WAAW,yPACT,SAAS,kDAAkD,iBAC7D;AAAA,QAEC;AAAA,kBAAQ,qBAAC,UAAK,WAAU,qCAAqC;AAAA;AAAA,YAAM;AAAA,aAAC,IAAU;AAAA,UAC/E,oBAAC,UAAK,WAAW,QAAQ,kCAAkC,+BACxD,iBACH;AAAA,UACC,cACC,oBAAC,eAAY,WAAU,gCAA+B,eAAY,QAAO,IACvE;AAAA;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AAEA,IAAO,qBAAQ;",
6
+ "names": ["ChipButton"]
7
+ }