@elevasis/ui 2.22.0 → 2.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/app/index.d.ts +2915 -0
  2. package/dist/app/index.js +5 -4
  3. package/dist/{chunk-3HEUGBOT.js → chunk-2WZ635SS.js} +2 -2
  4. package/dist/{chunk-GJ7EIABJ.js → chunk-4NWNS7TX.js} +1 -1
  5. package/dist/{chunk-LKVBEE63.js → chunk-FUEXGRFR.js} +2 -2
  6. package/dist/{chunk-6IA2OMAE.js → chunk-HC2KV6BU.js} +9 -0
  7. package/dist/{chunk-IBUYJXA3.js → chunk-KCJ6VATY.js} +1133 -578
  8. package/dist/{chunk-WWJ6S2HQ.js → chunk-KLFIJDTD.js} +1 -1
  9. package/dist/{chunk-COG4ABRI.js → chunk-M2HWJY6O.js} +704 -375
  10. package/dist/{chunk-LVJGPE6H.js → chunk-MTR6AN2C.js} +3 -12
  11. package/dist/chunk-OWHQ65EQ.js +211 -0
  12. package/dist/{chunk-XOTJNW4Q.js → chunk-QIW6OCEI.js} +18 -1
  13. package/dist/{chunk-B4FHWKEF.js → chunk-QULLZ5PE.js} +193 -10
  14. package/dist/{chunk-QZJM3RYI.js → chunk-SNHGSCKH.js} +1 -1
  15. package/dist/{chunk-LVUCBY7X.js → chunk-UDJE54WN.js} +85 -3
  16. package/dist/{chunk-IOTLB6ND.js → chunk-VGNAV3TH.js} +406 -195
  17. package/dist/{chunk-BSZRKBAW.js → chunk-YBZT7MJR.js} +3 -3
  18. package/dist/{chunk-SQ5JGELM.js → chunk-ZDKQNQ4X.js} +19 -1
  19. package/dist/components/index.d.ts +500 -466
  20. package/dist/components/index.js +75 -32
  21. package/dist/components/navigation/index.js +2 -2
  22. package/dist/features/auth/index.d.ts +472 -389
  23. package/dist/features/crm/index.d.ts +468 -391
  24. package/dist/features/crm/index.js +8 -8
  25. package/dist/features/dashboard/index.js +8 -8
  26. package/dist/features/delivery/index.d.ts +466 -383
  27. package/dist/features/delivery/index.js +8 -8
  28. package/dist/features/lead-gen/index.d.ts +213 -65
  29. package/dist/features/lead-gen/index.js +9 -8
  30. package/dist/features/monitoring/index.js +9 -9
  31. package/dist/features/monitoring/requests/index.js +7 -7
  32. package/dist/features/operations/index.js +11 -10
  33. package/dist/features/settings/index.d.ts +472 -389
  34. package/dist/features/settings/index.js +9 -9
  35. package/dist/hooks/delivery/index.d.ts +466 -383
  36. package/dist/hooks/index.d.ts +967 -744
  37. package/dist/hooks/index.js +7 -7
  38. package/dist/hooks/published.d.ts +967 -744
  39. package/dist/hooks/published.js +7 -7
  40. package/dist/index.d.ts +1360 -1069
  41. package/dist/index.js +8 -8
  42. package/dist/initialization/index.d.ts +472 -389
  43. package/dist/organization/index.d.ts +11 -1
  44. package/dist/organization/index.js +2 -2
  45. package/dist/profile/index.d.ts +472 -389
  46. package/dist/provider/index.d.ts +3132 -169
  47. package/dist/provider/index.js +6 -6
  48. package/dist/provider/published.d.ts +3098 -168
  49. package/dist/provider/published.js +3 -3
  50. package/dist/supabase/index.d.ts +577 -413
  51. package/dist/test-utils/index.d.ts +21 -1
  52. package/dist/test-utils/index.js +13 -4
  53. package/dist/theme/index.js +2 -2
  54. package/dist/types/index.d.ts +472 -389
  55. package/package.json +2 -2
  56. package/src/test-utils/README.md +2 -0
  57. /package/dist/{chunk-ZBCTB5CA.js → chunk-EIOJNUPL.js} +0 -0
@@ -4,16 +4,18 @@ import { SubshellNavItem } from './chunk-CEWTOKE7.js';
4
4
  import { SubshellSidebarSection } from './chunk-IIMU5YAJ.js';
5
5
  import { FilterBar } from './chunk-PDHTXPSF.js';
6
6
  import { CustomModal } from './chunk-KVJ3LFH2.js';
7
- import { useDealTasksDue, useDealsLookup, useCreateDealTask, useDealsSummary, useDeleteDeal, usePaginationState, useDeals, useTableSort, sortData, useTableSelection, useDealDetail, useCompany } from './chunk-B4FHWKEF.js';
7
+ import { useExecuteAction, useDealTasksDue, useDealsLookup, useCreateDealTask, useDealsSummary, useDeleteDeal, usePaginationState, useDeals, useTableSort, sortData, useTableSelection, useDealDetail, useCompany } from './chunk-QULLZ5PE.js';
8
+ import { useCrmActions, deriveActions } from './chunk-UDJE54WN.js';
8
9
  import { SubshellContentContainer } from './chunk-TKAYX2SP.js';
9
10
  import { CenteredErrorState, CardHeader, PageTitleCaption, EmptyState, ActivityTimeline } from './chunk-XUYBOO32.js';
10
11
  import { useRouterContext } from './chunk-Q7DJKLEN.js';
11
12
  import { PAGE_SIZE_DEFAULT, formatTimeAgo } from './chunk-SGXXJE52.js';
12
13
  import { useElevasisServices } from './chunk-IRW7JMQ4.js';
13
- import { Box, Stack, Group, Text, Badge, Center, Loader, UnstyledButton, Button, Modal, Title, Select, TextInput, Textarea, Paper, Alert, SimpleGrid, Table, Checkbox, Pagination, ActionIcon, Tabs, Card, Code, Divider, Anchor } from '@mantine/core';
14
- import { IconLayoutGrid, IconColumns, IconFileInvoice, IconAddressBook, IconTrophy, IconClockExclamation, IconUser, IconPlus, IconChecklist, IconAlertCircle, IconHistory, IconSearch, IconTargetArrow, IconAlertTriangle, IconArrowLeft, IconFileText, IconTrash, IconX, IconBuilding, IconCheckbox, IconCalendar, IconMail, IconPhone, IconArrowRight, IconNote } from '@tabler/icons-react';
14
+ import { Button, Modal, Stack, NumberInput, Switch, Select, Textarea, TextInput, Group, Alert, Text, Box, Badge, Center, Loader, UnstyledButton, Title, Paper, Table, SimpleGrid, Checkbox, Pagination, ActionIcon, Tabs, Card, Code, Divider, CopyButton, Tooltip } from '@mantine/core';
15
+ import { IconLayoutGrid, IconColumns, IconFileInvoice, IconAddressBook, IconAlertCircle, IconTrophy, IconClockExclamation, IconUser, IconPlus, IconChecklist, IconHistory, IconSearch, IconTargetArrow, IconAlertTriangle, IconArrowLeft, IconFileText, IconTrash, IconX, IconBuilding, IconCheckbox, IconCalendar, IconMail, IconPhone, IconArrowRight, IconNote, IconCheck, IconCopy } from '@tabler/icons-react';
15
16
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
16
17
  import { useState, useMemo, useEffect } from 'react';
18
+ import { useForm } from '@mantine/form';
17
19
  import { useQuery } from '@tanstack/react-query';
18
20
  import { useNavigate } from '@tanstack/react-router';
19
21
 
@@ -43,6 +45,282 @@ var SAVED_VIEW_PRESETS = [
43
45
  urlFilters: { stage: "closed_won" }
44
46
  }
45
47
  ];
48
+ function ActionButton({ action, dealId }) {
49
+ const executeAction = useExecuteAction({ dealId });
50
+ return /* @__PURE__ */ jsx(
51
+ Button,
52
+ {
53
+ variant: "light",
54
+ size: "sm",
55
+ loading: executeAction.isPending,
56
+ onClick: () => executeAction.mutate({ key: action.key }),
57
+ children: action.label
58
+ }
59
+ );
60
+ }
61
+ function getType(schema) {
62
+ const zodSchema = schema;
63
+ return zodSchema._def?.type ?? zodSchema._def?.typeName ?? "";
64
+ }
65
+ function unwrapField(schema) {
66
+ const type = getType(schema);
67
+ if (type === "optional" || type === "ZodOptional") {
68
+ const inner = schema._def?.innerType;
69
+ if (!inner) return { schema, required: false, nullable: false, defaultValue: void 0 };
70
+ return { ...unwrapField(inner), required: false };
71
+ }
72
+ if (type === "nullable" || type === "ZodNullable") {
73
+ const inner = schema._def?.innerType;
74
+ if (!inner) return { schema, required: true, nullable: true, defaultValue: null };
75
+ return { ...unwrapField(inner), nullable: true };
76
+ }
77
+ if (type === "default" || type === "ZodDefault") {
78
+ const def = schema._def;
79
+ const inner = def?.innerType;
80
+ const defaultValue = typeof def?.defaultValue === "function" ? def.defaultValue() : def?.defaultValue;
81
+ if (!inner) return { schema, required: false, nullable: false, defaultValue };
82
+ return { ...unwrapField(inner), required: false, defaultValue };
83
+ }
84
+ return { schema, required: true, nullable: false, defaultValue: void 0 };
85
+ }
86
+ function getObjectShape(schema) {
87
+ const zodSchema = schema;
88
+ const type = getType(schema);
89
+ if (type !== "object" && type !== "ZodObject") {
90
+ return null;
91
+ }
92
+ const shape = zodSchema.shape;
93
+ if (!shape || typeof shape !== "object" || Array.isArray(shape)) {
94
+ return null;
95
+ }
96
+ return shape;
97
+ }
98
+ function getEnumValues(schema) {
99
+ const zodSchema = schema;
100
+ const values = zodSchema.options ?? zodSchema._def?.values ?? Object.values(zodSchema._def?.entries ?? {});
101
+ if (!Array.isArray(values) || values.some((value) => typeof value !== "string")) {
102
+ return null;
103
+ }
104
+ return values;
105
+ }
106
+ function labelForField(name) {
107
+ return name.replace(/[_-]+/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/^./, (s) => s.toUpperCase());
108
+ }
109
+ function isLongTextField(name) {
110
+ return ["body", "message", "reply", "replyBody", "emailBody"].includes(name);
111
+ }
112
+ function initialValueFor(field, defaultValue) {
113
+ if (defaultValue !== void 0) {
114
+ if (field.kind === "date" && defaultValue instanceof Date) {
115
+ return defaultValue.toISOString().slice(0, 10);
116
+ }
117
+ return defaultValue;
118
+ }
119
+ switch (field.kind) {
120
+ case "boolean":
121
+ return false;
122
+ case "number":
123
+ return field.required ? 0 : "";
124
+ case "enum":
125
+ return field.required ? field.enumValues?.[0] ?? "" : "";
126
+ case "date":
127
+ case "dateString":
128
+ case "string":
129
+ return "";
130
+ }
131
+ }
132
+ function describeSchema(schema) {
133
+ if (!schema) {
134
+ return { supported: false, reason: "This action does not define a payload schema." };
135
+ }
136
+ const shape = getObjectShape(schema);
137
+ if (!shape) {
138
+ return { supported: false, reason: "This action requires a payload schema that is not a flat object." };
139
+ }
140
+ const fields = [];
141
+ const initialValues = {};
142
+ for (const [name, rawFieldSchema] of Object.entries(shape)) {
143
+ const { schema: fieldSchema, required, nullable, defaultValue } = unwrapField(rawFieldSchema);
144
+ const type = getType(fieldSchema);
145
+ const zodField = fieldSchema;
146
+ const stringFormat = zodField._def?.format;
147
+ let descriptor = null;
148
+ if (type === "string" || type === "ZodString") {
149
+ descriptor = {
150
+ name,
151
+ label: labelForField(name),
152
+ kind: stringFormat === "date" ? "dateString" : "string",
153
+ schema: rawFieldSchema,
154
+ required,
155
+ nullable
156
+ };
157
+ } else if (type === "number" || type === "ZodNumber") {
158
+ descriptor = { name, label: labelForField(name), kind: "number", schema: rawFieldSchema, required, nullable };
159
+ } else if (type === "boolean" || type === "ZodBoolean") {
160
+ descriptor = { name, label: labelForField(name), kind: "boolean", schema: rawFieldSchema, required, nullable };
161
+ } else if (type === "enum" || type === "ZodEnum") {
162
+ const enumValues = getEnumValues(fieldSchema);
163
+ if (!enumValues) {
164
+ return { supported: false, reason: `Field "${name}" uses an enum shape that is not supported by this form.` };
165
+ }
166
+ descriptor = {
167
+ name,
168
+ label: labelForField(name),
169
+ kind: "enum",
170
+ schema: rawFieldSchema,
171
+ required,
172
+ nullable,
173
+ enumValues
174
+ };
175
+ } else if (type === "date" || type === "ZodDate") {
176
+ descriptor = { name, label: labelForField(name), kind: "date", schema: rawFieldSchema, required, nullable };
177
+ }
178
+ if (!descriptor) {
179
+ return {
180
+ supported: false,
181
+ reason: `Field "${name}" is not supported. CRM action forms currently support only flat string, number, boolean, enum, and date fields.`
182
+ };
183
+ }
184
+ const field = { ...descriptor, defaultValue: initialValueFor(descriptor, defaultValue) };
185
+ fields.push(field);
186
+ initialValues[name] = field.defaultValue;
187
+ }
188
+ return { supported: true, fields, initialValues };
189
+ }
190
+ function normalizeValue(field, value) {
191
+ const isEmpty = value === "" || value === void 0 || value === null;
192
+ if (isEmpty) {
193
+ if (!field.required) return void 0;
194
+ if (field.nullable) return null;
195
+ return value;
196
+ }
197
+ if (field.kind === "date") {
198
+ const acceptsString = (field.schema._def?.coerce ?? false) === true;
199
+ return acceptsString ? value : new Date(String(value));
200
+ }
201
+ return value;
202
+ }
203
+ function buildPayload(fields, values) {
204
+ return fields.reduce((payload, field) => {
205
+ const value = normalizeValue(field, values[field.name]);
206
+ if (value !== void 0 || field.required) {
207
+ payload[field.name] = value;
208
+ }
209
+ return payload;
210
+ }, {});
211
+ }
212
+ function ActionFormButton({ action, dealId }) {
213
+ const [opened, setOpened] = useState(false);
214
+ const executeAction = useExecuteAction({ dealId });
215
+ const schemaDescription = describeSchema(action.payloadSchema);
216
+ const form = useForm({
217
+ initialValues: schemaDescription.supported ? schemaDescription.initialValues : {}
218
+ });
219
+ const handleClose = () => {
220
+ setOpened(false);
221
+ form.reset();
222
+ form.clearErrors();
223
+ };
224
+ const handleSubmit = form.onSubmit(async (values) => {
225
+ if (!schemaDescription.supported || !action.payloadSchema) return;
226
+ form.clearErrors();
227
+ const payload = buildPayload(schemaDescription.fields, values);
228
+ const parsed = action.payloadSchema.safeParse(payload);
229
+ if (!parsed.success) {
230
+ const formErrors = {};
231
+ for (const issue of parsed.error.issues) {
232
+ const fieldName = issue.path[0];
233
+ if (typeof fieldName === "string" && schemaDescription.fields.some((field) => field.name === fieldName)) {
234
+ formErrors[fieldName] = issue.message;
235
+ }
236
+ }
237
+ form.setErrors(formErrors);
238
+ return;
239
+ }
240
+ await executeAction.mutateAsync({ key: action.key, payload: parsed.data });
241
+ handleClose();
242
+ });
243
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
244
+ /* @__PURE__ */ jsx(Button, { variant: "light", size: "sm", onClick: () => setOpened(true), children: action.label }),
245
+ /* @__PURE__ */ jsx(Modal, { opened, onClose: handleClose, title: action.label, size: "xl", children: schemaDescription.supported ? /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
246
+ schemaDescription.fields.map((field) => {
247
+ if (field.kind === "number") {
248
+ return /* @__PURE__ */ jsx(
249
+ NumberInput,
250
+ {
251
+ label: field.label,
252
+ required: field.required,
253
+ disabled: executeAction.isPending,
254
+ error: form.errors[field.name],
255
+ ...form.getInputProps(field.name)
256
+ },
257
+ field.name
258
+ );
259
+ }
260
+ if (field.kind === "boolean") {
261
+ return /* @__PURE__ */ jsx(
262
+ Switch,
263
+ {
264
+ label: field.label,
265
+ disabled: executeAction.isPending,
266
+ error: form.errors[field.name],
267
+ ...form.getInputProps(field.name, { type: "checkbox" })
268
+ },
269
+ field.name
270
+ );
271
+ }
272
+ if (field.kind === "enum") {
273
+ return /* @__PURE__ */ jsx(
274
+ Select,
275
+ {
276
+ label: field.label,
277
+ required: field.required,
278
+ disabled: executeAction.isPending,
279
+ data: field.enumValues ?? [],
280
+ error: form.errors[field.name],
281
+ ...form.getInputProps(field.name)
282
+ },
283
+ field.name
284
+ );
285
+ }
286
+ if (field.kind === "string" && isLongTextField(field.name)) {
287
+ return /* @__PURE__ */ jsx(
288
+ Textarea,
289
+ {
290
+ label: field.label,
291
+ required: field.required,
292
+ disabled: executeAction.isPending,
293
+ error: form.errors[field.name],
294
+ autosize: true,
295
+ minRows: 6,
296
+ ...form.getInputProps(field.name)
297
+ },
298
+ field.name
299
+ );
300
+ }
301
+ return /* @__PURE__ */ jsx(
302
+ TextInput,
303
+ {
304
+ label: field.label,
305
+ type: field.kind === "date" || field.kind === "dateString" ? "date" : "text",
306
+ required: field.required,
307
+ disabled: executeAction.isPending,
308
+ error: form.errors[field.name],
309
+ ...form.getInputProps(field.name)
310
+ },
311
+ field.name
312
+ );
313
+ }),
314
+ /* @__PURE__ */ jsxs(Group, { justify: "flex-end", gap: "sm", children: [
315
+ /* @__PURE__ */ jsx(Button, { variant: "default", onClick: handleClose, disabled: executeAction.isPending, children: "Cancel" }),
316
+ /* @__PURE__ */ jsx(Button, { type: "submit", loading: executeAction.isPending, children: action.label })
317
+ ] })
318
+ ] }) }) : /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
319
+ /* @__PURE__ */ jsx(Alert, { color: "yellow", variant: "light", icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), title: "Unsupported action form", children: /* @__PURE__ */ jsx(Text, { size: "sm", children: schemaDescription.reason }) }),
320
+ /* @__PURE__ */ jsx(Button, { variant: "default", onClick: handleClose, disabled: executeAction.isPending, children: "Close" })
321
+ ] }) })
322
+ ] });
323
+ }
46
324
  var KIND_ICONS = {
47
325
  call: IconPhone,
48
326
  email: IconMail,
@@ -63,7 +341,7 @@ function formatDueLabel(dueAt) {
63
341
  return `in ${diffDays}d`;
64
342
  }
65
343
  function TaskRow({ task, onClick }) {
66
- const KindIcon2 = KIND_ICONS[task.kind];
344
+ const KindIcon = KIND_ICONS[task.kind];
67
345
  const dueLabel = formatDueLabel(task.dueAt);
68
346
  const isOverdue = task.dueAt !== null && new Date(task.dueAt) < /* @__PURE__ */ new Date();
69
347
  return /* @__PURE__ */ jsx(
@@ -84,7 +362,7 @@ function TaskRow({ task, onClick }) {
84
362
  e.currentTarget.style.backgroundColor = "transparent";
85
363
  },
86
364
  children: /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
87
- /* @__PURE__ */ jsx(KindIcon2, { size: 14, style: { color: "var(--color-text-dimmed)", flexShrink: 0 } }),
365
+ /* @__PURE__ */ jsx(KindIcon, { size: 14, style: { color: "var(--color-text-dimmed)", flexShrink: 0 } }),
88
366
  /* @__PURE__ */ jsx(Text, { size: "xs", truncate: true, style: { flex: 1, minWidth: 0 }, children: task.title }),
89
367
  dueLabel && /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: isOverdue ? "red" : "gray", style: { flexShrink: 0 }, children: dueLabel })
90
368
  ] })
@@ -381,11 +659,35 @@ function useRecentCrmActivity(opts) {
381
659
  error: query.error
382
660
  };
383
661
  }
384
- var currencyFormatter = new Intl.NumberFormat("en-US", {
385
- style: "currency",
386
- currency: "USD",
387
- maximumFractionDigits: 0
388
- });
662
+
663
+ // src/features/crm/pages/shared.ts
664
+ var DEAL_STAGE_COLORS = {
665
+ interested: "blue",
666
+ proposal: "yellow",
667
+ closing: "orange",
668
+ closed_won: "green",
669
+ closed_lost: "red",
670
+ nurturing: "grape"
671
+ };
672
+ var DEAL_STAGE_OPTIONS = [
673
+ { value: "interested", label: "Interested" },
674
+ { value: "proposal", label: "Proposal" },
675
+ { value: "closing", label: "Closing" },
676
+ { value: "closed_won", label: "Closed Won" },
677
+ { value: "closed_lost", label: "Closed Lost" },
678
+ { value: "nurturing", label: "Nurturing" }
679
+ ];
680
+ function formatDealStageLabel(stage) {
681
+ if (!stage) return "Unknown";
682
+ return stage.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
683
+ }
684
+ var BOOKING_PAGE_URL = "https://elevasis.io/inbound/book";
685
+ function buildBookingUrl(opts = {}) {
686
+ const params = new URLSearchParams();
687
+ if (opts.dealId) params.set("dealId", opts.dealId);
688
+ if (opts.contactId) params.set("contactId", opts.contactId);
689
+ return params.size > 0 ? `${BOOKING_PAGE_URL}?${params.toString()}` : BOOKING_PAGE_URL;
690
+ }
389
691
  var STAGE_LABELS = {
390
692
  interested: "Interested",
391
693
  proposal: "Proposal",
@@ -403,143 +705,54 @@ function PipelineFunnelWidget({ onStageClick, getDealValue }) {
403
705
  return /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load pipeline data" }) });
404
706
  }
405
707
  const totalDeals = data.reduce((sum, s) => sum + s.count, 0);
406
- const maxCount = Math.max(...data.map((s) => s.count), 1);
407
- if (totalDeals === 0) {
408
- return /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
409
- /* @__PURE__ */ jsx(CardHeader, { icon: /* @__PURE__ */ jsx(IconColumns, { size: 16 }), title: "Pipeline" }),
410
- /* @__PURE__ */ jsx(Center, { h: 200, children: /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, {}), color: "gray", variant: "light", children: "No deals in the pipeline yet" }) })
411
- ] });
412
- }
413
708
  return /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
414
709
  /* @__PURE__ */ jsx(
415
710
  CardHeader,
416
711
  {
417
712
  icon: /* @__PURE__ */ jsx(IconColumns, { size: 16 }),
418
713
  title: "Pipeline",
419
- subtitle: `${totalDeals} deal${totalDeals !== 1 ? "s" : ""} total`
714
+ subtitle: totalDeals === 0 ? "No deals in the pipeline yet" : `${totalDeals} deal${totalDeals !== 1 ? "s" : ""} total`
420
715
  }
421
716
  ),
422
- /* @__PURE__ */ jsx(Box, { children: PIPELINE_FUNNEL_ORDER.map((stage) => {
717
+ /* @__PURE__ */ jsx(Group, { gap: "lg", wrap: "nowrap", mt: "md", children: PIPELINE_FUNNEL_ORDER.map((stage) => {
423
718
  const summary = data.find((s) => s.stage === stage);
424
719
  const isEmpty = summary.count === 0;
425
- const barWidth = isEmpty ? 2 : Math.max(4, summary.count / maxCount * 100);
426
- return /* @__PURE__ */ jsx(
720
+ const stageColor = DEAL_STAGE_COLORS[stage] ?? "gray";
721
+ const accent = `var(--mantine-color-${stageColor}-6)`;
722
+ return /* @__PURE__ */ jsxs(
427
723
  Box,
428
724
  {
429
725
  onClick: () => onStageClick(stage),
430
726
  style: {
727
+ flex: 1,
728
+ minWidth: 0,
431
729
  cursor: "pointer",
432
- borderRadius: "var(--mantine-radius-sm)",
433
- padding: "6px 8px",
434
- transition: `background-color var(--duration-fast) var(--easing)`,
435
- marginBottom: 4
730
+ padding: "4px 0"
436
731
  },
437
- onMouseEnter: (e) => {
438
- e.currentTarget.style.backgroundColor = "var(--color-surface-hover)";
439
- },
440
- onMouseLeave: (e) => {
441
- e.currentTarget.style.backgroundColor = "transparent";
442
- },
443
- children: /* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "nowrap", children: [
444
- /* @__PURE__ */ jsx(Text, { size: "sm", c: isEmpty ? "dimmed" : void 0, style: { width: 130, flexShrink: 0 }, children: STAGE_LABELS[stage] }),
445
- /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: isEmpty ? "gray" : void 0, style: { flexShrink: 0 }, children: summary.count }),
446
- /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "outline", color: isEmpty ? "gray" : "teal", style: { flexShrink: 0 }, children: currencyFormatter.format(summary.totalValue) }),
447
- /* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx(
448
- Box,
449
- {
450
- style: {
451
- height: 8,
452
- width: `${barWidth}%`,
453
- borderRadius: 4,
454
- backgroundColor: isEmpty ? "var(--color-border)" : "color-mix(in srgb, var(--color-primary) 70%, transparent)",
455
- opacity: isEmpty ? 0.4 : 1,
456
- transition: `width var(--duration-normal) var(--easing)`
732
+ children: [
733
+ /* @__PURE__ */ jsxs(Group, { gap: 8, wrap: "nowrap", align: "center", mb: 6, children: [
734
+ /* @__PURE__ */ jsx(
735
+ Box,
736
+ {
737
+ style: {
738
+ width: 8,
739
+ height: 8,
740
+ borderRadius: "50%",
741
+ background: accent,
742
+ flexShrink: 0
743
+ }
457
744
  }
458
- }
459
- ) })
460
- ] })
745
+ ),
746
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", truncate: true, children: STAGE_LABELS[stage] })
747
+ ] }),
748
+ /* @__PURE__ */ jsx(Text, { size: "xl", fw: 600, c: isEmpty ? "dimmed" : void 0, lh: 1, children: summary.count })
749
+ ]
461
750
  },
462
751
  stage
463
752
  );
464
753
  }) })
465
754
  ] });
466
755
  }
467
- var MAX_VISIBLE = 5;
468
- function KindIcon({ kind }) {
469
- const size = 16;
470
- switch (kind) {
471
- case "call":
472
- return /* @__PURE__ */ jsx(IconPhone, { size });
473
- case "email":
474
- return /* @__PURE__ */ jsx(IconMail, { size });
475
- case "meeting":
476
- return /* @__PURE__ */ jsx(IconCalendar, { size });
477
- default:
478
- return /* @__PURE__ */ jsx(IconCheckbox, { size });
479
- }
480
- }
481
- function formatDueDate(dueAt) {
482
- if (!dueAt) return "No due date";
483
- return new Date(dueAt).toLocaleDateString();
484
- }
485
- function TasksDueWidget({ onTaskClick, onSeeAll }) {
486
- const { data: tasks, isLoading, error } = useDealTasksDue({ window: "today_and_overdue" });
487
- if (isLoading) {
488
- return /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) });
489
- }
490
- if (error) {
491
- return /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load tasks" }) });
492
- }
493
- const totalCount = tasks?.length ?? 0;
494
- const visibleTasks = (tasks ?? []).slice(0, MAX_VISIBLE);
495
- const hasMore = totalCount > MAX_VISIBLE;
496
- const seeAllLink = onSeeAll && hasMore ? /* @__PURE__ */ jsxs(Anchor, { size: "sm", onClick: onSeeAll, style: { cursor: "pointer" }, children: [
497
- "See all (",
498
- totalCount,
499
- ")"
500
- ] }) : void 0;
501
- if (totalCount === 0) {
502
- return /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
503
- /* @__PURE__ */ jsx(CardHeader, { icon: /* @__PURE__ */ jsx(IconChecklist, { size: 16 }), title: "Tasks Due" }),
504
- /* @__PURE__ */ jsx(Center, { h: 120, children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No tasks due today" }) })
505
- ] });
506
- }
507
- return /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
508
- /* @__PURE__ */ jsx(
509
- CardHeader,
510
- {
511
- icon: /* @__PURE__ */ jsx(IconChecklist, { size: 16 }),
512
- title: "Tasks Due",
513
- subtitle: `${totalCount} task${totalCount !== 1 ? "s" : ""}`,
514
- rightSection: seeAllLink
515
- }
516
- ),
517
- /* @__PURE__ */ jsx(Stack, { gap: "xs", children: visibleTasks.map((task) => /* @__PURE__ */ jsx(
518
- Box,
519
- {
520
- onClick: () => onTaskClick(task.dealId),
521
- style: {
522
- cursor: "pointer",
523
- borderRadius: "var(--mantine-radius-sm)",
524
- padding: "6px 8px",
525
- transition: `background-color var(--duration-fast) var(--easing)`
526
- },
527
- onMouseEnter: (e) => {
528
- e.currentTarget.style.backgroundColor = "var(--color-surface-hover)";
529
- },
530
- onMouseLeave: (e) => {
531
- e.currentTarget.style.backgroundColor = "transparent";
532
- },
533
- children: /* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "nowrap", children: [
534
- /* @__PURE__ */ jsx(Text, { c: "dimmed", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx(KindIcon, { kind: task.kind }) }),
535
- /* @__PURE__ */ jsx(Text, { size: "sm", style: { flex: 1, minWidth: 0 }, truncate: true, children: task.title }),
536
- /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: "gray", style: { flexShrink: 0 }, children: formatDueDate(task.dueAt) })
537
- ] })
538
- },
539
- task.id
540
- )) })
541
- ] });
542
- }
543
756
  function ActivityKindIcon({ kind }) {
544
757
  const size = 16;
545
758
  switch (kind) {
@@ -578,41 +791,28 @@ function ActivityFeedWidget({ onDealClick, limit }) {
578
791
  /* @__PURE__ */ jsx(Center, { h: 120, children: /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, {}), color: "gray", variant: "light", children: "No recent activity" }) })
579
792
  ] });
580
793
  }
581
- return /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
794
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
582
795
  /* @__PURE__ */ jsx(CardHeader, { icon: /* @__PURE__ */ jsx(IconHistory, { size: 16 }), title: "Recent Activity" }),
583
- /* @__PURE__ */ jsx(Stack, { gap: 4, children: data.map((entry) => {
584
- const name = entry.contactName ?? entry.companyName ?? "Unknown";
585
- return /* @__PURE__ */ jsx(
586
- Box,
587
- {
588
- onClick: () => onDealClick(entry.dealId),
589
- style: {
590
- cursor: "pointer",
591
- borderRadius: "var(--mantine-radius-sm)",
592
- padding: "6px 8px",
593
- transition: `background-color var(--duration-fast) var(--easing)`
594
- },
595
- onMouseEnter: (e) => {
596
- e.currentTarget.style.backgroundColor = "var(--color-surface-hover)";
597
- },
598
- onMouseLeave: (e) => {
599
- e.currentTarget.style.backgroundColor = "transparent";
600
- },
601
- children: /* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "nowrap", align: "flex-start", children: [
602
- /* @__PURE__ */ jsx(Text, { c: "dimmed", style: { flexShrink: 0, paddingTop: 2 }, children: /* @__PURE__ */ jsx(ActivityKindIcon, { kind: entry.kind }) }),
603
- /* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
604
- /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, truncate: true, style: { flexShrink: 0, maxWidth: 140 }, children: name }),
605
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", truncate: true, style: { flex: 1, minWidth: 0 }, children: entry.description })
606
- ] }) }),
607
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", style: { flexShrink: 0, whiteSpace: "nowrap" }, children: formatRelativeTime(entry.occurredAt) })
608
- ] })
609
- },
610
- entry.id
611
- );
612
- }) })
613
- ] });
796
+ /* @__PURE__ */ jsxs(Table, { highlightOnHover: true, children: [
797
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
798
+ /* @__PURE__ */ jsx(Table.Th, { w: 40 }),
799
+ /* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
800
+ /* @__PURE__ */ jsx(Table.Th, { children: "Activity" }),
801
+ /* @__PURE__ */ jsx(Table.Th, { w: 120, children: "When" })
802
+ ] }) }),
803
+ /* @__PURE__ */ jsx(Table.Tbody, { children: data.map((entry) => {
804
+ const name = entry.contactName ?? entry.companyName ?? "Unknown";
805
+ return /* @__PURE__ */ jsxs(Table.Tr, { style: { cursor: "pointer" }, onClick: () => onDealClick(entry.dealId), children: [
806
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { c: "dimmed", component: "span", children: /* @__PURE__ */ jsx(ActivityKindIcon, { kind: entry.kind }) }) }),
807
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, truncate: true, children: name }) }),
808
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", truncate: true, children: entry.description }) }),
809
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", style: { whiteSpace: "nowrap" }, children: formatRelativeTime(entry.occurredAt) }) })
810
+ ] }, entry.id);
811
+ }) })
812
+ ] })
813
+ ] }) });
614
814
  }
615
- var currencyFormatter2 = new Intl.NumberFormat("en-US", {
815
+ var currencyFormatter = new Intl.NumberFormat("en-US", {
616
816
  style: "currency",
617
817
  currency: "USD",
618
818
  maximumFractionDigits: 0
@@ -629,7 +829,7 @@ function StatTile({ label, value }) {
629
829
  function MetricsStrip() {
630
830
  const { data } = useCrmQuickMetrics();
631
831
  return /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 2, sm: 4 }, children: [
632
- /* @__PURE__ */ jsx(StatTile, { label: "Total Pipeline Value", value: currencyFormatter2.format(data.totalPipelineValue) }),
832
+ /* @__PURE__ */ jsx(StatTile, { label: "Total Pipeline Value", value: currencyFormatter.format(data.totalPipelineValue) }),
633
833
  /* @__PURE__ */ jsx(StatTile, { label: "Win Rate", value: formatPercent(data.winRate) }),
634
834
  /* @__PURE__ */ jsx(StatTile, { label: "Open Deals", value: String(data.openDeals) }),
635
835
  /* @__PURE__ */ jsx(StatTile, { label: "Won This Period", value: String(data.wonDeals) })
@@ -653,13 +853,8 @@ function CrmOverview({
653
853
  }
654
854
  ),
655
855
  /* @__PURE__ */ jsx(MetricsStrip, {}),
656
- /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, lg: 2 }, spacing: "md", children: [
657
- /* @__PURE__ */ jsx(PipelineFunnelWidget, { onStageClick, getDealValue }),
658
- /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
659
- /* @__PURE__ */ jsx(TasksDueWidget, { onTaskClick: onDealClick }),
660
- /* @__PURE__ */ jsx(ActivityFeedWidget, { onDealClick })
661
- ] })
662
- ] })
856
+ /* @__PURE__ */ jsx(PipelineFunnelWidget, { onStageClick, getDealValue }),
857
+ /* @__PURE__ */ jsx(ActivityFeedWidget, { onDealClick })
663
858
  ] });
664
859
  }
665
860
  var crmManifest = {
@@ -669,33 +864,11 @@ var crmManifest = {
669
864
  icon: IconAddressBook,
670
865
  sidebar: CrmSidebar
671
866
  };
672
-
673
- // src/features/crm/pages/shared.ts
674
- var DEAL_STAGE_COLORS = {
675
- interested: "blue",
676
- proposal: "yellow",
677
- closing: "orange",
678
- closed_won: "green",
679
- closed_lost: "red",
680
- nurturing: "grape"
681
- };
682
- var DEAL_STAGE_OPTIONS = [
683
- { value: "interested", label: "Interested" },
684
- { value: "proposal", label: "Proposal" },
685
- { value: "closing", label: "Closing" },
686
- { value: "closed_won", label: "Closed Won" },
687
- { value: "closed_lost", label: "Closed Lost" },
688
- { value: "nurturing", label: "Nurturing" }
689
- ];
690
- function formatDealStageLabel(stage) {
691
- if (!stage) return "Unknown";
692
- return stage.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
693
- }
694
867
  var sortAccessors = {
695
868
  company: (deal) => deal.contact?.company?.name || deal.discovery_data?.company || deal.contact_email?.split("@")[1] || "",
696
869
  contact: (deal) => [deal.contact?.first_name, deal.contact?.last_name].filter(Boolean).join(" ") || "",
697
870
  email: (deal) => deal.contact_email || "",
698
- stage: (deal) => deal.cached_stage || "",
871
+ stage: (deal) => deal.stage_key || "",
699
872
  updated: (deal) => deal.updated_at || ""
700
873
  };
701
874
  function DealsListPage() {
@@ -705,7 +878,12 @@ function DealsListPage() {
705
878
  const [searchQuery, setSearchQuery] = useState("");
706
879
  const [showBatchDelete, setShowBatchDelete] = useState(false);
707
880
  const pagination = usePaginationState(PAGE_SIZE_DEFAULT, [stageFilter, searchQuery]);
708
- const { data: deals, total, isLoading, error } = useDeals({
881
+ const {
882
+ data: deals,
883
+ total,
884
+ isLoading,
885
+ error
886
+ } = useDeals({
709
887
  stage: stageFilter || void 0,
710
888
  search: searchQuery || void 0,
711
889
  limit: PAGE_SIZE_DEFAULT,
@@ -800,7 +978,7 @@ function DealsListPage() {
800
978
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: companyName }) }),
801
979
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", children: contactName || "-" }) }),
802
980
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: deal.contact_email || "-" }) }),
803
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { variant: "light", color: DEAL_STAGE_COLORS[deal.cached_stage || ""] || "gray", size: "sm", children: formatDealStageLabel(deal.cached_stage) }) }),
981
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { variant: "light", color: DEAL_STAGE_COLORS[deal.stage_key || ""] || "gray", size: "sm", children: formatDealStageLabel(deal.stage_key) }) }),
804
982
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: formatTimeAgo(deal.updated_at) }) })
805
983
  ]
806
984
  },
@@ -852,11 +1030,31 @@ function DealsListPage() {
852
1030
  )
853
1031
  ] });
854
1032
  }
1033
+ function BookingLinkPanel({ dealId, contactId }) {
1034
+ const url = buildBookingUrl({ dealId, contactId });
1035
+ return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
1036
+ /* @__PURE__ */ jsx(Title, { order: 4, children: "Booking Link" }),
1037
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
1038
+ /* @__PURE__ */ jsx(
1039
+ Text,
1040
+ {
1041
+ size: "sm",
1042
+ c: "var(--color-primary)",
1043
+ style: { flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
1044
+ children: url
1045
+ }
1046
+ ),
1047
+ /* @__PURE__ */ jsx(CopyButton, { value: url, children: ({ copied, copy }) => /* @__PURE__ */ jsx(Tooltip, { label: copied ? "Copied" : "Copy", withArrow: true, children: /* @__PURE__ */ jsx(ActionIcon, { variant: "light", color: copied ? "teal" : void 0, onClick: copy, children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: 16 }) : /* @__PURE__ */ jsx(IconCopy, { size: 16 }) }) }) })
1048
+ ] })
1049
+ ] }) });
1050
+ }
855
1051
  function DealDetailPage({ dealId, renderActions, onDealLoaded }) {
856
1052
  const navigate = useNavigate();
857
1053
  const deleteDeal = useDeleteDeal();
858
1054
  const { data: deal, isLoading, error } = useDealDetail(dealId);
859
1055
  const [deleteModalOpen, setDeleteModalOpen] = useState(false);
1056
+ const crmActions = useCrmActions();
1057
+ const actions = useMemo(() => deal ? deriveActions(deal, crmActions) : [], [deal, crmActions]);
860
1058
  useEffect(() => {
861
1059
  if (deal) onDealLoaded?.(deal);
862
1060
  }, [deal, onDealLoaded]);
@@ -889,9 +1087,21 @@ function DealDetailPage({ dealId, renderActions, onDealLoaded }) {
889
1087
  children: "View Proposal"
890
1088
  }
891
1089
  ),
1090
+ actions.map(
1091
+ (action) => action.payloadSchema ? /* @__PURE__ */ jsx(ActionFormButton, { action, dealId: deal.id }, action.key) : /* @__PURE__ */ jsx(ActionButton, { action, dealId: deal.id }, action.key)
1092
+ ),
892
1093
  renderActions?.(deal),
893
1094
  /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", color: "red", onClick: () => setDeleteModalOpen(true), children: /* @__PURE__ */ jsx(IconTrash, { size: 16 }) })
894
- ] }) : /* @__PURE__ */ jsx(Button, { variant: "light", size: "sm", leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }), onClick: () => navigate({ to: "/crm/deals" }), children: "Deals" });
1095
+ ] }) : /* @__PURE__ */ jsx(
1096
+ Button,
1097
+ {
1098
+ variant: "light",
1099
+ size: "sm",
1100
+ leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
1101
+ onClick: () => navigate({ to: "/crm/deals" }),
1102
+ children: "Deals"
1103
+ }
1104
+ );
895
1105
  if (isLoading) {
896
1106
  return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsxs(PageContainer, { children: [
897
1107
  /* @__PURE__ */ jsx(Stack, { children: /* @__PURE__ */ jsx(PageTitleCaption, { title, caption: "Loading deal details...", rightSection: headerActions }) }),
@@ -916,7 +1126,7 @@ function DealDetailPage({ dealId, renderActions, onDealLoaded }) {
916
1126
  PageTitleCaption,
917
1127
  {
918
1128
  title,
919
- caption: `${companyName || "Unknown"} - ${formatDealStageLabel(deal.cached_stage)}`,
1129
+ caption: `${companyName || "Unknown"} - ${formatDealStageLabel(deal.stage_key)}`,
920
1130
  rightSection: headerActions
921
1131
  }
922
1132
  ) }),
@@ -931,7 +1141,7 @@ function DealDetailPage({ dealId, renderActions, onDealLoaded }) {
931
1141
  /* @__PURE__ */ jsx(Title, { order: 4, children: "Deal" }),
932
1142
  /* @__PURE__ */ jsxs(Group, { children: [
933
1143
  /* @__PURE__ */ jsx(Text, { fw: 500, children: "Stage:" }),
934
- /* @__PURE__ */ jsx(Badge, { color: DEAL_STAGE_COLORS[deal.cached_stage || ""] || "gray", children: formatDealStageLabel(deal.cached_stage) })
1144
+ /* @__PURE__ */ jsx(Badge, { color: DEAL_STAGE_COLORS[deal.stage_key || ""] || "gray", children: formatDealStageLabel(deal.stage_key) })
935
1145
  ] }),
936
1146
  /* @__PURE__ */ jsxs(Group, { children: [
937
1147
  /* @__PURE__ */ jsx(Text, { fw: 500, children: "Sent:" }),
@@ -974,6 +1184,7 @@ function DealDetailPage({ dealId, renderActions, onDealLoaded }) {
974
1184
  ] })
975
1185
  ] })
976
1186
  ] }) }),
1187
+ deal.contact_id && /* @__PURE__ */ jsx(BookingLinkPanel, { dealId: deal.id, contactId: deal.contact_id }),
977
1188
  /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
978
1189
  /* @__PURE__ */ jsx(Title, { order: 4, children: "Company" }),
979
1190
  /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 2 }, spacing: "sm", children: [
@@ -1003,7 +1214,7 @@ function DealDetailPage({ dealId, renderActions, onDealLoaded }) {
1003
1214
  ] })
1004
1215
  ] })
1005
1216
  ] }) }),
1006
- ["proposal_signed", "payment_sent", "closed_won"].includes(deal.cached_stage || "") && /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
1217
+ ["closing", "closed_won"].includes(deal.stage_key || "") && /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
1007
1218
  /* @__PURE__ */ jsx(Title, { order: 4, children: "Payment" }),
1008
1219
  /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 2 }, spacing: "sm", children: [
1009
1220
  /* @__PURE__ */ jsxs(Group, { children: [
@@ -1188,4 +1399,4 @@ function CompanyDetailPage({ companyId }) {
1188
1399
  ] }) });
1189
1400
  }
1190
1401
 
1191
- export { ActivityFeedWidget, CRM_ITEMS, CompanyDetailPage, CrmOverview, CrmSidebar, CrmSidebarMiddle, CrmSidebarTop, DEAL_STAGE_COLORS, DEAL_STAGE_OPTIONS, DealDetailPage, DealsListPage, MetricsStrip, MyTasksPanel, PIPELINE_FUNNEL_ORDER, PipelineFunnelWidget, QuickCreateActions, SAVED_VIEW_PRESETS, SavedViewsPanel, TasksDueWidget, crmManifest, formatDealStageLabel, useCrmPipelineSummary, useCrmQuickMetrics, useRecentCrmActivity };
1402
+ export { ActionButton, ActionFormButton, ActivityFeedWidget, CRM_ITEMS, CompanyDetailPage, CrmOverview, CrmSidebar, CrmSidebarMiddle, CrmSidebarTop, DEAL_STAGE_COLORS, DEAL_STAGE_OPTIONS, DealDetailPage, DealsListPage, MetricsStrip, MyTasksPanel, PIPELINE_FUNNEL_ORDER, PipelineFunnelWidget, QuickCreateActions, SAVED_VIEW_PRESETS, SavedViewsPanel, crmManifest, formatDealStageLabel, useCrmPipelineSummary, useCrmQuickMetrics, useRecentCrmActivity };