@open-mercato/core 0.6.3-develop.3651.1.d3a548a5f1 → 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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/generated/entities/customer_settings/index.js +2 -0
- package/dist/generated/entities/customer_settings/index.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +1 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/customers/api/deals/aggregate/route.js +332 -0
- package/dist/modules/customers/api/deals/aggregate/route.js.map +7 -0
- package/dist/modules/customers/api/deals/bulk-update-owner/route.js +188 -0
- package/dist/modules/customers/api/deals/bulk-update-owner/route.js.map +7 -0
- package/dist/modules/customers/api/deals/bulk-update-stage/route.js +188 -0
- package/dist/modules/customers/api/deals/bulk-update-stage/route.js.map +7 -0
- package/dist/modules/customers/api/deals/route.js +255 -122
- package/dist/modules/customers/api/deals/route.js.map +2 -2
- package/dist/modules/customers/api/settings/stuck-threshold/route.js +169 -0
- package/dist/modules/customers/api/settings/stuck-threshold/route.js.map +7 -0
- package/dist/modules/customers/backend/config/customers/deals/page.js +181 -0
- package/dist/modules/customers/backend/config/customers/deals/page.js.map +7 -0
- package/dist/modules/customers/backend/config/customers/deals/page.meta.js +38 -0
- package/dist/modules/customers/backend/config/customers/deals/page.meta.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/create/page.js +17 -6
- package/dist/modules/customers/backend/customers/deals/create/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +2 -0
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ActivityComposerDialog.js +217 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ActivityComposerDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageDialog.js +335 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageLane.js +29 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageLane.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/BulkActionsBar.js +160 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/BulkActionsBar.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.js +157 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeStageDialog.js +114 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeStageDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChipButton.js +36 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChipButton.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CloseDateFilterPopover.js +199 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CloseDateFilterPopover.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CurrencyBreakdownTable.js +71 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CurrencyBreakdownTable.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CurrencyFilterPopover.js +233 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CurrencyFilterPopover.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CustomizeViewDialog.js +126 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CustomizeViewDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/DashedTileButton.js +31 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/DashedTileButton.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/DealCard.js +389 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/DealCard.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/DealCardMenu.js +181 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/DealCardMenu.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/EntityFilterPopover.js +199 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/EntityFilterPopover.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.js +44 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterPopoverShell.js +70 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterPopoverShell.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js +278 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/LaneCurrencyBreakdown.js +135 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/LaneCurrencyBreakdown.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/LaneResizeHandle.js +83 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/LaneResizeHandle.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/PipelineFilterPopover.js +155 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/PipelineFilterPopover.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js +318 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/SortByPopover.js +138 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/SortByPopover.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js +126 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js +71 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/constants.js +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/constants.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js +2330 -415
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +3 -3
- package/dist/modules/customers/commands/deals.js +6 -0
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/pipeline-stages.js +48 -13
- package/dist/modules/customers/commands/pipeline-stages.js.map +3 -3
- package/dist/modules/customers/commands/settings.js +45 -5
- package/dist/modules/customers/commands/settings.js.map +2 -2
- package/dist/modules/customers/data/enrichers.js +130 -1
- package/dist/modules/customers/data/enrichers.js.map +2 -2
- package/dist/modules/customers/data/entities.js +4 -0
- package/dist/modules/customers/data/entities.js.map +2 -2
- package/dist/modules/customers/data/validators.js +29 -2
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/lib/bulkDeals.js +150 -0
- package/dist/modules/customers/lib/bulkDeals.js.map +7 -0
- package/dist/modules/customers/lib/kysely.js +12 -0
- package/dist/modules/customers/lib/kysely.js.map +7 -0
- package/dist/modules/customers/lib/stuckDeals.js +32 -0
- package/dist/modules/customers/lib/stuckDeals.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260513203311_customers.js +13 -0
- package/dist/modules/customers/migrations/Migration20260513203311_customers.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.js +52 -0
- package/dist/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.js.map +7 -0
- package/dist/modules/customers/workers/deals-bulk-update-owner.js +41 -0
- package/dist/modules/customers/workers/deals-bulk-update-owner.js.map +7 -0
- package/dist/modules/customers/workers/deals-bulk-update-stage.js +41 -0
- package/dist/modules/customers/workers/deals-bulk-update-stage.js.map +7 -0
- package/generated/entities/customer_settings/index.ts +1 -0
- package/generated/entity-fields-registry.ts +1 -0
- package/package.json +7 -7
- package/src/modules/customers/api/deals/aggregate/route.ts +438 -0
- package/src/modules/customers/api/deals/bulk-update-owner/route.ts +216 -0
- package/src/modules/customers/api/deals/bulk-update-stage/route.ts +228 -0
- package/src/modules/customers/api/deals/route.ts +330 -135
- package/src/modules/customers/api/settings/stuck-threshold/route.ts +195 -0
- package/src/modules/customers/backend/config/customers/deals/page.meta.ts +36 -0
- package/src/modules/customers/backend/config/customers/deals/page.tsx +205 -0
- package/src/modules/customers/backend/customers/deals/create/page.tsx +25 -6
- package/src/modules/customers/backend/customers/deals/page.tsx +2 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/ActivityComposerDialog.tsx +277 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/AddStageDialog.tsx +425 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/AddStageLane.tsx +31 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/BulkActionsBar.tsx +171 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.tsx +196 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/ChangeStageDialog.tsx +138 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/ChipButton.tsx +47 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/CloseDateFilterPopover.tsx +232 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/CurrencyBreakdownTable.tsx +110 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/CurrencyFilterPopover.tsx +310 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/CustomizeViewDialog.tsx +169 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/DashedTileButton.tsx +54 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/DealCard.tsx +562 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/DealCardMenu.tsx +214 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/EntityFilterPopover.tsx +257 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.tsx +62 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/FilterPopoverShell.tsx +101 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/Lane.tsx +378 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/LaneCurrencyBreakdown.tsx +192 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/LaneResizeHandle.tsx +107 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/PipelineFilterPopover.tsx +196 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.tsx +408 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/SortByPopover.tsx +164 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.tsx +171 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.tsx +84 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/constants.ts +16 -0
- package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +2841 -550
- package/src/modules/customers/commands/deals.ts +19 -0
- package/src/modules/customers/commands/pipeline-stages.ts +68 -13
- package/src/modules/customers/commands/settings.ts +64 -5
- package/src/modules/customers/data/enrichers.ts +209 -2
- package/src/modules/customers/data/entities.ts +4 -1
- package/src/modules/customers/data/validators.ts +36 -2
- package/src/modules/customers/i18n/de.json +244 -0
- package/src/modules/customers/i18n/en.json +244 -0
- package/src/modules/customers/i18n/es.json +244 -0
- package/src/modules/customers/i18n/pl.json +244 -0
- package/src/modules/customers/lib/bulkDeals.ts +231 -0
- package/src/modules/customers/lib/kysely.ts +60 -0
- package/src/modules/customers/lib/stuckDeals.ts +88 -0
- package/src/modules/customers/migrations/.snapshot-open-mercato.json +16 -0
- package/src/modules/customers/migrations/Migration20260513203311_customers.ts +13 -0
- package/src/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.ts +71 -0
- package/src/modules/customers/workers/deals-bulk-update-owner.ts +46 -0
- 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
|
package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageLane.js.map
ADDED
|
@@ -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
|
package/dist/modules/customers/backend/customers/deals/pipeline/components/BulkActionsBar.js.map
ADDED
|
@@ -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": ";AA2EQ,cAcA,YAdA;AAzER,YAAY,WAAW;AACvB,SAAS,UAAU,QAAQ,UAAU,aAAa,SAAS;AAC3D,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AACrB,SAAS,6BAA6B;AAY/B,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmD;AACjD,QAAM,IAAI,KAAK;AAMf,QAAM,UAAU,MAAM;AACpB,QAAI,UAAU,EAAG;AACjB,UAAM,QAAQ,CAAC,UAAyB;AACtC,UAAI,MAAM,QAAQ,SAAU;AAG5B,YAAM,SAAS,SAAS;AACxB,UAAI,QAAQ;AACV,cAAM,MAAM,OAAO;AACnB,YAAI,QAAQ,WAAW,QAAQ,cAAc,OAAO,kBAAmB;AAAA,MACzE;AACA,YAAM,eAAe;AACrB,cAAQ;AAAA,IACV;AACA,aAAS,iBAAiB,WAAW,KAAK;AAC1C,WAAO,MAAM,SAAS,oBAAoB,WAAW,KAAK;AAAA,EAC5D,GAAG,CAAC,OAAO,OAAO,CAAC;AAEnB,MAAI,UAAU,EAAG,QAAO;AAExB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,WAAU;AAAA,MAEV;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,SAAS;AAAA,YACT,cAAY;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,YACA,WAAU;AAAA,YAEV,8BAAC,KAAE,WAAU,UAAS,eAAY,QAAO;AAAA;AAAA,QAC3C;AAAA,QAEA,oBAAC,UAAK,WAAU,oGACb,iBACH;AAAA,QACA,oBAAC,UAAK,WAAU,uBACb;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,QACF,GACF;AAAA,QACC,aACC,qBAAC,UAAK,WAAU,+CAA8C;AAAA;AAAA,UAC1D;AAAA,UACD;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA,EAAE,OAAO,WAAW;AAAA,UACtB;AAAA,WACF,IACE;AAAA,QAEJ,qBAAC,SAAI,WAAU,mCACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAU;AAAA,cAEV;AAAA,oCAAC,YAAS,WAAU,UAAS,eAAY,QAAO;AAAA,gBAChD,oBAAC,UACE;AAAA,kBACC;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF,GACF;AAAA;AAAA;AAAA,UACF;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAU;AAAA,cAEV;AAAA,oCAAC,eAAY,WAAU,UAAS,eAAY,QAAO;AAAA,gBACnD,oBAAC,UACE;AAAA,kBACC;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF,GACF;AAAA;AAAA;AAAA,UACF;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAU;AAAA,cAEV;AAAA,oCAAC,YAAS,WAAU,UAAS,eAAY,QAAO;AAAA,gBAChD,oBAAC,UACE;AAAA,kBACC;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF,GACF;AAAA;AAAA;AAAA,UACF;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAU;AAAA,cAEV;AAAA,oCAAC,UAAO,WAAU,UAAS,eAAY,QAAO;AAAA,gBAC9C,oBAAC,UACE;AAAA,kBACC;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF,GACF;AAAA;AAAA;AAAA,UACF;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,yBAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.js
ADDED
|
@@ -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
|
package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.js.map
ADDED
|
@@ -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
|
+
}
|
package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeStageDialog.js
ADDED
|
@@ -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
|
package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeStageDialog.js.map
ADDED
|
@@ -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
|
+
}
|