@contractspec/example.crm-pipeline 3.7.6 → 3.7.10
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 +45 -42
- package/AGENTS.md +51 -33
- package/CHANGELOG.md +36 -0
- package/README.md +67 -148
- package/dist/browser/docs/crm-pipeline.docblock.js +1 -1
- package/dist/browser/docs/index.js +1 -1
- 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/handlers/crm.handlers.js +13 -2
- package/dist/browser/handlers/index.js +13 -2
- package/dist/browser/index.js +680 -447
- package/dist/browser/ui/CrmDashboard.js +574 -352
- package/dist/browser/ui/CrmDealCard.js +5 -5
- package/dist/browser/ui/CrmPipelineBoard.js +13 -13
- package/dist/browser/ui/hooks/index.js +21 -10
- package/dist/browser/ui/hooks/useDealList.js +20 -9
- package/dist/browser/ui/hooks/useDealMutations.js +1 -1
- package/dist/browser/ui/index.js +683 -450
- 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 +140 -118
- package/dist/browser/ui/renderers/pipeline.markdown.js +13 -2
- package/dist/browser/ui/renderers/pipeline.renderer.js +108 -97
- package/dist/browser/ui/tables/DealListTab.js +390 -0
- package/dist/deal/index.d.ts +2 -2
- package/dist/docs/crm-pipeline.docblock.js +1 -1
- package/dist/docs/index.js +1 -1
- 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/crm.handlers.d.ts +2 -0
- package/dist/handlers/crm.handlers.js +13 -2
- package/dist/handlers/index.d.ts +2 -2
- package/dist/handlers/index.js +13 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +680 -447
- package/dist/node/docs/crm-pipeline.docblock.js +1 -1
- package/dist/node/docs/index.js +1 -1
- 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/handlers/crm.handlers.js +13 -2
- package/dist/node/handlers/index.js +13 -2
- package/dist/node/index.js +680 -447
- package/dist/node/ui/CrmDashboard.js +574 -352
- package/dist/node/ui/CrmDealCard.js +5 -5
- package/dist/node/ui/CrmPipelineBoard.js +13 -13
- package/dist/node/ui/hooks/index.js +21 -10
- package/dist/node/ui/hooks/useDealList.js +20 -9
- package/dist/node/ui/hooks/useDealMutations.js +1 -1
- package/dist/node/ui/index.js +683 -450
- 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 +140 -118
- package/dist/node/ui/renderers/pipeline.markdown.js +13 -2
- package/dist/node/ui/renderers/pipeline.renderer.js +108 -97
- package/dist/node/ui/tables/DealListTab.js +390 -0
- package/dist/operations/index.d.ts +1 -1
- package/dist/ui/CrmDashboard.js +574 -352
- 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 +21 -10
- package/dist/ui/hooks/useDealList.d.ts +8 -2
- package/dist/ui/hooks/useDealList.js +20 -9
- 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 +683 -450
- 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 +140 -118
- package/dist/ui/renderers/pipeline.markdown.js +13 -2
- package/dist/ui/renderers/pipeline.renderer.d.ts +1 -1
- package/dist/ui/renderers/pipeline.renderer.js +108 -97
- package/dist/ui/tables/DealListTab.d.ts +20 -0
- package/dist/ui/tables/DealListTab.js +391 -0
- package/dist/ui/tables/DealListTab.smoke.test.d.ts +1 -0
- package/package.json +29 -14
- 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 +44 -44
- 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 +375 -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 +210 -279
- 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 +113 -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/src/ui/tables/DealListTab.smoke.test.tsx +149 -0
- package/src/ui/tables/DealListTab.tsx +276 -0
- package/tsconfig.json +7 -8
- package/tsdown.config.js +7 -3
package/dist/ui/CrmDealCard.js
CHANGED
|
@@ -14,7 +14,7 @@ function CrmDealCard({ deal, onClick }) {
|
|
|
14
14
|
const daysUntilClose = deal.expectedCloseDate ? Math.ceil((deal.expectedCloseDate.getTime() - Date.now()) / (1000 * 60 * 60 * 24)) : null;
|
|
15
15
|
return /* @__PURE__ */ jsxDEV("div", {
|
|
16
16
|
onClick,
|
|
17
|
-
className: "
|
|
17
|
+
className: "cursor-pointer rounded-lg border border-border bg-card p-3 shadow-sm transition-shadow hover:shadow-md",
|
|
18
18
|
role: "button",
|
|
19
19
|
tabIndex: 0,
|
|
20
20
|
onKeyDown: (e) => {
|
|
@@ -23,22 +23,22 @@ function CrmDealCard({ deal, onClick }) {
|
|
|
23
23
|
},
|
|
24
24
|
children: [
|
|
25
25
|
/* @__PURE__ */ jsxDEV("h4", {
|
|
26
|
-
className: "leading-snug
|
|
26
|
+
className: "font-medium leading-snug",
|
|
27
27
|
children: deal.name
|
|
28
28
|
}, undefined, false, undefined, this),
|
|
29
29
|
/* @__PURE__ */ jsxDEV("div", {
|
|
30
|
-
className: "
|
|
30
|
+
className: "mt-2 font-semibold text-lg text-primary",
|
|
31
31
|
children: formatCurrency(deal.value, deal.currency)
|
|
32
32
|
}, undefined, false, undefined, this),
|
|
33
33
|
/* @__PURE__ */ jsxDEV("div", {
|
|
34
|
-
className: "
|
|
34
|
+
className: "mt-3 flex items-center justify-between text-muted-foreground text-xs",
|
|
35
35
|
children: [
|
|
36
36
|
daysUntilClose !== null && /* @__PURE__ */ jsxDEV("span", {
|
|
37
37
|
className: daysUntilClose < 0 ? "text-red-500" : daysUntilClose <= 7 ? "text-yellow-600 dark:text-yellow-500" : "",
|
|
38
38
|
children: daysUntilClose < 0 ? `${Math.abs(daysUntilClose)}d overdue` : daysUntilClose === 0 ? "Due today" : `${daysUntilClose}d left`
|
|
39
39
|
}, undefined, false, undefined, this),
|
|
40
40
|
/* @__PURE__ */ jsxDEV("span", {
|
|
41
|
-
className: `rounded px-1.5 py-0.5 text-xs
|
|
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
42
|
children: deal.status
|
|
43
43
|
}, undefined, false, undefined, this)
|
|
44
44
|
]
|
|
@@ -14,7 +14,7 @@ function CrmDealCard({ deal, onClick }) {
|
|
|
14
14
|
const daysUntilClose = deal.expectedCloseDate ? Math.ceil((deal.expectedCloseDate.getTime() - Date.now()) / (1000 * 60 * 60 * 24)) : null;
|
|
15
15
|
return /* @__PURE__ */ jsxDEV("div", {
|
|
16
16
|
onClick,
|
|
17
|
-
className: "
|
|
17
|
+
className: "cursor-pointer rounded-lg border border-border bg-card p-3 shadow-sm transition-shadow hover:shadow-md",
|
|
18
18
|
role: "button",
|
|
19
19
|
tabIndex: 0,
|
|
20
20
|
onKeyDown: (e) => {
|
|
@@ -23,22 +23,22 @@ function CrmDealCard({ deal, onClick }) {
|
|
|
23
23
|
},
|
|
24
24
|
children: [
|
|
25
25
|
/* @__PURE__ */ jsxDEV("h4", {
|
|
26
|
-
className: "leading-snug
|
|
26
|
+
className: "font-medium leading-snug",
|
|
27
27
|
children: deal.name
|
|
28
28
|
}, undefined, false, undefined, this),
|
|
29
29
|
/* @__PURE__ */ jsxDEV("div", {
|
|
30
|
-
className: "
|
|
30
|
+
className: "mt-2 font-semibold text-lg text-primary",
|
|
31
31
|
children: formatCurrency(deal.value, deal.currency)
|
|
32
32
|
}, undefined, false, undefined, this),
|
|
33
33
|
/* @__PURE__ */ jsxDEV("div", {
|
|
34
|
-
className: "
|
|
34
|
+
className: "mt-3 flex items-center justify-between text-muted-foreground text-xs",
|
|
35
35
|
children: [
|
|
36
36
|
daysUntilClose !== null && /* @__PURE__ */ jsxDEV("span", {
|
|
37
37
|
className: daysUntilClose < 0 ? "text-red-500" : daysUntilClose <= 7 ? "text-yellow-600 dark:text-yellow-500" : "",
|
|
38
38
|
children: daysUntilClose < 0 ? `${Math.abs(daysUntilClose)}d overdue` : daysUntilClose === 0 ? "Due today" : `${daysUntilClose}d left`
|
|
39
39
|
}, undefined, false, undefined, this),
|
|
40
40
|
/* @__PURE__ */ jsxDEV("span", {
|
|
41
|
-
className: `rounded px-1.5 py-0.5 text-xs
|
|
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
42
|
children: deal.status
|
|
43
43
|
}, undefined, false, undefined, this)
|
|
44
44
|
]
|
|
@@ -76,10 +76,10 @@ function CrmPipelineBoard({
|
|
|
76
76
|
const deals = dealsByStage[stage.id] ?? [];
|
|
77
77
|
const stageValue = deals.reduce((sum, d) => sum + d.value, 0);
|
|
78
78
|
return /* @__PURE__ */ jsxDEV2("div", {
|
|
79
|
-
className: "
|
|
79
|
+
className: "flex w-72 flex-shrink-0 flex-col rounded-lg bg-muted/30",
|
|
80
80
|
children: [
|
|
81
81
|
/* @__PURE__ */ jsxDEV2("div", {
|
|
82
|
-
className: "
|
|
82
|
+
className: "flex items-center justify-between border-border border-b px-3 py-2",
|
|
83
83
|
children: [
|
|
84
84
|
/* @__PURE__ */ jsxDEV2("div", {
|
|
85
85
|
children: [
|
|
@@ -98,7 +98,7 @@ function CrmPipelineBoard({
|
|
|
98
98
|
]
|
|
99
99
|
}, undefined, true, undefined, this),
|
|
100
100
|
/* @__PURE__ */ jsxDEV2("span", {
|
|
101
|
-
className: "
|
|
101
|
+
className: "flex h-6 w-6 items-center justify-center rounded-full bg-muted font-medium text-xs",
|
|
102
102
|
children: deals.length
|
|
103
103
|
}, undefined, false, undefined, this)
|
|
104
104
|
]
|
|
@@ -106,7 +106,7 @@ function CrmPipelineBoard({
|
|
|
106
106
|
/* @__PURE__ */ jsxDEV2("div", {
|
|
107
107
|
className: "flex flex-1 flex-col gap-2 p-2",
|
|
108
108
|
children: deals.length === 0 ? /* @__PURE__ */ jsxDEV2("div", {
|
|
109
|
-
className: "
|
|
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
110
|
children: "No deals"
|
|
111
111
|
}, undefined, false, undefined, this) : deals.map((deal) => /* @__PURE__ */ jsxDEV2("div", {
|
|
112
112
|
className: "group relative",
|
|
@@ -124,15 +124,15 @@ function CrmPipelineBoard({
|
|
|
124
124
|
e.stopPropagation();
|
|
125
125
|
setQuickMoveOpen(quickMoveOpen === deal.id ? null : deal.id);
|
|
126
126
|
},
|
|
127
|
-
className: "
|
|
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
128
|
title: "Quick move",
|
|
129
129
|
children: "\u27A1\uFE0F"
|
|
130
130
|
}, undefined, false, undefined, this),
|
|
131
131
|
quickMoveOpen === deal.id && /* @__PURE__ */ jsxDEV2("div", {
|
|
132
|
-
className: "
|
|
132
|
+
className: "absolute top-7 right-0 z-20 min-w-[140px] rounded-lg border border-border bg-card py-1 shadow-lg",
|
|
133
133
|
children: [
|
|
134
134
|
/* @__PURE__ */ jsxDEV2("p", {
|
|
135
|
-
className: "
|
|
135
|
+
className: "px-3 py-1 font-medium text-muted-foreground text-xs",
|
|
136
136
|
children: "Move to:"
|
|
137
137
|
}, undefined, false, undefined, this),
|
|
138
138
|
sortedStages.filter((s) => s.id !== deal.stageId).map((s) => /* @__PURE__ */ jsxDEV2("button", {
|
|
@@ -141,7 +141,7 @@ function CrmPipelineBoard({
|
|
|
141
141
|
e.stopPropagation();
|
|
142
142
|
handleQuickMove(deal.id, s.id);
|
|
143
143
|
},
|
|
144
|
-
className: "
|
|
144
|
+
className: "w-full px-3 py-1.5 text-left text-sm hover:bg-muted",
|
|
145
145
|
children: s.name
|
|
146
146
|
}, s.id, false, undefined, this))
|
|
147
147
|
]
|
package/dist/ui/hooks/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
1
|
+
export { type UseDealListOptions, useDealList } from './useDealList';
|
|
2
|
+
export { type UseDealMutationsOptions, useDealMutations, } from './useDealMutations';
|
package/dist/ui/hooks/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// src/ui/hooks/useDealList.ts
|
|
3
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
4
3
|
import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
|
|
4
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
5
5
|
"use client";
|
|
6
6
|
function useDealList(options = {}) {
|
|
7
7
|
const { handlers, projectId } = useTemplateRuntime();
|
|
@@ -11,8 +11,13 @@ function useDealList(options = {}) {
|
|
|
11
11
|
const [stages, setStages] = useState([]);
|
|
12
12
|
const [loading, setLoading] = useState(true);
|
|
13
13
|
const [error, setError] = useState(null);
|
|
14
|
-
const [
|
|
14
|
+
const [internalPage, setInternalPage] = useState(0);
|
|
15
15
|
const pipelineId = options.pipelineId ?? "pipeline-1";
|
|
16
|
+
const pageIndex = options.pageIndex ?? internalPage;
|
|
17
|
+
const pageSize = options.pageSize ?? options.limit ?? 50;
|
|
18
|
+
const [sort] = options.sorting ?? [];
|
|
19
|
+
const sortBy = sort?.id;
|
|
20
|
+
const sortDirection = sort ? sort.desc ? "desc" : "asc" : undefined;
|
|
16
21
|
const fetchData = useCallback(async () => {
|
|
17
22
|
setLoading(true);
|
|
18
23
|
setError(null);
|
|
@@ -24,8 +29,10 @@ function useDealList(options = {}) {
|
|
|
24
29
|
stageId: options.stageId,
|
|
25
30
|
status: options.status === "all" ? undefined : options.status,
|
|
26
31
|
search: options.search,
|
|
27
|
-
limit:
|
|
28
|
-
offset:
|
|
32
|
+
limit: pageSize,
|
|
33
|
+
offset: pageIndex * pageSize,
|
|
34
|
+
sortBy: sortBy === "name" || sortBy === "value" || sortBy === "status" || sortBy === "expectedCloseDate" || sortBy === "updatedAt" ? sortBy : undefined,
|
|
35
|
+
sortDirection
|
|
29
36
|
}),
|
|
30
37
|
crm.getDealsByStage({ projectId, pipelineId }),
|
|
31
38
|
crm.getPipelineStages({ pipelineId })
|
|
@@ -45,8 +52,10 @@ function useDealList(options = {}) {
|
|
|
45
52
|
options.stageId,
|
|
46
53
|
options.status,
|
|
47
54
|
options.search,
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
pageIndex,
|
|
56
|
+
pageSize,
|
|
57
|
+
sortBy,
|
|
58
|
+
sortDirection
|
|
50
59
|
]);
|
|
51
60
|
useEffect(() => {
|
|
52
61
|
fetchData();
|
|
@@ -74,16 +83,18 @@ function useDealList(options = {}) {
|
|
|
74
83
|
loading,
|
|
75
84
|
error,
|
|
76
85
|
stats,
|
|
77
|
-
page,
|
|
86
|
+
page: pageIndex + 1,
|
|
87
|
+
pageIndex,
|
|
88
|
+
pageSize,
|
|
78
89
|
refetch: fetchData,
|
|
79
|
-
nextPage: () =>
|
|
80
|
-
prevPage: () =>
|
|
90
|
+
nextPage: options.pageIndex === undefined ? () => setInternalPage((page) => page + 1) : undefined,
|
|
91
|
+
prevPage: options.pageIndex === undefined ? () => pageIndex > 0 && setInternalPage((page) => page - 1) : undefined
|
|
81
92
|
};
|
|
82
93
|
}
|
|
83
94
|
|
|
84
95
|
// src/ui/hooks/useDealMutations.ts
|
|
85
|
-
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
86
96
|
import { useTemplateRuntime as useTemplateRuntime2 } from "@contractspec/lib.example-shared-ui";
|
|
97
|
+
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
87
98
|
function useDealMutations(options = {}) {
|
|
88
99
|
const { handlers, projectId } = useTemplateRuntime2();
|
|
89
100
|
const { crm } = handlers;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ContractTableSort } from '@contractspec/lib.presentation-runtime-core';
|
|
1
2
|
import { type Deal as RuntimeDeal, type ListDealsOutput as RuntimeListDealsOutput, type Stage } from '../../handlers/crm.handlers';
|
|
2
3
|
export type Deal = RuntimeDeal;
|
|
3
4
|
export type ListDealsOutput = RuntimeListDealsOutput;
|
|
@@ -7,6 +8,9 @@ export interface UseDealListOptions {
|
|
|
7
8
|
status?: 'OPEN' | 'WON' | 'LOST' | 'all';
|
|
8
9
|
search?: string;
|
|
9
10
|
limit?: number;
|
|
11
|
+
pageIndex?: number;
|
|
12
|
+
pageSize?: number;
|
|
13
|
+
sorting?: ContractTableSort[];
|
|
10
14
|
}
|
|
11
15
|
export declare function useDealList(options?: UseDealListOptions): {
|
|
12
16
|
data: RuntimeListDealsOutput | null;
|
|
@@ -24,7 +28,9 @@ export declare function useDealList(options?: UseDealListOptions): {
|
|
|
24
28
|
lostCount: number;
|
|
25
29
|
} | null;
|
|
26
30
|
page: number;
|
|
31
|
+
pageIndex: number;
|
|
32
|
+
pageSize: number;
|
|
27
33
|
refetch: () => Promise<void>;
|
|
28
|
-
nextPage: () => void;
|
|
29
|
-
prevPage: () => false | void;
|
|
34
|
+
nextPage: (() => void) | undefined;
|
|
35
|
+
prevPage: (() => false | void) | undefined;
|
|
30
36
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// src/ui/hooks/useDealList.ts
|
|
3
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
4
3
|
import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
|
|
4
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
5
5
|
"use client";
|
|
6
6
|
function useDealList(options = {}) {
|
|
7
7
|
const { handlers, projectId } = useTemplateRuntime();
|
|
@@ -11,8 +11,13 @@ function useDealList(options = {}) {
|
|
|
11
11
|
const [stages, setStages] = useState([]);
|
|
12
12
|
const [loading, setLoading] = useState(true);
|
|
13
13
|
const [error, setError] = useState(null);
|
|
14
|
-
const [
|
|
14
|
+
const [internalPage, setInternalPage] = useState(0);
|
|
15
15
|
const pipelineId = options.pipelineId ?? "pipeline-1";
|
|
16
|
+
const pageIndex = options.pageIndex ?? internalPage;
|
|
17
|
+
const pageSize = options.pageSize ?? options.limit ?? 50;
|
|
18
|
+
const [sort] = options.sorting ?? [];
|
|
19
|
+
const sortBy = sort?.id;
|
|
20
|
+
const sortDirection = sort ? sort.desc ? "desc" : "asc" : undefined;
|
|
16
21
|
const fetchData = useCallback(async () => {
|
|
17
22
|
setLoading(true);
|
|
18
23
|
setError(null);
|
|
@@ -24,8 +29,10 @@ function useDealList(options = {}) {
|
|
|
24
29
|
stageId: options.stageId,
|
|
25
30
|
status: options.status === "all" ? undefined : options.status,
|
|
26
31
|
search: options.search,
|
|
27
|
-
limit:
|
|
28
|
-
offset:
|
|
32
|
+
limit: pageSize,
|
|
33
|
+
offset: pageIndex * pageSize,
|
|
34
|
+
sortBy: sortBy === "name" || sortBy === "value" || sortBy === "status" || sortBy === "expectedCloseDate" || sortBy === "updatedAt" ? sortBy : undefined,
|
|
35
|
+
sortDirection
|
|
29
36
|
}),
|
|
30
37
|
crm.getDealsByStage({ projectId, pipelineId }),
|
|
31
38
|
crm.getPipelineStages({ pipelineId })
|
|
@@ -45,8 +52,10 @@ function useDealList(options = {}) {
|
|
|
45
52
|
options.stageId,
|
|
46
53
|
options.status,
|
|
47
54
|
options.search,
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
pageIndex,
|
|
56
|
+
pageSize,
|
|
57
|
+
sortBy,
|
|
58
|
+
sortDirection
|
|
50
59
|
]);
|
|
51
60
|
useEffect(() => {
|
|
52
61
|
fetchData();
|
|
@@ -74,10 +83,12 @@ function useDealList(options = {}) {
|
|
|
74
83
|
loading,
|
|
75
84
|
error,
|
|
76
85
|
stats,
|
|
77
|
-
page,
|
|
86
|
+
page: pageIndex + 1,
|
|
87
|
+
pageIndex,
|
|
88
|
+
pageSize,
|
|
78
89
|
refetch: fetchData,
|
|
79
|
-
nextPage: () =>
|
|
80
|
-
prevPage: () =>
|
|
90
|
+
nextPage: options.pageIndex === undefined ? () => setInternalPage((page) => page + 1) : undefined,
|
|
91
|
+
prevPage: options.pageIndex === undefined ? () => pageIndex > 0 && setInternalPage((page) => page - 1) : undefined
|
|
81
92
|
};
|
|
82
93
|
}
|
|
83
94
|
export {
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for CRM deal mutations (commands)
|
|
3
|
+
*
|
|
4
|
+
* Uses runtime-local database-backed handlers for:
|
|
5
|
+
* - CreateDealContract
|
|
6
|
+
* - MoveDealContract
|
|
7
|
+
* - WinDealContract
|
|
8
|
+
* - LoseDealContract
|
|
9
|
+
*/
|
|
1
10
|
import type { CreateDealInput, Deal, LoseDealInput, MoveDealInput, WinDealInput } from '../../handlers/crm.handlers';
|
|
2
11
|
export interface MutationState<T> {
|
|
3
12
|
loading: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// src/ui/hooks/useDealMutations.ts
|
|
3
|
-
import { useCallback, useState } from "react";
|
|
4
3
|
import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
|
|
4
|
+
import { useCallback, useState } from "react";
|
|
5
5
|
function useDealMutations(options = {}) {
|
|
6
6
|
const { handlers, projectId } = useTemplateRuntime();
|
|
7
7
|
const { crm } = handlers;
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from './CrmDashboard';
|
|
2
|
-
export * from './CrmPipelineBoard';
|
|
3
2
|
export * from './CrmDealCard';
|
|
4
|
-
export * from './
|
|
3
|
+
export * from './CrmPipelineBoard';
|
|
5
4
|
export * from './hooks';
|
|
6
|
-
export * from './
|
|
5
|
+
export * from './modals';
|
|
7
6
|
export * from './overlays';
|
|
7
|
+
export * from './renderers';
|