@contractspec/example.crm-pipeline 3.7.6 → 3.7.7
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 +8 -8
- package/AGENTS.md +51 -33
- package/README.md +66 -148
- package/dist/browser/events/contact.event.js +1 -1
- package/dist/browser/events/deal.event.js +1 -1
- package/dist/browser/events/index.js +3 -3
- package/dist/browser/events/task.event.js +1 -1
- package/dist/browser/index.js +293 -293
- package/dist/browser/ui/CrmDashboard.js +221 -221
- package/dist/browser/ui/CrmDealCard.js +5 -5
- package/dist/browser/ui/CrmPipelineBoard.js +13 -13
- package/dist/browser/ui/hooks/index.js +2 -2
- package/dist/browser/ui/hooks/useDealList.js +1 -1
- package/dist/browser/ui/hooks/useDealMutations.js +1 -1
- package/dist/browser/ui/index.js +290 -290
- package/dist/browser/ui/modals/CreateDealModal.js +12 -12
- package/dist/browser/ui/modals/DealActionsModal.js +21 -21
- package/dist/browser/ui/modals/index.js +33 -33
- package/dist/browser/ui/renderers/index.js +116 -116
- package/dist/browser/ui/renderers/pipeline.renderer.js +97 -97
- package/dist/deal/index.d.ts +2 -2
- package/dist/events/contact.event.js +1 -1
- package/dist/events/deal.event.js +1 -1
- package/dist/events/index.js +3 -3
- package/dist/events/task.event.js +1 -1
- package/dist/handlers/index.d.ts +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +293 -293
- package/dist/node/events/contact.event.js +1 -1
- package/dist/node/events/deal.event.js +1 -1
- package/dist/node/events/index.js +3 -3
- package/dist/node/events/task.event.js +1 -1
- package/dist/node/index.js +293 -293
- package/dist/node/ui/CrmDashboard.js +221 -221
- package/dist/node/ui/CrmDealCard.js +5 -5
- package/dist/node/ui/CrmPipelineBoard.js +13 -13
- package/dist/node/ui/hooks/index.js +2 -2
- package/dist/node/ui/hooks/useDealList.js +1 -1
- package/dist/node/ui/hooks/useDealMutations.js +1 -1
- package/dist/node/ui/index.js +290 -290
- package/dist/node/ui/modals/CreateDealModal.js +12 -12
- package/dist/node/ui/modals/DealActionsModal.js +21 -21
- package/dist/node/ui/modals/index.js +33 -33
- package/dist/node/ui/renderers/index.js +116 -116
- package/dist/node/ui/renderers/pipeline.renderer.js +97 -97
- package/dist/operations/index.d.ts +1 -1
- package/dist/ui/CrmDashboard.js +221 -221
- package/dist/ui/CrmDealCard.js +5 -5
- package/dist/ui/CrmPipelineBoard.js +13 -13
- package/dist/ui/hooks/index.d.ts +2 -2
- package/dist/ui/hooks/index.js +2 -2
- package/dist/ui/hooks/useDealList.js +1 -1
- package/dist/ui/hooks/useDealMutations.d.ts +9 -0
- package/dist/ui/hooks/useDealMutations.js +1 -1
- package/dist/ui/index.d.ts +3 -3
- package/dist/ui/index.js +290 -290
- package/dist/ui/modals/CreateDealModal.js +12 -12
- package/dist/ui/modals/DealActionsModal.js +21 -21
- package/dist/ui/modals/index.js +33 -33
- package/dist/ui/renderers/index.d.ts +1 -1
- package/dist/ui/renderers/index.js +116 -116
- package/dist/ui/renderers/pipeline.renderer.d.ts +1 -1
- package/dist/ui/renderers/pipeline.renderer.js +97 -97
- package/package.json +10 -10
- package/src/crm-pipeline.feature.ts +86 -86
- package/src/deal/deal.enum.ts +8 -8
- package/src/deal/deal.operation.ts +255 -255
- package/src/deal/deal.schema.ts +92 -92
- package/src/deal/deal.test-spec.ts +48 -48
- package/src/deal/index.ts +17 -19
- package/src/docs/crm-pipeline.docblock.ts +43 -43
- package/src/entities/company.entity.ts +52 -52
- package/src/entities/contact.entity.ts +67 -67
- package/src/entities/deal.entity.ts +134 -134
- package/src/entities/index.ts +27 -27
- package/src/entities/task.entity.ts +105 -105
- package/src/events/contact.event.ts +22 -22
- package/src/events/deal.event.ts +77 -77
- package/src/events/task.event.ts +19 -19
- package/src/example.ts +32 -32
- package/src/handlers/crm.handlers.ts +358 -357
- package/src/handlers/deal.handlers.ts +179 -179
- package/src/handlers/index.ts +18 -19
- package/src/handlers/mock-data.ts +167 -167
- package/src/index.ts +11 -11
- package/src/operations/index.ts +16 -16
- package/src/presentations/dashboard.presentation.ts +45 -45
- package/src/presentations/pipeline.presentation.ts +90 -90
- package/src/seeders/index.ts +26 -26
- package/src/shared/overlay-types.ts +23 -23
- package/src/ui/CrmDashboard.tsx +256 -256
- package/src/ui/CrmDealCard.tsx +64 -64
- package/src/ui/CrmPipelineBoard.tsx +105 -105
- package/src/ui/hooks/index.ts +3 -3
- package/src/ui/hooks/useDealList.ts +85 -85
- package/src/ui/hooks/useDealMutations.ts +151 -150
- package/src/ui/index.ts +5 -10
- package/src/ui/modals/CreateDealModal.tsx +217 -217
- package/src/ui/modals/DealActionsModal.tsx +390 -390
- package/src/ui/overlays/demo-overlays.ts +43 -43
- package/src/ui/renderers/index.ts +4 -3
- package/src/ui/renderers/pipeline.markdown.ts +165 -165
- package/src/ui/renderers/pipeline.renderer.tsx +17 -16
- package/tsconfig.json +7 -8
- package/tsdown.config.js +7 -3
package/dist/ui/CrmDashboard.js
CHANGED
|
@@ -1,17 +1,175 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
// src/ui/CrmDealCard.tsx
|
|
3
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
4
|
+
"use client";
|
|
5
|
+
function formatCurrency(value, currency) {
|
|
6
|
+
return new Intl.NumberFormat("en-US", {
|
|
7
|
+
style: "currency",
|
|
8
|
+
currency,
|
|
9
|
+
minimumFractionDigits: 0,
|
|
10
|
+
maximumFractionDigits: 0
|
|
11
|
+
}).format(value);
|
|
12
|
+
}
|
|
13
|
+
function CrmDealCard({ deal, onClick }) {
|
|
14
|
+
const daysUntilClose = deal.expectedCloseDate ? Math.ceil((deal.expectedCloseDate.getTime() - Date.now()) / (1000 * 60 * 60 * 24)) : null;
|
|
15
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
16
|
+
onClick,
|
|
17
|
+
className: "cursor-pointer rounded-lg border border-border bg-card p-3 shadow-sm transition-shadow hover:shadow-md",
|
|
18
|
+
role: "button",
|
|
19
|
+
tabIndex: 0,
|
|
20
|
+
onKeyDown: (e) => {
|
|
21
|
+
if (e.key === "Enter" || e.key === " ")
|
|
22
|
+
onClick?.();
|
|
23
|
+
},
|
|
24
|
+
children: [
|
|
25
|
+
/* @__PURE__ */ jsxDEV("h4", {
|
|
26
|
+
className: "font-medium leading-snug",
|
|
27
|
+
children: deal.name
|
|
28
|
+
}, undefined, false, undefined, this),
|
|
29
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
30
|
+
className: "mt-2 font-semibold text-lg text-primary",
|
|
31
|
+
children: formatCurrency(deal.value, deal.currency)
|
|
32
|
+
}, undefined, false, undefined, this),
|
|
33
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
34
|
+
className: "mt-3 flex items-center justify-between text-muted-foreground text-xs",
|
|
35
|
+
children: [
|
|
36
|
+
daysUntilClose !== null && /* @__PURE__ */ jsxDEV("span", {
|
|
37
|
+
className: daysUntilClose < 0 ? "text-red-500" : daysUntilClose <= 7 ? "text-yellow-600 dark:text-yellow-500" : "",
|
|
38
|
+
children: daysUntilClose < 0 ? `${Math.abs(daysUntilClose)}d overdue` : daysUntilClose === 0 ? "Due today" : `${daysUntilClose}d left`
|
|
39
|
+
}, undefined, false, undefined, this),
|
|
40
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
41
|
+
className: `rounded px-1.5 py-0.5 font-medium text-xs ${deal.status === "WON" ? "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400" : deal.status === "LOST" ? "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400" : "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400"}`,
|
|
42
|
+
children: deal.status
|
|
43
|
+
}, undefined, false, undefined, this)
|
|
44
|
+
]
|
|
45
|
+
}, undefined, true, undefined, this)
|
|
46
|
+
]
|
|
47
|
+
}, undefined, true, undefined, this);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/ui/CrmPipelineBoard.tsx
|
|
51
|
+
import { useState } from "react";
|
|
52
|
+
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
53
|
+
"use client";
|
|
54
|
+
function formatCurrency2(value) {
|
|
55
|
+
if (value >= 1e6)
|
|
56
|
+
return `$${(value / 1e6).toFixed(1)}M`;
|
|
57
|
+
if (value >= 1000)
|
|
58
|
+
return `$${(value / 1000).toFixed(0)}K`;
|
|
59
|
+
return `$${value}`;
|
|
60
|
+
}
|
|
61
|
+
function CrmPipelineBoard({
|
|
62
|
+
dealsByStage,
|
|
63
|
+
stages,
|
|
64
|
+
onDealClick,
|
|
65
|
+
onDealMove
|
|
66
|
+
}) {
|
|
67
|
+
const [quickMoveOpen, setQuickMoveOpen] = useState(null);
|
|
68
|
+
const sortedStages = [...stages].sort((a, b) => a.position - b.position);
|
|
69
|
+
const handleQuickMove = (dealId, toStageId) => {
|
|
70
|
+
onDealMove?.(dealId, toStageId);
|
|
71
|
+
setQuickMoveOpen(null);
|
|
72
|
+
};
|
|
73
|
+
return /* @__PURE__ */ jsxDEV2("div", {
|
|
74
|
+
className: "flex gap-4 overflow-x-auto pb-4",
|
|
75
|
+
children: sortedStages.map((stage) => {
|
|
76
|
+
const deals = dealsByStage[stage.id] ?? [];
|
|
77
|
+
const stageValue = deals.reduce((sum, d) => sum + d.value, 0);
|
|
78
|
+
return /* @__PURE__ */ jsxDEV2("div", {
|
|
79
|
+
className: "flex w-72 flex-shrink-0 flex-col rounded-lg bg-muted/30",
|
|
80
|
+
children: [
|
|
81
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
82
|
+
className: "flex items-center justify-between border-border border-b px-3 py-2",
|
|
83
|
+
children: [
|
|
84
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
85
|
+
children: [
|
|
86
|
+
/* @__PURE__ */ jsxDEV2("h3", {
|
|
87
|
+
className: "font-medium",
|
|
88
|
+
children: stage.name
|
|
89
|
+
}, undefined, false, undefined, this),
|
|
90
|
+
/* @__PURE__ */ jsxDEV2("p", {
|
|
91
|
+
className: "text-muted-foreground text-xs",
|
|
92
|
+
children: [
|
|
93
|
+
deals.length,
|
|
94
|
+
" deals \xB7 ",
|
|
95
|
+
formatCurrency2(stageValue)
|
|
96
|
+
]
|
|
97
|
+
}, undefined, true, undefined, this)
|
|
98
|
+
]
|
|
99
|
+
}, undefined, true, undefined, this),
|
|
100
|
+
/* @__PURE__ */ jsxDEV2("span", {
|
|
101
|
+
className: "flex h-6 w-6 items-center justify-center rounded-full bg-muted font-medium text-xs",
|
|
102
|
+
children: deals.length
|
|
103
|
+
}, undefined, false, undefined, this)
|
|
104
|
+
]
|
|
105
|
+
}, undefined, true, undefined, this),
|
|
106
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
107
|
+
className: "flex flex-1 flex-col gap-2 p-2",
|
|
108
|
+
children: deals.length === 0 ? /* @__PURE__ */ jsxDEV2("div", {
|
|
109
|
+
className: "flex h-24 items-center justify-center rounded-md border-2 border-muted-foreground/20 border-dashed text-muted-foreground text-xs",
|
|
110
|
+
children: "No deals"
|
|
111
|
+
}, undefined, false, undefined, this) : deals.map((deal) => /* @__PURE__ */ jsxDEV2("div", {
|
|
112
|
+
className: "group relative",
|
|
113
|
+
children: [
|
|
114
|
+
/* @__PURE__ */ jsxDEV2(CrmDealCard, {
|
|
115
|
+
deal,
|
|
116
|
+
onClick: () => onDealClick?.(deal.id)
|
|
117
|
+
}, undefined, false, undefined, this),
|
|
118
|
+
deal.status === "OPEN" && onDealMove && /* @__PURE__ */ jsxDEV2("div", {
|
|
119
|
+
className: "absolute top-1 right-1 opacity-0 transition-opacity group-hover:opacity-100",
|
|
120
|
+
children: [
|
|
121
|
+
/* @__PURE__ */ jsxDEV2("button", {
|
|
122
|
+
type: "button",
|
|
123
|
+
onClick: (e) => {
|
|
124
|
+
e.stopPropagation();
|
|
125
|
+
setQuickMoveOpen(quickMoveOpen === deal.id ? null : deal.id);
|
|
126
|
+
},
|
|
127
|
+
className: "flex h-6 w-6 items-center justify-center rounded border border-border bg-background text-xs shadow-sm hover:bg-muted",
|
|
128
|
+
title: "Quick move",
|
|
129
|
+
children: "\u27A1\uFE0F"
|
|
130
|
+
}, undefined, false, undefined, this),
|
|
131
|
+
quickMoveOpen === deal.id && /* @__PURE__ */ jsxDEV2("div", {
|
|
132
|
+
className: "absolute top-7 right-0 z-20 min-w-[140px] rounded-lg border border-border bg-card py-1 shadow-lg",
|
|
133
|
+
children: [
|
|
134
|
+
/* @__PURE__ */ jsxDEV2("p", {
|
|
135
|
+
className: "px-3 py-1 font-medium text-muted-foreground text-xs",
|
|
136
|
+
children: "Move to:"
|
|
137
|
+
}, undefined, false, undefined, this),
|
|
138
|
+
sortedStages.filter((s) => s.id !== deal.stageId).map((s) => /* @__PURE__ */ jsxDEV2("button", {
|
|
139
|
+
type: "button",
|
|
140
|
+
onClick: (e) => {
|
|
141
|
+
e.stopPropagation();
|
|
142
|
+
handleQuickMove(deal.id, s.id);
|
|
143
|
+
},
|
|
144
|
+
className: "w-full px-3 py-1.5 text-left text-sm hover:bg-muted",
|
|
145
|
+
children: s.name
|
|
146
|
+
}, s.id, false, undefined, this))
|
|
147
|
+
]
|
|
148
|
+
}, undefined, true, undefined, this)
|
|
149
|
+
]
|
|
150
|
+
}, undefined, true, undefined, this)
|
|
151
|
+
]
|
|
152
|
+
}, deal.id, true, undefined, this))
|
|
153
|
+
}, undefined, false, undefined, this)
|
|
154
|
+
]
|
|
155
|
+
}, stage.id, true, undefined, this);
|
|
156
|
+
})
|
|
157
|
+
}, undefined, false, undefined, this);
|
|
158
|
+
}
|
|
159
|
+
|
|
2
160
|
// src/ui/hooks/useDealList.ts
|
|
3
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
4
161
|
import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
|
|
162
|
+
import { useCallback, useEffect, useMemo, useState as useState2 } from "react";
|
|
5
163
|
"use client";
|
|
6
164
|
function useDealList(options = {}) {
|
|
7
165
|
const { handlers, projectId } = useTemplateRuntime();
|
|
8
166
|
const { crm } = handlers;
|
|
9
|
-
const [data, setData] =
|
|
10
|
-
const [dealsByStage, setDealsByStage] =
|
|
11
|
-
const [stages, setStages] =
|
|
12
|
-
const [loading, setLoading] =
|
|
13
|
-
const [error, setError] =
|
|
14
|
-
const [page, setPage] =
|
|
167
|
+
const [data, setData] = useState2(null);
|
|
168
|
+
const [dealsByStage, setDealsByStage] = useState2({});
|
|
169
|
+
const [stages, setStages] = useState2([]);
|
|
170
|
+
const [loading, setLoading] = useState2(true);
|
|
171
|
+
const [error, setError] = useState2(null);
|
|
172
|
+
const [page, setPage] = useState2(1);
|
|
15
173
|
const pipelineId = options.pipelineId ?? "pipeline-1";
|
|
16
174
|
const fetchData = useCallback(async () => {
|
|
17
175
|
setLoading(true);
|
|
@@ -82,27 +240,27 @@ function useDealList(options = {}) {
|
|
|
82
240
|
}
|
|
83
241
|
|
|
84
242
|
// src/ui/hooks/useDealMutations.ts
|
|
85
|
-
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
86
243
|
import { useTemplateRuntime as useTemplateRuntime2 } from "@contractspec/lib.example-shared-ui";
|
|
244
|
+
import { useCallback as useCallback2, useState as useState3 } from "react";
|
|
87
245
|
function useDealMutations(options = {}) {
|
|
88
246
|
const { handlers, projectId } = useTemplateRuntime2();
|
|
89
247
|
const { crm } = handlers;
|
|
90
|
-
const [createState, setCreateState] =
|
|
248
|
+
const [createState, setCreateState] = useState3({
|
|
91
249
|
loading: false,
|
|
92
250
|
error: null,
|
|
93
251
|
data: null
|
|
94
252
|
});
|
|
95
|
-
const [moveState, setMoveState] =
|
|
253
|
+
const [moveState, setMoveState] = useState3({
|
|
96
254
|
loading: false,
|
|
97
255
|
error: null,
|
|
98
256
|
data: null
|
|
99
257
|
});
|
|
100
|
-
const [winState, setWinState] =
|
|
258
|
+
const [winState, setWinState] = useState3({
|
|
101
259
|
loading: false,
|
|
102
260
|
error: null,
|
|
103
261
|
data: null
|
|
104
262
|
});
|
|
105
|
-
const [loseState, setLoseState] =
|
|
263
|
+
const [loseState, setLoseState] = useState3({
|
|
106
264
|
loading: false,
|
|
107
265
|
error: null,
|
|
108
266
|
data: null
|
|
@@ -179,167 +337,9 @@ function useDealMutations(options = {}) {
|
|
|
179
337
|
};
|
|
180
338
|
}
|
|
181
339
|
|
|
182
|
-
// src/ui/CrmDealCard.tsx
|
|
183
|
-
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
184
|
-
"use client";
|
|
185
|
-
function formatCurrency(value, currency) {
|
|
186
|
-
return new Intl.NumberFormat("en-US", {
|
|
187
|
-
style: "currency",
|
|
188
|
-
currency,
|
|
189
|
-
minimumFractionDigits: 0,
|
|
190
|
-
maximumFractionDigits: 0
|
|
191
|
-
}).format(value);
|
|
192
|
-
}
|
|
193
|
-
function CrmDealCard({ deal, onClick }) {
|
|
194
|
-
const daysUntilClose = deal.expectedCloseDate ? Math.ceil((deal.expectedCloseDate.getTime() - Date.now()) / (1000 * 60 * 60 * 24)) : null;
|
|
195
|
-
return /* @__PURE__ */ jsxDEV("div", {
|
|
196
|
-
onClick,
|
|
197
|
-
className: "border-border bg-card cursor-pointer rounded-lg border p-3 shadow-sm transition-shadow hover:shadow-md",
|
|
198
|
-
role: "button",
|
|
199
|
-
tabIndex: 0,
|
|
200
|
-
onKeyDown: (e) => {
|
|
201
|
-
if (e.key === "Enter" || e.key === " ")
|
|
202
|
-
onClick?.();
|
|
203
|
-
},
|
|
204
|
-
children: [
|
|
205
|
-
/* @__PURE__ */ jsxDEV("h4", {
|
|
206
|
-
className: "leading-snug font-medium",
|
|
207
|
-
children: deal.name
|
|
208
|
-
}, undefined, false, undefined, this),
|
|
209
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
210
|
-
className: "text-primary mt-2 text-lg font-semibold",
|
|
211
|
-
children: formatCurrency(deal.value, deal.currency)
|
|
212
|
-
}, undefined, false, undefined, this),
|
|
213
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
214
|
-
className: "text-muted-foreground mt-3 flex items-center justify-between text-xs",
|
|
215
|
-
children: [
|
|
216
|
-
daysUntilClose !== null && /* @__PURE__ */ jsxDEV("span", {
|
|
217
|
-
className: daysUntilClose < 0 ? "text-red-500" : daysUntilClose <= 7 ? "text-yellow-600 dark:text-yellow-500" : "",
|
|
218
|
-
children: daysUntilClose < 0 ? `${Math.abs(daysUntilClose)}d overdue` : daysUntilClose === 0 ? "Due today" : `${daysUntilClose}d left`
|
|
219
|
-
}, undefined, false, undefined, this),
|
|
220
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
221
|
-
className: `rounded px-1.5 py-0.5 text-xs font-medium ${deal.status === "WON" ? "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400" : deal.status === "LOST" ? "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400" : "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400"}`,
|
|
222
|
-
children: deal.status
|
|
223
|
-
}, undefined, false, undefined, this)
|
|
224
|
-
]
|
|
225
|
-
}, undefined, true, undefined, this)
|
|
226
|
-
]
|
|
227
|
-
}, undefined, true, undefined, this);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// src/ui/CrmPipelineBoard.tsx
|
|
231
|
-
import { useState as useState3 } from "react";
|
|
232
|
-
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
233
|
-
"use client";
|
|
234
|
-
function formatCurrency2(value) {
|
|
235
|
-
if (value >= 1e6)
|
|
236
|
-
return `$${(value / 1e6).toFixed(1)}M`;
|
|
237
|
-
if (value >= 1000)
|
|
238
|
-
return `$${(value / 1000).toFixed(0)}K`;
|
|
239
|
-
return `$${value}`;
|
|
240
|
-
}
|
|
241
|
-
function CrmPipelineBoard({
|
|
242
|
-
dealsByStage,
|
|
243
|
-
stages,
|
|
244
|
-
onDealClick,
|
|
245
|
-
onDealMove
|
|
246
|
-
}) {
|
|
247
|
-
const [quickMoveOpen, setQuickMoveOpen] = useState3(null);
|
|
248
|
-
const sortedStages = [...stages].sort((a, b) => a.position - b.position);
|
|
249
|
-
const handleQuickMove = (dealId, toStageId) => {
|
|
250
|
-
onDealMove?.(dealId, toStageId);
|
|
251
|
-
setQuickMoveOpen(null);
|
|
252
|
-
};
|
|
253
|
-
return /* @__PURE__ */ jsxDEV2("div", {
|
|
254
|
-
className: "flex gap-4 overflow-x-auto pb-4",
|
|
255
|
-
children: sortedStages.map((stage) => {
|
|
256
|
-
const deals = dealsByStage[stage.id] ?? [];
|
|
257
|
-
const stageValue = deals.reduce((sum, d) => sum + d.value, 0);
|
|
258
|
-
return /* @__PURE__ */ jsxDEV2("div", {
|
|
259
|
-
className: "bg-muted/30 flex w-72 flex-shrink-0 flex-col rounded-lg",
|
|
260
|
-
children: [
|
|
261
|
-
/* @__PURE__ */ jsxDEV2("div", {
|
|
262
|
-
className: "border-border flex items-center justify-between border-b px-3 py-2",
|
|
263
|
-
children: [
|
|
264
|
-
/* @__PURE__ */ jsxDEV2("div", {
|
|
265
|
-
children: [
|
|
266
|
-
/* @__PURE__ */ jsxDEV2("h3", {
|
|
267
|
-
className: "font-medium",
|
|
268
|
-
children: stage.name
|
|
269
|
-
}, undefined, false, undefined, this),
|
|
270
|
-
/* @__PURE__ */ jsxDEV2("p", {
|
|
271
|
-
className: "text-muted-foreground text-xs",
|
|
272
|
-
children: [
|
|
273
|
-
deals.length,
|
|
274
|
-
" deals \xB7 ",
|
|
275
|
-
formatCurrency2(stageValue)
|
|
276
|
-
]
|
|
277
|
-
}, undefined, true, undefined, this)
|
|
278
|
-
]
|
|
279
|
-
}, undefined, true, undefined, this),
|
|
280
|
-
/* @__PURE__ */ jsxDEV2("span", {
|
|
281
|
-
className: "bg-muted flex h-6 w-6 items-center justify-center rounded-full text-xs font-medium",
|
|
282
|
-
children: deals.length
|
|
283
|
-
}, undefined, false, undefined, this)
|
|
284
|
-
]
|
|
285
|
-
}, undefined, true, undefined, this),
|
|
286
|
-
/* @__PURE__ */ jsxDEV2("div", {
|
|
287
|
-
className: "flex flex-1 flex-col gap-2 p-2",
|
|
288
|
-
children: deals.length === 0 ? /* @__PURE__ */ jsxDEV2("div", {
|
|
289
|
-
className: "border-muted-foreground/20 text-muted-foreground flex h-24 items-center justify-center rounded-md border-2 border-dashed text-xs",
|
|
290
|
-
children: "No deals"
|
|
291
|
-
}, undefined, false, undefined, this) : deals.map((deal) => /* @__PURE__ */ jsxDEV2("div", {
|
|
292
|
-
className: "group relative",
|
|
293
|
-
children: [
|
|
294
|
-
/* @__PURE__ */ jsxDEV2(CrmDealCard, {
|
|
295
|
-
deal,
|
|
296
|
-
onClick: () => onDealClick?.(deal.id)
|
|
297
|
-
}, undefined, false, undefined, this),
|
|
298
|
-
deal.status === "OPEN" && onDealMove && /* @__PURE__ */ jsxDEV2("div", {
|
|
299
|
-
className: "absolute top-1 right-1 opacity-0 transition-opacity group-hover:opacity-100",
|
|
300
|
-
children: [
|
|
301
|
-
/* @__PURE__ */ jsxDEV2("button", {
|
|
302
|
-
type: "button",
|
|
303
|
-
onClick: (e) => {
|
|
304
|
-
e.stopPropagation();
|
|
305
|
-
setQuickMoveOpen(quickMoveOpen === deal.id ? null : deal.id);
|
|
306
|
-
},
|
|
307
|
-
className: "bg-background border-border hover:bg-muted flex h-6 w-6 items-center justify-center rounded border text-xs shadow-sm",
|
|
308
|
-
title: "Quick move",
|
|
309
|
-
children: "\u27A1\uFE0F"
|
|
310
|
-
}, undefined, false, undefined, this),
|
|
311
|
-
quickMoveOpen === deal.id && /* @__PURE__ */ jsxDEV2("div", {
|
|
312
|
-
className: "bg-card border-border absolute top-7 right-0 z-20 min-w-[140px] rounded-lg border py-1 shadow-lg",
|
|
313
|
-
children: [
|
|
314
|
-
/* @__PURE__ */ jsxDEV2("p", {
|
|
315
|
-
className: "text-muted-foreground px-3 py-1 text-xs font-medium",
|
|
316
|
-
children: "Move to:"
|
|
317
|
-
}, undefined, false, undefined, this),
|
|
318
|
-
sortedStages.filter((s) => s.id !== deal.stageId).map((s) => /* @__PURE__ */ jsxDEV2("button", {
|
|
319
|
-
type: "button",
|
|
320
|
-
onClick: (e) => {
|
|
321
|
-
e.stopPropagation();
|
|
322
|
-
handleQuickMove(deal.id, s.id);
|
|
323
|
-
},
|
|
324
|
-
className: "hover:bg-muted w-full px-3 py-1.5 text-left text-sm",
|
|
325
|
-
children: s.name
|
|
326
|
-
}, s.id, false, undefined, this))
|
|
327
|
-
]
|
|
328
|
-
}, undefined, true, undefined, this)
|
|
329
|
-
]
|
|
330
|
-
}, undefined, true, undefined, this)
|
|
331
|
-
]
|
|
332
|
-
}, deal.id, true, undefined, this))
|
|
333
|
-
}, undefined, false, undefined, this)
|
|
334
|
-
]
|
|
335
|
-
}, stage.id, true, undefined, this);
|
|
336
|
-
})
|
|
337
|
-
}, undefined, false, undefined, this);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
340
|
// src/ui/modals/CreateDealModal.tsx
|
|
341
|
-
import { useState as useState4 } from "react";
|
|
342
341
|
import { Button, Input } from "@contractspec/lib.design-system";
|
|
342
|
+
import { useState as useState4 } from "react";
|
|
343
343
|
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
344
344
|
"use client";
|
|
345
345
|
var CURRENCIES = ["USD", "EUR", "GBP", "CAD"];
|
|
@@ -398,7 +398,7 @@ function CreateDealModal({
|
|
|
398
398
|
className: "fixed inset-0 z-50 flex items-center justify-center",
|
|
399
399
|
children: [
|
|
400
400
|
/* @__PURE__ */ jsxDEV3("div", {
|
|
401
|
-
className: "bg-background/80
|
|
401
|
+
className: "absolute inset-0 bg-background/80 backdrop-blur-sm",
|
|
402
402
|
onClick: onClose,
|
|
403
403
|
role: "button",
|
|
404
404
|
tabIndex: 0,
|
|
@@ -409,10 +409,10 @@ function CreateDealModal({
|
|
|
409
409
|
"aria-label": "Close modal"
|
|
410
410
|
}, undefined, false, undefined, this),
|
|
411
411
|
/* @__PURE__ */ jsxDEV3("div", {
|
|
412
|
-
className: "
|
|
412
|
+
className: "relative z-10 w-full max-w-md rounded-xl border border-border bg-card p-6 shadow-xl",
|
|
413
413
|
children: [
|
|
414
414
|
/* @__PURE__ */ jsxDEV3("h2", {
|
|
415
|
-
className: "mb-4 text-xl
|
|
415
|
+
className: "mb-4 font-semibold text-xl",
|
|
416
416
|
children: "Create New Deal"
|
|
417
417
|
}, undefined, false, undefined, this),
|
|
418
418
|
/* @__PURE__ */ jsxDEV3("form", {
|
|
@@ -423,7 +423,7 @@ function CreateDealModal({
|
|
|
423
423
|
children: [
|
|
424
424
|
/* @__PURE__ */ jsxDEV3("label", {
|
|
425
425
|
htmlFor: "deal-name",
|
|
426
|
-
className: "
|
|
426
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
427
427
|
children: "Deal Name *"
|
|
428
428
|
}, undefined, false, undefined, this),
|
|
429
429
|
/* @__PURE__ */ jsxDEV3(Input, {
|
|
@@ -443,7 +443,7 @@ function CreateDealModal({
|
|
|
443
443
|
children: [
|
|
444
444
|
/* @__PURE__ */ jsxDEV3("label", {
|
|
445
445
|
htmlFor: "deal-value",
|
|
446
|
-
className: "
|
|
446
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
447
447
|
children: "Value *"
|
|
448
448
|
}, undefined, false, undefined, this),
|
|
449
449
|
/* @__PURE__ */ jsxDEV3(Input, {
|
|
@@ -463,7 +463,7 @@ function CreateDealModal({
|
|
|
463
463
|
children: [
|
|
464
464
|
/* @__PURE__ */ jsxDEV3("label", {
|
|
465
465
|
htmlFor: "deal-currency",
|
|
466
|
-
className: "
|
|
466
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
467
467
|
children: "Currency"
|
|
468
468
|
}, undefined, false, undefined, this),
|
|
469
469
|
/* @__PURE__ */ jsxDEV3("select", {
|
|
@@ -471,7 +471,7 @@ function CreateDealModal({
|
|
|
471
471
|
value: currency,
|
|
472
472
|
onChange: (e) => setCurrency(e.target.value),
|
|
473
473
|
disabled: isLoading,
|
|
474
|
-
className: "
|
|
474
|
+
className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50",
|
|
475
475
|
children: CURRENCIES.map((c) => /* @__PURE__ */ jsxDEV3("option", {
|
|
476
476
|
value: c,
|
|
477
477
|
children: c
|
|
@@ -485,7 +485,7 @@ function CreateDealModal({
|
|
|
485
485
|
children: [
|
|
486
486
|
/* @__PURE__ */ jsxDEV3("label", {
|
|
487
487
|
htmlFor: "deal-stage",
|
|
488
|
-
className: "
|
|
488
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
489
489
|
children: "Pipeline Stage *"
|
|
490
490
|
}, undefined, false, undefined, this),
|
|
491
491
|
/* @__PURE__ */ jsxDEV3("select", {
|
|
@@ -493,7 +493,7 @@ function CreateDealModal({
|
|
|
493
493
|
value: stageId,
|
|
494
494
|
onChange: (e) => setStageId(e.target.value),
|
|
495
495
|
disabled: isLoading,
|
|
496
|
-
className: "
|
|
496
|
+
className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50",
|
|
497
497
|
children: stages.map((stage) => /* @__PURE__ */ jsxDEV3("option", {
|
|
498
498
|
value: stage.id,
|
|
499
499
|
children: stage.name
|
|
@@ -505,7 +505,7 @@ function CreateDealModal({
|
|
|
505
505
|
children: [
|
|
506
506
|
/* @__PURE__ */ jsxDEV3("label", {
|
|
507
507
|
htmlFor: "deal-close-date",
|
|
508
|
-
className: "
|
|
508
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
509
509
|
children: "Expected Close Date"
|
|
510
510
|
}, undefined, false, undefined, this),
|
|
511
511
|
/* @__PURE__ */ jsxDEV3(Input, {
|
|
@@ -518,7 +518,7 @@ function CreateDealModal({
|
|
|
518
518
|
]
|
|
519
519
|
}, undefined, true, undefined, this),
|
|
520
520
|
error && /* @__PURE__ */ jsxDEV3("div", {
|
|
521
|
-
className: "bg-destructive/10
|
|
521
|
+
className: "rounded-md bg-destructive/10 p-3 text-destructive text-sm",
|
|
522
522
|
children: error
|
|
523
523
|
}, undefined, false, undefined, this),
|
|
524
524
|
/* @__PURE__ */ jsxDEV3("div", {
|
|
@@ -547,8 +547,8 @@ function CreateDealModal({
|
|
|
547
547
|
}
|
|
548
548
|
|
|
549
549
|
// src/ui/modals/DealActionsModal.tsx
|
|
550
|
-
import { useState as useState5 } from "react";
|
|
551
550
|
import { Button as Button2 } from "@contractspec/lib.design-system";
|
|
551
|
+
import { useState as useState5 } from "react";
|
|
552
552
|
import { jsxDEV as jsxDEV4, Fragment } from "react/jsx-dev-runtime";
|
|
553
553
|
"use client";
|
|
554
554
|
function formatCurrency3(value, currency) {
|
|
@@ -649,7 +649,7 @@ function DealActionsModal({
|
|
|
649
649
|
className: "fixed inset-0 z-50 flex items-center justify-center",
|
|
650
650
|
children: [
|
|
651
651
|
/* @__PURE__ */ jsxDEV4("div", {
|
|
652
|
-
className: "bg-background/80
|
|
652
|
+
className: "absolute inset-0 bg-background/80 backdrop-blur-sm",
|
|
653
653
|
onClick: handleClose,
|
|
654
654
|
role: "button",
|
|
655
655
|
tabIndex: 0,
|
|
@@ -660,21 +660,21 @@ function DealActionsModal({
|
|
|
660
660
|
"aria-label": "Close modal"
|
|
661
661
|
}, undefined, false, undefined, this),
|
|
662
662
|
/* @__PURE__ */ jsxDEV4("div", {
|
|
663
|
-
className: "
|
|
663
|
+
className: "relative z-10 w-full max-w-md rounded-xl border border-border bg-card p-6 shadow-xl",
|
|
664
664
|
children: [
|
|
665
665
|
/* @__PURE__ */ jsxDEV4("div", {
|
|
666
|
-
className: "
|
|
666
|
+
className: "mb-4 border-border border-b pb-4",
|
|
667
667
|
children: [
|
|
668
668
|
/* @__PURE__ */ jsxDEV4("h2", {
|
|
669
|
-
className: "text-xl
|
|
669
|
+
className: "font-semibold text-xl",
|
|
670
670
|
children: deal.name
|
|
671
671
|
}, undefined, false, undefined, this),
|
|
672
672
|
/* @__PURE__ */ jsxDEV4("p", {
|
|
673
|
-
className: "
|
|
673
|
+
className: "font-medium text-lg text-primary",
|
|
674
674
|
children: formatCurrency3(deal.value, deal.currency)
|
|
675
675
|
}, undefined, false, undefined, this),
|
|
676
676
|
/* @__PURE__ */ jsxDEV4("span", {
|
|
677
|
-
className: `mt-2 inline-flex rounded-full px-2 py-0.5 text-xs
|
|
677
|
+
className: `mt-2 inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${deal.status === "WON" ? "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400" : deal.status === "LOST" ? "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400" : "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400"}`,
|
|
678
678
|
children: deal.status
|
|
679
679
|
}, undefined, false, undefined, this)
|
|
680
680
|
]
|
|
@@ -726,7 +726,7 @@ function DealActionsModal({
|
|
|
726
726
|
]
|
|
727
727
|
}, undefined, true, undefined, this),
|
|
728
728
|
deal.status !== "OPEN" && /* @__PURE__ */ jsxDEV4("p", {
|
|
729
|
-
className: "
|
|
729
|
+
className: "py-4 text-center text-muted-foreground",
|
|
730
730
|
children: [
|
|
731
731
|
"This deal is already ",
|
|
732
732
|
deal.status.toLowerCase(),
|
|
@@ -751,14 +751,14 @@ function DealActionsModal({
|
|
|
751
751
|
children: [
|
|
752
752
|
/* @__PURE__ */ jsxDEV4("label", {
|
|
753
753
|
htmlFor: "won-source",
|
|
754
|
-
className: "
|
|
754
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
755
755
|
children: "How did you win this deal?"
|
|
756
756
|
}, undefined, false, undefined, this),
|
|
757
757
|
/* @__PURE__ */ jsxDEV4("select", {
|
|
758
758
|
id: "won-source",
|
|
759
759
|
value: wonSource,
|
|
760
760
|
onChange: (e) => setWonSource(e.target.value),
|
|
761
|
-
className: "
|
|
761
|
+
className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring",
|
|
762
762
|
children: [
|
|
763
763
|
/* @__PURE__ */ jsxDEV4("option", {
|
|
764
764
|
value: "",
|
|
@@ -792,7 +792,7 @@ function DealActionsModal({
|
|
|
792
792
|
children: [
|
|
793
793
|
/* @__PURE__ */ jsxDEV4("label", {
|
|
794
794
|
htmlFor: "win-notes",
|
|
795
|
-
className: "
|
|
795
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
796
796
|
children: "Notes (optional)"
|
|
797
797
|
}, undefined, false, undefined, this),
|
|
798
798
|
/* @__PURE__ */ jsxDEV4("textarea", {
|
|
@@ -801,12 +801,12 @@ function DealActionsModal({
|
|
|
801
801
|
onChange: (e) => setNotes(e.target.value),
|
|
802
802
|
placeholder: "Any additional notes about the win...",
|
|
803
803
|
rows: 3,
|
|
804
|
-
className: "
|
|
804
|
+
className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
|
|
805
805
|
}, undefined, false, undefined, this)
|
|
806
806
|
]
|
|
807
807
|
}, undefined, true, undefined, this),
|
|
808
808
|
error && /* @__PURE__ */ jsxDEV4("div", {
|
|
809
|
-
className: "bg-destructive/10
|
|
809
|
+
className: "rounded-md bg-destructive/10 p-3 text-destructive text-sm",
|
|
810
810
|
children: error
|
|
811
811
|
}, undefined, false, undefined, this),
|
|
812
812
|
/* @__PURE__ */ jsxDEV4("div", {
|
|
@@ -834,14 +834,14 @@ function DealActionsModal({
|
|
|
834
834
|
children: [
|
|
835
835
|
/* @__PURE__ */ jsxDEV4("label", {
|
|
836
836
|
htmlFor: "lost-reason",
|
|
837
|
-
className: "
|
|
837
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
838
838
|
children: "Why was this deal lost? *"
|
|
839
839
|
}, undefined, false, undefined, this),
|
|
840
840
|
/* @__PURE__ */ jsxDEV4("select", {
|
|
841
841
|
id: "lost-reason",
|
|
842
842
|
value: lostReason,
|
|
843
843
|
onChange: (e) => setLostReason(e.target.value),
|
|
844
|
-
className: "
|
|
844
|
+
className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring",
|
|
845
845
|
children: [
|
|
846
846
|
/* @__PURE__ */ jsxDEV4("option", {
|
|
847
847
|
value: "",
|
|
@@ -883,7 +883,7 @@ function DealActionsModal({
|
|
|
883
883
|
children: [
|
|
884
884
|
/* @__PURE__ */ jsxDEV4("label", {
|
|
885
885
|
htmlFor: "lose-notes",
|
|
886
|
-
className: "
|
|
886
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
887
887
|
children: "Notes (optional)"
|
|
888
888
|
}, undefined, false, undefined, this),
|
|
889
889
|
/* @__PURE__ */ jsxDEV4("textarea", {
|
|
@@ -892,12 +892,12 @@ function DealActionsModal({
|
|
|
892
892
|
onChange: (e) => setNotes(e.target.value),
|
|
893
893
|
placeholder: "Any additional details...",
|
|
894
894
|
rows: 3,
|
|
895
|
-
className: "
|
|
895
|
+
className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
|
|
896
896
|
}, undefined, false, undefined, this)
|
|
897
897
|
]
|
|
898
898
|
}, undefined, true, undefined, this),
|
|
899
899
|
error && /* @__PURE__ */ jsxDEV4("div", {
|
|
900
|
-
className: "bg-destructive/10
|
|
900
|
+
className: "rounded-md bg-destructive/10 p-3 text-destructive text-sm",
|
|
901
901
|
children: error
|
|
902
902
|
}, undefined, false, undefined, this),
|
|
903
903
|
/* @__PURE__ */ jsxDEV4("div", {
|
|
@@ -926,14 +926,14 @@ function DealActionsModal({
|
|
|
926
926
|
children: [
|
|
927
927
|
/* @__PURE__ */ jsxDEV4("label", {
|
|
928
928
|
htmlFor: "move-stage",
|
|
929
|
-
className: "
|
|
929
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
930
930
|
children: "Move to Stage"
|
|
931
931
|
}, undefined, false, undefined, this),
|
|
932
932
|
/* @__PURE__ */ jsxDEV4("select", {
|
|
933
933
|
id: "move-stage",
|
|
934
934
|
value: selectedStageId,
|
|
935
935
|
onChange: (e) => setSelectedStageId(e.target.value),
|
|
936
|
-
className: "
|
|
936
|
+
className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring",
|
|
937
937
|
children: stages.map((stage) => /* @__PURE__ */ jsxDEV4("option", {
|
|
938
938
|
value: stage.id,
|
|
939
939
|
children: [
|
|
@@ -945,7 +945,7 @@ function DealActionsModal({
|
|
|
945
945
|
]
|
|
946
946
|
}, undefined, true, undefined, this),
|
|
947
947
|
error && /* @__PURE__ */ jsxDEV4("div", {
|
|
948
|
-
className: "bg-destructive/10
|
|
948
|
+
className: "rounded-md bg-destructive/10 p-3 text-destructive text-sm",
|
|
949
949
|
children: error
|
|
950
950
|
}, undefined, false, undefined, this),
|
|
951
951
|
/* @__PURE__ */ jsxDEV4("div", {
|
|
@@ -973,7 +973,6 @@ function DealActionsModal({
|
|
|
973
973
|
}
|
|
974
974
|
|
|
975
975
|
// src/ui/CrmDashboard.tsx
|
|
976
|
-
import { useCallback as useCallback3, useState as useState6 } from "react";
|
|
977
976
|
import {
|
|
978
977
|
Button as Button3,
|
|
979
978
|
ErrorState,
|
|
@@ -987,6 +986,7 @@ import {
|
|
|
987
986
|
TabsList,
|
|
988
987
|
TabsTrigger
|
|
989
988
|
} from "@contractspec/lib.ui-kit-web/ui/tabs";
|
|
989
|
+
import { useCallback as useCallback3, useState as useState6 } from "react";
|
|
990
990
|
import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
|
|
991
991
|
"use client";
|
|
992
992
|
function formatCurrency4(value, currency = "USD") {
|
|
@@ -1037,7 +1037,7 @@ function CrmDashboard() {
|
|
|
1037
1037
|
className: "flex items-center justify-between",
|
|
1038
1038
|
children: [
|
|
1039
1039
|
/* @__PURE__ */ jsxDEV5("h2", {
|
|
1040
|
-
className: "text-2xl
|
|
1040
|
+
className: "font-bold text-2xl",
|
|
1041
1041
|
children: "CRM Pipeline"
|
|
1042
1042
|
}, undefined, false, undefined, this),
|
|
1043
1043
|
/* @__PURE__ */ jsxDEV5(Button3, {
|
|
@@ -1176,44 +1176,44 @@ function CrmDashboard() {
|
|
|
1176
1176
|
function DealListTab({ data, onDealClick }) {
|
|
1177
1177
|
if (!data?.deals.length) {
|
|
1178
1178
|
return /* @__PURE__ */ jsxDEV5("div", {
|
|
1179
|
-
className: "
|
|
1179
|
+
className: "flex h-64 items-center justify-center text-muted-foreground",
|
|
1180
1180
|
children: "No deals found"
|
|
1181
1181
|
}, undefined, false, undefined, this);
|
|
1182
1182
|
}
|
|
1183
1183
|
return /* @__PURE__ */ jsxDEV5("div", {
|
|
1184
|
-
className: "
|
|
1184
|
+
className: "rounded-lg border border-border",
|
|
1185
1185
|
children: /* @__PURE__ */ jsxDEV5("table", {
|
|
1186
1186
|
className: "w-full",
|
|
1187
1187
|
children: [
|
|
1188
1188
|
/* @__PURE__ */ jsxDEV5("thead", {
|
|
1189
|
-
className: "border-border bg-muted/30
|
|
1189
|
+
className: "border-border border-b bg-muted/30",
|
|
1190
1190
|
children: /* @__PURE__ */ jsxDEV5("tr", {
|
|
1191
1191
|
children: [
|
|
1192
1192
|
/* @__PURE__ */ jsxDEV5("th", {
|
|
1193
|
-
className: "px-4 py-3 text-left text-sm
|
|
1193
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
1194
1194
|
children: "Deal"
|
|
1195
1195
|
}, undefined, false, undefined, this),
|
|
1196
1196
|
/* @__PURE__ */ jsxDEV5("th", {
|
|
1197
|
-
className: "px-4 py-3 text-left text-sm
|
|
1197
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
1198
1198
|
children: "Value"
|
|
1199
1199
|
}, undefined, false, undefined, this),
|
|
1200
1200
|
/* @__PURE__ */ jsxDEV5("th", {
|
|
1201
|
-
className: "px-4 py-3 text-left text-sm
|
|
1201
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
1202
1202
|
children: "Status"
|
|
1203
1203
|
}, undefined, false, undefined, this),
|
|
1204
1204
|
/* @__PURE__ */ jsxDEV5("th", {
|
|
1205
|
-
className: "px-4 py-3 text-left text-sm
|
|
1205
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
1206
1206
|
children: "Expected Close"
|
|
1207
1207
|
}, undefined, false, undefined, this),
|
|
1208
1208
|
/* @__PURE__ */ jsxDEV5("th", {
|
|
1209
|
-
className: "px-4 py-3 text-left text-sm
|
|
1209
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
1210
1210
|
children: "Actions"
|
|
1211
1211
|
}, undefined, false, undefined, this)
|
|
1212
1212
|
]
|
|
1213
1213
|
}, undefined, true, undefined, this)
|
|
1214
1214
|
}, undefined, false, undefined, this),
|
|
1215
1215
|
/* @__PURE__ */ jsxDEV5("tbody", {
|
|
1216
|
-
className: "divide-
|
|
1216
|
+
className: "divide-y divide-border",
|
|
1217
1217
|
children: data.deals.map((deal) => /* @__PURE__ */ jsxDEV5("tr", {
|
|
1218
1218
|
className: "hover:bg-muted/50",
|
|
1219
1219
|
children: [
|
|
@@ -1231,12 +1231,12 @@ function DealListTab({ data, onDealClick }) {
|
|
|
1231
1231
|
/* @__PURE__ */ jsxDEV5("td", {
|
|
1232
1232
|
className: "px-4 py-3",
|
|
1233
1233
|
children: /* @__PURE__ */ jsxDEV5("span", {
|
|
1234
|
-
className: `inline-flex rounded-full px-2 py-0.5 text-xs
|
|
1234
|
+
className: `inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${deal.status === "WON" ? "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400" : deal.status === "LOST" ? "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400" : "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400"}`,
|
|
1235
1235
|
children: deal.status
|
|
1236
1236
|
}, undefined, false, undefined, this)
|
|
1237
1237
|
}, undefined, false, undefined, this),
|
|
1238
1238
|
/* @__PURE__ */ jsxDEV5("td", {
|
|
1239
|
-
className: "
|
|
1239
|
+
className: "px-4 py-3 text-muted-foreground",
|
|
1240
1240
|
children: deal.expectedCloseDate?.toLocaleDateString() ?? "-"
|
|
1241
1241
|
}, undefined, false, undefined, this),
|
|
1242
1242
|
/* @__PURE__ */ jsxDEV5("td", {
|
|
@@ -1263,10 +1263,10 @@ function MetricsTab({
|
|
|
1263
1263
|
return /* @__PURE__ */ jsxDEV5("div", {
|
|
1264
1264
|
className: "space-y-6",
|
|
1265
1265
|
children: /* @__PURE__ */ jsxDEV5("div", {
|
|
1266
|
-
className: "border-border bg-card
|
|
1266
|
+
className: "rounded-xl border border-border bg-card p-6",
|
|
1267
1267
|
children: [
|
|
1268
1268
|
/* @__PURE__ */ jsxDEV5("h3", {
|
|
1269
|
-
className: "mb-4 text-lg
|
|
1269
|
+
className: "mb-4 font-semibold text-lg",
|
|
1270
1270
|
children: "Pipeline Overview"
|
|
1271
1271
|
}, undefined, false, undefined, this),
|
|
1272
1272
|
/* @__PURE__ */ jsxDEV5("dl", {
|
|
@@ -1279,7 +1279,7 @@ function MetricsTab({
|
|
|
1279
1279
|
children: "Win Rate"
|
|
1280
1280
|
}, undefined, false, undefined, this),
|
|
1281
1281
|
/* @__PURE__ */ jsxDEV5("dd", {
|
|
1282
|
-
className: "text-2xl
|
|
1282
|
+
className: "font-semibold text-2xl",
|
|
1283
1283
|
children: [
|
|
1284
1284
|
stats.total > 0 ? (stats.wonCount / stats.total * 100).toFixed(0) : 0,
|
|
1285
1285
|
"%"
|
|
@@ -1294,7 +1294,7 @@ function MetricsTab({
|
|
|
1294
1294
|
children: "Avg Deal Size"
|
|
1295
1295
|
}, undefined, false, undefined, this),
|
|
1296
1296
|
/* @__PURE__ */ jsxDEV5("dd", {
|
|
1297
|
-
className: "text-2xl
|
|
1297
|
+
className: "font-semibold text-2xl",
|
|
1298
1298
|
children: formatCurrency4(stats.total > 0 ? stats.totalValue / stats.total : 0)
|
|
1299
1299
|
}, undefined, false, undefined, this)
|
|
1300
1300
|
]
|
|
@@ -1306,7 +1306,7 @@ function MetricsTab({
|
|
|
1306
1306
|
children: "Conversion"
|
|
1307
1307
|
}, undefined, false, undefined, this),
|
|
1308
1308
|
/* @__PURE__ */ jsxDEV5("dd", {
|
|
1309
|
-
className: "text-2xl
|
|
1309
|
+
className: "font-semibold text-2xl",
|
|
1310
1310
|
children: [
|
|
1311
1311
|
stats.wonCount,
|
|
1312
1312
|
" / ",
|