@contractspec/example.crm-pipeline 1.57.0 → 1.58.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.
- package/.turbo/turbo-build.log +148 -164
- package/.turbo/turbo-prebuild.log +1 -0
- package/CHANGELOG.md +20 -0
- package/dist/browser/crm-pipeline.feature.js +75 -0
- package/dist/browser/deal/deal.enum.js +18 -0
- package/dist/browser/deal/deal.operation.js +396 -0
- package/dist/browser/deal/deal.schema.js +141 -0
- package/dist/browser/deal/deal.test-spec.js +58 -0
- package/dist/browser/deal/index.js +408 -0
- package/dist/browser/docs/crm-pipeline.docblock.js +113 -0
- package/dist/browser/docs/index.js +113 -0
- package/dist/browser/entities/company.entity.js +52 -0
- package/dist/browser/entities/contact.entity.js +66 -0
- package/dist/browser/entities/deal.entity.js +107 -0
- package/dist/browser/entities/index.js +343 -0
- package/dist/browser/entities/task.entity.js +99 -0
- package/dist/browser/events/contact.event.js +31 -0
- package/dist/browser/events/deal.event.js +101 -0
- package/dist/browser/events/index.js +158 -0
- package/dist/browser/events/task.event.js +28 -0
- package/dist/browser/example.js +39 -0
- package/dist/browser/handlers/crm.handlers.js +160 -0
- package/dist/browser/handlers/deal.handlers.js +293 -0
- package/dist/browser/handlers/index.js +456 -0
- package/dist/browser/handlers/mock-data.js +165 -0
- package/dist/browser/index.js +3279 -0
- package/dist/browser/operations/index.js +407 -0
- package/dist/browser/presentations/dashboard.presentation.js +52 -0
- package/dist/browser/presentations/index.js +284 -0
- package/dist/browser/presentations/pipeline.presentation.js +233 -0
- package/dist/browser/seeders/index.js +22 -0
- package/dist/browser/shared/overlay-types.js +0 -0
- package/dist/browser/ui/CrmDashboard.js +1325 -0
- package/dist/browser/ui/CrmDealCard.js +50 -0
- package/dist/browser/ui/CrmPipelineBoard.js +160 -0
- package/dist/browser/ui/hooks/index.js +186 -0
- package/dist/browser/ui/hooks/useDealList.js +84 -0
- package/dist/browser/ui/hooks/useDealMutations.js +100 -0
- package/dist/browser/ui/index.js +1972 -0
- package/dist/browser/ui/modals/CreateDealModal.js +211 -0
- package/dist/browser/ui/modals/DealActionsModal.js +428 -0
- package/dist/browser/ui/modals/index.js +638 -0
- package/dist/browser/ui/overlays/demo-overlays.js +55 -0
- package/dist/browser/ui/overlays/index.js +55 -0
- package/dist/browser/ui/renderers/index.js +827 -0
- package/dist/browser/ui/renderers/pipeline.markdown.js +564 -0
- package/dist/browser/ui/renderers/pipeline.renderer.js +264 -0
- package/dist/crm-pipeline.feature.d.ts +1 -6
- package/dist/crm-pipeline.feature.d.ts.map +1 -1
- package/dist/crm-pipeline.feature.js +74 -164
- package/dist/deal/deal.enum.d.ts +2 -7
- package/dist/deal/deal.enum.d.ts.map +1 -1
- package/dist/deal/deal.enum.js +16 -22
- package/dist/deal/deal.operation.d.ts +444 -450
- package/dist/deal/deal.operation.d.ts.map +1 -1
- package/dist/deal/deal.operation.js +390 -263
- package/dist/deal/deal.schema.d.ts +251 -256
- package/dist/deal/deal.schema.d.ts.map +1 -1
- package/dist/deal/deal.schema.js +131 -275
- package/dist/deal/deal.test-spec.d.ts +2 -7
- package/dist/deal/deal.test-spec.d.ts.map +1 -1
- package/dist/deal/deal.test-spec.js +56 -62
- package/dist/deal/index.d.ts +7 -4
- package/dist/deal/index.d.ts.map +1 -0
- package/dist/deal/index.js +408 -4
- package/dist/docs/crm-pipeline.docblock.d.ts +2 -1
- package/dist/docs/crm-pipeline.docblock.d.ts.map +1 -0
- package/dist/docs/crm-pipeline.docblock.js +45 -51
- package/dist/docs/index.d.ts +2 -1
- package/dist/docs/index.d.ts.map +1 -0
- package/dist/docs/index.js +114 -1
- package/dist/entities/company.entity.d.ts +27 -32
- package/dist/entities/company.entity.d.ts.map +1 -1
- package/dist/entities/company.entity.js +51 -61
- package/dist/entities/contact.entity.d.ts +31 -36
- package/dist/entities/contact.entity.d.ts.map +1 -1
- package/dist/entities/contact.entity.js +65 -76
- package/dist/entities/deal.entity.d.ts +52 -57
- package/dist/entities/deal.entity.d.ts.map +1 -1
- package/dist/entities/deal.entity.js +104 -116
- package/dist/entities/index.d.ts +6 -10
- package/dist/entities/index.d.ts.map +1 -1
- package/dist/entities/index.js +342 -31
- package/dist/entities/task.entity.d.ts +42 -47
- package/dist/entities/task.entity.d.ts.map +1 -1
- package/dist/entities/task.entity.js +95 -124
- package/dist/events/contact.event.d.ts +21 -27
- package/dist/events/contact.event.d.ts.map +1 -1
- package/dist/events/contact.event.js +29 -42
- package/dist/events/deal.event.d.ts +100 -106
- package/dist/events/deal.event.d.ts.map +1 -1
- package/dist/events/deal.event.js +93 -163
- package/dist/events/index.d.ts +4 -4
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +158 -4
- package/dist/events/task.event.d.ts +21 -27
- package/dist/events/task.event.d.ts.map +1 -1
- package/dist/events/task.event.js +26 -42
- package/dist/example.d.ts +2 -6
- package/dist/example.d.ts.map +1 -1
- package/dist/example.js +38 -50
- package/dist/handlers/crm.handlers.d.ts +80 -78
- package/dist/handlers/crm.handlers.d.ts.map +1 -1
- package/dist/handlers/crm.handlers.js +155 -166
- package/dist/handlers/deal.handlers.d.ts +58 -63
- package/dist/handlers/deal.handlers.d.ts.map +1 -1
- package/dist/handlers/deal.handlers.js +279 -105
- package/dist/handlers/index.d.ts +10 -4
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +456 -4
- package/dist/handlers/mock-data.d.ts +38 -41
- package/dist/handlers/mock-data.d.ts.map +1 -1
- package/dist/handlers/mock-data.js +162 -184
- package/dist/index.d.ts +13 -42
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3277 -53
- package/dist/node/crm-pipeline.feature.js +75 -0
- package/dist/node/deal/deal.enum.js +18 -0
- package/dist/node/deal/deal.operation.js +396 -0
- package/dist/node/deal/deal.schema.js +141 -0
- package/dist/node/deal/deal.test-spec.js +58 -0
- package/dist/node/deal/index.js +408 -0
- package/dist/node/docs/crm-pipeline.docblock.js +113 -0
- package/dist/node/docs/index.js +113 -0
- package/dist/node/entities/company.entity.js +52 -0
- package/dist/node/entities/contact.entity.js +66 -0
- package/dist/node/entities/deal.entity.js +107 -0
- package/dist/node/entities/index.js +343 -0
- package/dist/node/entities/task.entity.js +99 -0
- package/dist/node/events/contact.event.js +31 -0
- package/dist/node/events/deal.event.js +101 -0
- package/dist/node/events/index.js +158 -0
- package/dist/node/events/task.event.js +28 -0
- package/dist/node/example.js +39 -0
- package/dist/node/handlers/crm.handlers.js +160 -0
- package/dist/node/handlers/deal.handlers.js +293 -0
- package/dist/node/handlers/index.js +456 -0
- package/dist/node/handlers/mock-data.js +165 -0
- package/dist/node/index.js +3279 -0
- package/dist/node/operations/index.js +407 -0
- package/dist/node/presentations/dashboard.presentation.js +52 -0
- package/dist/node/presentations/index.js +284 -0
- package/dist/node/presentations/pipeline.presentation.js +233 -0
- package/dist/node/seeders/index.js +22 -0
- package/dist/node/shared/overlay-types.js +0 -0
- package/dist/node/ui/CrmDashboard.js +1325 -0
- package/dist/node/ui/CrmDealCard.js +50 -0
- package/dist/node/ui/CrmPipelineBoard.js +160 -0
- package/dist/node/ui/hooks/index.js +186 -0
- package/dist/node/ui/hooks/useDealList.js +84 -0
- package/dist/node/ui/hooks/useDealMutations.js +100 -0
- package/dist/node/ui/index.js +1972 -0
- package/dist/node/ui/modals/CreateDealModal.js +211 -0
- package/dist/node/ui/modals/DealActionsModal.js +428 -0
- package/dist/node/ui/modals/index.js +638 -0
- package/dist/node/ui/overlays/demo-overlays.js +55 -0
- package/dist/node/ui/overlays/index.js +55 -0
- package/dist/node/ui/renderers/index.js +827 -0
- package/dist/node/ui/renderers/pipeline.markdown.js +564 -0
- package/dist/node/ui/renderers/pipeline.renderer.js +264 -0
- package/dist/operations/index.d.ts +2 -5
- package/dist/operations/index.d.ts.map +1 -0
- package/dist/operations/index.js +407 -5
- package/dist/presentations/dashboard.presentation.d.ts +2 -7
- package/dist/presentations/dashboard.presentation.d.ts.map +1 -1
- package/dist/presentations/dashboard.presentation.js +51 -60
- package/dist/presentations/index.d.ts +3 -3
- package/dist/presentations/index.d.ts.map +1 -0
- package/dist/presentations/index.js +284 -3
- package/dist/presentations/pipeline.presentation.d.ts +4 -9
- package/dist/presentations/pipeline.presentation.d.ts.map +1 -1
- package/dist/presentations/pipeline.presentation.js +228 -116
- package/dist/seeders/index.d.ts +4 -8
- package/dist/seeders/index.d.ts.map +1 -1
- package/dist/seeders/index.js +21 -45
- package/dist/shared/overlay-types.d.ts +25 -28
- package/dist/shared/overlay-types.d.ts.map +1 -1
- package/dist/shared/overlay-types.js +1 -0
- package/dist/ui/CrmDashboard.d.ts +1 -6
- package/dist/ui/CrmDashboard.d.ts.map +1 -1
- package/dist/ui/CrmDashboard.js +1318 -296
- package/dist/ui/CrmDealCard.d.ts +8 -12
- package/dist/ui/CrmDealCard.d.ts.map +1 -1
- package/dist/ui/CrmDealCard.js +47 -45
- package/dist/ui/CrmPipelineBoard.d.ts +11 -20
- package/dist/ui/CrmPipelineBoard.d.ts.map +1 -1
- package/dist/ui/CrmPipelineBoard.js +157 -94
- package/dist/ui/hooks/index.d.ts +3 -3
- package/dist/ui/hooks/index.d.ts.map +1 -0
- package/dist/ui/hooks/index.js +185 -4
- package/dist/ui/hooks/useDealList.d.ts +28 -32
- package/dist/ui/hooks/useDealList.d.ts.map +1 -1
- package/dist/ui/hooks/useDealList.js +81 -90
- package/dist/ui/hooks/useDealMutations.d.ts +18 -22
- package/dist/ui/hooks/useDealMutations.d.ts.map +1 -1
- package/dist/ui/hooks/useDealMutations.js +97 -155
- package/dist/ui/index.d.ts +8 -14
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +1973 -15
- package/dist/ui/modals/CreateDealModal.d.ts +19 -29
- package/dist/ui/modals/CreateDealModal.d.ts.map +1 -1
- package/dist/ui/modals/CreateDealModal.js +209 -180
- package/dist/ui/modals/DealActionsModal.d.ts +31 -44
- package/dist/ui/modals/DealActionsModal.d.ts.map +1 -1
- package/dist/ui/modals/DealActionsModal.js +424 -367
- package/dist/ui/modals/index.d.ts +3 -3
- package/dist/ui/modals/index.d.ts.map +1 -0
- package/dist/ui/modals/index.js +638 -3
- package/dist/ui/overlays/demo-overlays.d.ts +10 -8
- package/dist/ui/overlays/demo-overlays.d.ts.map +1 -1
- package/dist/ui/overlays/demo-overlays.js +54 -66
- package/dist/ui/overlays/index.d.ts +2 -2
- package/dist/ui/overlays/index.d.ts.map +1 -0
- package/dist/ui/overlays/index.js +56 -3
- package/dist/ui/renderers/index.d.ts +3 -3
- package/dist/ui/renderers/index.d.ts.map +1 -0
- package/dist/ui/renderers/index.js +827 -3
- package/dist/ui/renderers/pipeline.markdown.d.ts +12 -11
- package/dist/ui/renderers/pipeline.markdown.d.ts.map +1 -1
- package/dist/ui/renderers/pipeline.markdown.js +560 -114
- package/dist/ui/renderers/pipeline.renderer.d.ts +9 -7
- package/dist/ui/renderers/pipeline.renderer.d.ts.map +1 -1
- package/dist/ui/renderers/pipeline.renderer.js +261 -24
- package/package.json +476 -90
- package/tsdown.config.js +1 -2
- package/.turbo/turbo-build$colon$bundle.log +0 -164
- package/dist/crm-pipeline.feature.js.map +0 -1
- package/dist/deal/deal.enum.js.map +0 -1
- package/dist/deal/deal.operation.js.map +0 -1
- package/dist/deal/deal.schema.js.map +0 -1
- package/dist/deal/deal.test-spec.js.map +0 -1
- package/dist/docs/crm-pipeline.docblock.js.map +0 -1
- package/dist/entities/company.entity.js.map +0 -1
- package/dist/entities/contact.entity.js.map +0 -1
- package/dist/entities/deal.entity.js.map +0 -1
- package/dist/entities/index.js.map +0 -1
- package/dist/entities/task.entity.js.map +0 -1
- package/dist/events/contact.event.js.map +0 -1
- package/dist/events/deal.event.js.map +0 -1
- package/dist/events/task.event.js.map +0 -1
- package/dist/example.js.map +0 -1
- package/dist/handlers/crm.handlers.js.map +0 -1
- package/dist/handlers/deal.handlers.js.map +0 -1
- package/dist/handlers/mock-data.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/presentations/dashboard.presentation.js.map +0 -1
- package/dist/presentations/pipeline.presentation.js.map +0 -1
- package/dist/seeders/index.js.map +0 -1
- package/dist/ui/CrmDashboard.js.map +0 -1
- package/dist/ui/CrmDealCard.js.map +0 -1
- package/dist/ui/CrmPipelineBoard.js.map +0 -1
- package/dist/ui/hooks/useDealList.js.map +0 -1
- package/dist/ui/hooks/useDealMutations.js.map +0 -1
- package/dist/ui/modals/CreateDealModal.js.map +0 -1
- package/dist/ui/modals/DealActionsModal.js.map +0 -1
- package/dist/ui/overlays/demo-overlays.js.map +0 -1
- package/dist/ui/renderers/pipeline.markdown.js.map +0 -1
- package/dist/ui/renderers/pipeline.renderer.js.map +0 -1
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
// src/handlers/crm.handlers.ts
|
|
2
|
+
import { web } from "@contractspec/lib.runtime-sandbox";
|
|
3
|
+
var { generateId } = web;
|
|
4
|
+
function rowToDeal(row) {
|
|
5
|
+
return {
|
|
6
|
+
id: row.id,
|
|
7
|
+
projectId: row.projectId,
|
|
8
|
+
name: row.name,
|
|
9
|
+
value: row.value,
|
|
10
|
+
currency: row.currency,
|
|
11
|
+
pipelineId: row.pipelineId,
|
|
12
|
+
stageId: row.stageId,
|
|
13
|
+
status: row.status,
|
|
14
|
+
contactId: row.contactId ?? undefined,
|
|
15
|
+
companyId: row.companyId ?? undefined,
|
|
16
|
+
ownerId: row.ownerId,
|
|
17
|
+
expectedCloseDate: row.expectedCloseDate ? new Date(row.expectedCloseDate) : undefined,
|
|
18
|
+
wonSource: row.wonSource ?? undefined,
|
|
19
|
+
lostReason: row.lostReason ?? undefined,
|
|
20
|
+
notes: row.notes ?? undefined,
|
|
21
|
+
createdAt: new Date(row.createdAt),
|
|
22
|
+
updatedAt: new Date(row.updatedAt)
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function createCrmHandlers(db) {
|
|
26
|
+
async function listDeals(input) {
|
|
27
|
+
const {
|
|
28
|
+
projectId,
|
|
29
|
+
pipelineId,
|
|
30
|
+
stageId,
|
|
31
|
+
status,
|
|
32
|
+
ownerId,
|
|
33
|
+
search,
|
|
34
|
+
limit = 20,
|
|
35
|
+
offset = 0
|
|
36
|
+
} = input;
|
|
37
|
+
let whereClause = "WHERE projectId = ?";
|
|
38
|
+
const params = [projectId];
|
|
39
|
+
if (pipelineId) {
|
|
40
|
+
whereClause += " AND pipelineId = ?";
|
|
41
|
+
params.push(pipelineId);
|
|
42
|
+
}
|
|
43
|
+
if (stageId) {
|
|
44
|
+
whereClause += " AND stageId = ?";
|
|
45
|
+
params.push(stageId);
|
|
46
|
+
}
|
|
47
|
+
if (status && status !== "all") {
|
|
48
|
+
whereClause += " AND status = ?";
|
|
49
|
+
params.push(status);
|
|
50
|
+
}
|
|
51
|
+
if (ownerId) {
|
|
52
|
+
whereClause += " AND ownerId = ?";
|
|
53
|
+
params.push(ownerId);
|
|
54
|
+
}
|
|
55
|
+
if (search) {
|
|
56
|
+
whereClause += " AND name LIKE ?";
|
|
57
|
+
params.push(`%${search}%`);
|
|
58
|
+
}
|
|
59
|
+
const countResult = (await db.query(`SELECT COUNT(*) as count FROM crm_deal ${whereClause}`, params)).rows;
|
|
60
|
+
const total = countResult[0]?.count ?? 0;
|
|
61
|
+
const valueResult = (await db.query(`SELECT COALESCE(SUM(value), 0) as total FROM crm_deal ${whereClause}`, params)).rows;
|
|
62
|
+
const totalValue = valueResult[0]?.total ?? 0;
|
|
63
|
+
const dealRows = (await db.query(`SELECT * FROM crm_deal ${whereClause} ORDER BY value DESC LIMIT ? OFFSET ?`, [...params, limit, offset])).rows;
|
|
64
|
+
return {
|
|
65
|
+
deals: dealRows.map(rowToDeal),
|
|
66
|
+
total,
|
|
67
|
+
totalValue
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async function createDeal(input, context) {
|
|
71
|
+
const id = generateId("deal");
|
|
72
|
+
const now = new Date().toISOString();
|
|
73
|
+
await db.execute(`INSERT INTO crm_deal (id, projectId, pipelineId, stageId, name, value, currency, status, contactId, companyId, ownerId, expectedCloseDate, createdAt, updatedAt)
|
|
74
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
75
|
+
id,
|
|
76
|
+
context.projectId,
|
|
77
|
+
input.pipelineId,
|
|
78
|
+
input.stageId,
|
|
79
|
+
input.name,
|
|
80
|
+
input.value,
|
|
81
|
+
input.currency ?? "USD",
|
|
82
|
+
"OPEN",
|
|
83
|
+
input.contactId ?? null,
|
|
84
|
+
input.companyId ?? null,
|
|
85
|
+
context.ownerId,
|
|
86
|
+
input.expectedCloseDate?.toISOString() ?? null,
|
|
87
|
+
now,
|
|
88
|
+
now
|
|
89
|
+
]);
|
|
90
|
+
const rows = (await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [id])).rows;
|
|
91
|
+
if (!rows[0]) {
|
|
92
|
+
throw new Error("Failed to create deal");
|
|
93
|
+
}
|
|
94
|
+
return rowToDeal(rows[0]);
|
|
95
|
+
}
|
|
96
|
+
async function moveDeal(input) {
|
|
97
|
+
const now = new Date().toISOString();
|
|
98
|
+
const existing = (await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])).rows;
|
|
99
|
+
if (!existing[0]) {
|
|
100
|
+
throw new Error("NOT_FOUND");
|
|
101
|
+
}
|
|
102
|
+
const stage = (await db.query(`SELECT * FROM crm_stage WHERE id = ?`, [input.stageId])).rows;
|
|
103
|
+
if (!stage[0]) {
|
|
104
|
+
throw new Error("INVALID_STAGE");
|
|
105
|
+
}
|
|
106
|
+
await db.execute(`UPDATE crm_deal SET stageId = ?, updatedAt = ? WHERE id = ?`, [input.stageId, now, input.dealId]);
|
|
107
|
+
const rows = (await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])).rows;
|
|
108
|
+
return rowToDeal(rows[0]);
|
|
109
|
+
}
|
|
110
|
+
async function winDeal(input) {
|
|
111
|
+
const now = new Date().toISOString();
|
|
112
|
+
const existing = (await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])).rows;
|
|
113
|
+
if (!existing[0]) {
|
|
114
|
+
throw new Error("NOT_FOUND");
|
|
115
|
+
}
|
|
116
|
+
await db.execute(`UPDATE crm_deal SET status = 'WON', wonSource = ?, notes = ?, updatedAt = ? WHERE id = ?`, [input.wonSource ?? null, input.notes ?? null, now, input.dealId]);
|
|
117
|
+
const rows = (await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])).rows;
|
|
118
|
+
return rowToDeal(rows[0]);
|
|
119
|
+
}
|
|
120
|
+
async function loseDeal(input) {
|
|
121
|
+
const now = new Date().toISOString();
|
|
122
|
+
const existing = (await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])).rows;
|
|
123
|
+
if (!existing[0]) {
|
|
124
|
+
throw new Error("NOT_FOUND");
|
|
125
|
+
}
|
|
126
|
+
await db.execute(`UPDATE crm_deal SET status = 'LOST', lostReason = ?, notes = ?, updatedAt = ? WHERE id = ?`, [input.lostReason, input.notes ?? null, now, input.dealId]);
|
|
127
|
+
const rows = (await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])).rows;
|
|
128
|
+
return rowToDeal(rows[0]);
|
|
129
|
+
}
|
|
130
|
+
async function getDealsByStage(input) {
|
|
131
|
+
const deals = (await db.query(`SELECT * FROM crm_deal WHERE projectId = ? AND pipelineId = ? AND status = 'OPEN' ORDER BY value DESC`, [input.projectId, input.pipelineId])).rows;
|
|
132
|
+
const stages = (await db.query(`SELECT * FROM crm_stage WHERE pipelineId = ? ORDER BY position`, [input.pipelineId])).rows;
|
|
133
|
+
const grouped = {};
|
|
134
|
+
for (const stage of stages) {
|
|
135
|
+
grouped[stage.id] = deals.filter((d) => d.stageId === stage.id).map(rowToDeal);
|
|
136
|
+
}
|
|
137
|
+
return grouped;
|
|
138
|
+
}
|
|
139
|
+
async function getPipelineStages(input) {
|
|
140
|
+
const rows = (await db.query(`SELECT * FROM crm_stage WHERE pipelineId = ? ORDER BY position`, [input.pipelineId])).rows;
|
|
141
|
+
return rows.map((row) => ({
|
|
142
|
+
id: row.id,
|
|
143
|
+
pipelineId: row.pipelineId,
|
|
144
|
+
name: row.name,
|
|
145
|
+
position: row.position
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
listDeals,
|
|
150
|
+
createDeal,
|
|
151
|
+
moveDeal,
|
|
152
|
+
winDeal,
|
|
153
|
+
loseDeal,
|
|
154
|
+
getDealsByStage,
|
|
155
|
+
getPipelineStages
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/handlers/mock-data.ts
|
|
160
|
+
var MOCK_STAGES = [
|
|
161
|
+
{ id: "stage-1", name: "Lead", position: 1, pipelineId: "pipeline-1" },
|
|
162
|
+
{ id: "stage-2", name: "Qualified", position: 2, pipelineId: "pipeline-1" },
|
|
163
|
+
{ id: "stage-3", name: "Proposal", position: 3, pipelineId: "pipeline-1" },
|
|
164
|
+
{ id: "stage-4", name: "Negotiation", position: 4, pipelineId: "pipeline-1" },
|
|
165
|
+
{ id: "stage-5", name: "Closed", position: 5, pipelineId: "pipeline-1" }
|
|
166
|
+
];
|
|
167
|
+
var MOCK_DEALS = [
|
|
168
|
+
{
|
|
169
|
+
id: "deal-1",
|
|
170
|
+
name: "Enterprise License - Acme Corp",
|
|
171
|
+
value: 75000,
|
|
172
|
+
currency: "USD",
|
|
173
|
+
pipelineId: "pipeline-1",
|
|
174
|
+
stageId: "stage-3",
|
|
175
|
+
status: "OPEN",
|
|
176
|
+
contactId: "contact-1",
|
|
177
|
+
companyId: "company-1",
|
|
178
|
+
ownerId: "user-1",
|
|
179
|
+
expectedCloseDate: new Date("2024-05-15T00:00:00Z"),
|
|
180
|
+
createdAt: new Date("2024-02-01T10:00:00Z"),
|
|
181
|
+
updatedAt: new Date("2024-04-10T14:30:00Z")
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
id: "deal-2",
|
|
185
|
+
name: "Startup Plan - TechStart Inc",
|
|
186
|
+
value: 12000,
|
|
187
|
+
currency: "USD",
|
|
188
|
+
pipelineId: "pipeline-1",
|
|
189
|
+
stageId: "stage-2",
|
|
190
|
+
status: "OPEN",
|
|
191
|
+
contactId: "contact-2",
|
|
192
|
+
companyId: "company-2",
|
|
193
|
+
ownerId: "user-2",
|
|
194
|
+
expectedCloseDate: new Date("2024-04-30T00:00:00Z"),
|
|
195
|
+
createdAt: new Date("2024-03-15T09:00:00Z"),
|
|
196
|
+
updatedAt: new Date("2024-04-08T11:15:00Z")
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
id: "deal-3",
|
|
200
|
+
name: "Professional Services - Global Ltd",
|
|
201
|
+
value: 45000,
|
|
202
|
+
currency: "USD",
|
|
203
|
+
pipelineId: "pipeline-1",
|
|
204
|
+
stageId: "stage-4",
|
|
205
|
+
status: "OPEN",
|
|
206
|
+
contactId: "contact-3",
|
|
207
|
+
companyId: "company-3",
|
|
208
|
+
ownerId: "user-1",
|
|
209
|
+
expectedCloseDate: new Date("2024-04-20T00:00:00Z"),
|
|
210
|
+
createdAt: new Date("2024-01-20T08:00:00Z"),
|
|
211
|
+
updatedAt: new Date("2024-04-12T16:45:00Z")
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
id: "deal-4",
|
|
215
|
+
name: "Annual Contract - SmallBiz Co",
|
|
216
|
+
value: 8500,
|
|
217
|
+
currency: "USD",
|
|
218
|
+
pipelineId: "pipeline-1",
|
|
219
|
+
stageId: "stage-1",
|
|
220
|
+
status: "OPEN",
|
|
221
|
+
contactId: "contact-4",
|
|
222
|
+
companyId: "company-4",
|
|
223
|
+
ownerId: "user-3",
|
|
224
|
+
createdAt: new Date("2024-04-05T12:00:00Z"),
|
|
225
|
+
updatedAt: new Date("2024-04-05T12:00:00Z")
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
id: "deal-5",
|
|
229
|
+
name: "Custom Integration - MegaCorp",
|
|
230
|
+
value: 125000,
|
|
231
|
+
currency: "USD",
|
|
232
|
+
pipelineId: "pipeline-1",
|
|
233
|
+
stageId: "stage-5",
|
|
234
|
+
status: "WON",
|
|
235
|
+
contactId: "contact-5",
|
|
236
|
+
companyId: "company-5",
|
|
237
|
+
ownerId: "user-1",
|
|
238
|
+
expectedCloseDate: new Date("2024-03-31T00:00:00Z"),
|
|
239
|
+
createdAt: new Date("2023-11-10T10:00:00Z"),
|
|
240
|
+
updatedAt: new Date("2024-03-28T09:00:00Z")
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
id: "deal-6",
|
|
244
|
+
name: "Pilot Project - NewCo",
|
|
245
|
+
value: 5000,
|
|
246
|
+
currency: "USD",
|
|
247
|
+
pipelineId: "pipeline-1",
|
|
248
|
+
stageId: "stage-2",
|
|
249
|
+
status: "LOST",
|
|
250
|
+
contactId: "contact-6",
|
|
251
|
+
companyId: "company-6",
|
|
252
|
+
ownerId: "user-2",
|
|
253
|
+
createdAt: new Date("2024-01-15T14:00:00Z"),
|
|
254
|
+
updatedAt: new Date("2024-02-28T10:30:00Z")
|
|
255
|
+
}
|
|
256
|
+
];
|
|
257
|
+
var MOCK_COMPANIES = [
|
|
258
|
+
{
|
|
259
|
+
id: "company-1",
|
|
260
|
+
name: "Acme Corporation",
|
|
261
|
+
domain: "acme.com",
|
|
262
|
+
industry: "Technology",
|
|
263
|
+
size: "1000-5000",
|
|
264
|
+
website: "https://acme.com",
|
|
265
|
+
createdAt: new Date("2024-01-01T00:00:00Z")
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
id: "company-2",
|
|
269
|
+
name: "TechStart Inc",
|
|
270
|
+
domain: "techstart.io",
|
|
271
|
+
industry: "Software",
|
|
272
|
+
size: "10-50",
|
|
273
|
+
website: "https://techstart.io",
|
|
274
|
+
createdAt: new Date("2024-02-15T00:00:00Z")
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
id: "company-3",
|
|
278
|
+
name: "Global Ltd",
|
|
279
|
+
domain: "global.com",
|
|
280
|
+
industry: "Consulting",
|
|
281
|
+
size: "500-1000",
|
|
282
|
+
website: "https://global.com",
|
|
283
|
+
createdAt: new Date("2023-12-01T00:00:00Z")
|
|
284
|
+
}
|
|
285
|
+
];
|
|
286
|
+
var MOCK_CONTACTS = [
|
|
287
|
+
{
|
|
288
|
+
id: "contact-1",
|
|
289
|
+
firstName: "John",
|
|
290
|
+
lastName: "Smith",
|
|
291
|
+
email: "john.smith@acme.com",
|
|
292
|
+
phone: "+1-555-0101",
|
|
293
|
+
title: "VP of Engineering",
|
|
294
|
+
companyId: "company-1",
|
|
295
|
+
createdAt: new Date("2024-01-05T00:00:00Z")
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
id: "contact-2",
|
|
299
|
+
firstName: "Sarah",
|
|
300
|
+
lastName: "Johnson",
|
|
301
|
+
email: "sarah@techstart.io",
|
|
302
|
+
phone: "+1-555-0102",
|
|
303
|
+
title: "CEO",
|
|
304
|
+
companyId: "company-2",
|
|
305
|
+
createdAt: new Date("2024-02-20T00:00:00Z")
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
id: "contact-3",
|
|
309
|
+
firstName: "Michael",
|
|
310
|
+
lastName: "Brown",
|
|
311
|
+
email: "michael.brown@global.com",
|
|
312
|
+
phone: "+1-555-0103",
|
|
313
|
+
title: "CTO",
|
|
314
|
+
companyId: "company-3",
|
|
315
|
+
createdAt: new Date("2023-12-10T00:00:00Z")
|
|
316
|
+
}
|
|
317
|
+
];
|
|
318
|
+
|
|
319
|
+
// src/handlers/deal.handlers.ts
|
|
320
|
+
async function mockListDealsHandler(input) {
|
|
321
|
+
const {
|
|
322
|
+
pipelineId,
|
|
323
|
+
stageId,
|
|
324
|
+
status,
|
|
325
|
+
ownerId,
|
|
326
|
+
search,
|
|
327
|
+
limit = 20,
|
|
328
|
+
offset = 0
|
|
329
|
+
} = input;
|
|
330
|
+
let filtered = [...MOCK_DEALS];
|
|
331
|
+
if (pipelineId) {
|
|
332
|
+
filtered = filtered.filter((d) => d.pipelineId === pipelineId);
|
|
333
|
+
}
|
|
334
|
+
if (stageId) {
|
|
335
|
+
filtered = filtered.filter((d) => d.stageId === stageId);
|
|
336
|
+
}
|
|
337
|
+
if (status && status !== "all") {
|
|
338
|
+
filtered = filtered.filter((d) => d.status === status);
|
|
339
|
+
}
|
|
340
|
+
if (ownerId) {
|
|
341
|
+
filtered = filtered.filter((d) => d.ownerId === ownerId);
|
|
342
|
+
}
|
|
343
|
+
if (search) {
|
|
344
|
+
const q = search.toLowerCase();
|
|
345
|
+
filtered = filtered.filter((d) => d.name.toLowerCase().includes(q));
|
|
346
|
+
}
|
|
347
|
+
filtered.sort((a, b) => b.value - a.value);
|
|
348
|
+
const total = filtered.length;
|
|
349
|
+
const totalValue = filtered.reduce((sum, d) => sum + d.value, 0);
|
|
350
|
+
const deals = filtered.slice(offset, offset + limit);
|
|
351
|
+
return {
|
|
352
|
+
deals,
|
|
353
|
+
total,
|
|
354
|
+
totalValue
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
async function mockCreateDealHandler(input, context) {
|
|
358
|
+
const now = new Date;
|
|
359
|
+
const deal = {
|
|
360
|
+
id: `deal-${Date.now()}`,
|
|
361
|
+
name: input.name,
|
|
362
|
+
value: input.value,
|
|
363
|
+
currency: input.currency ?? "USD",
|
|
364
|
+
pipelineId: input.pipelineId,
|
|
365
|
+
stageId: input.stageId,
|
|
366
|
+
status: "OPEN",
|
|
367
|
+
contactId: input.contactId,
|
|
368
|
+
companyId: input.companyId,
|
|
369
|
+
ownerId: context.ownerId,
|
|
370
|
+
expectedCloseDate: input.expectedCloseDate,
|
|
371
|
+
createdAt: now,
|
|
372
|
+
updatedAt: now
|
|
373
|
+
};
|
|
374
|
+
MOCK_DEALS.push(deal);
|
|
375
|
+
return deal;
|
|
376
|
+
}
|
|
377
|
+
async function mockMoveDealHandler(input) {
|
|
378
|
+
const dealIndex = MOCK_DEALS.findIndex((d) => d.id === input.dealId);
|
|
379
|
+
if (dealIndex === -1) {
|
|
380
|
+
throw new Error("NOT_FOUND");
|
|
381
|
+
}
|
|
382
|
+
const deal = MOCK_DEALS[dealIndex];
|
|
383
|
+
if (!deal) {
|
|
384
|
+
throw new Error("NOT_FOUND");
|
|
385
|
+
}
|
|
386
|
+
const stage = MOCK_STAGES.find((s) => s.id === input.stageId);
|
|
387
|
+
if (!stage) {
|
|
388
|
+
throw new Error("INVALID_STAGE");
|
|
389
|
+
}
|
|
390
|
+
const updatedDeal = {
|
|
391
|
+
...deal,
|
|
392
|
+
stageId: input.stageId,
|
|
393
|
+
updatedAt: new Date
|
|
394
|
+
};
|
|
395
|
+
MOCK_DEALS[dealIndex] = updatedDeal;
|
|
396
|
+
return updatedDeal;
|
|
397
|
+
}
|
|
398
|
+
async function mockWinDealHandler(input) {
|
|
399
|
+
const dealIndex = MOCK_DEALS.findIndex((d) => d.id === input.dealId);
|
|
400
|
+
if (dealIndex === -1) {
|
|
401
|
+
throw new Error("NOT_FOUND");
|
|
402
|
+
}
|
|
403
|
+
const deal = MOCK_DEALS[dealIndex];
|
|
404
|
+
if (!deal) {
|
|
405
|
+
throw new Error("NOT_FOUND");
|
|
406
|
+
}
|
|
407
|
+
const updatedDeal = {
|
|
408
|
+
...deal,
|
|
409
|
+
status: "WON",
|
|
410
|
+
updatedAt: new Date
|
|
411
|
+
};
|
|
412
|
+
MOCK_DEALS[dealIndex] = updatedDeal;
|
|
413
|
+
return updatedDeal;
|
|
414
|
+
}
|
|
415
|
+
async function mockLoseDealHandler(input) {
|
|
416
|
+
const dealIndex = MOCK_DEALS.findIndex((d) => d.id === input.dealId);
|
|
417
|
+
if (dealIndex === -1) {
|
|
418
|
+
throw new Error("NOT_FOUND");
|
|
419
|
+
}
|
|
420
|
+
const deal = MOCK_DEALS[dealIndex];
|
|
421
|
+
if (!deal) {
|
|
422
|
+
throw new Error("NOT_FOUND");
|
|
423
|
+
}
|
|
424
|
+
const updatedDeal = {
|
|
425
|
+
...deal,
|
|
426
|
+
status: "LOST",
|
|
427
|
+
updatedAt: new Date
|
|
428
|
+
};
|
|
429
|
+
MOCK_DEALS[dealIndex] = updatedDeal;
|
|
430
|
+
return updatedDeal;
|
|
431
|
+
}
|
|
432
|
+
async function mockGetDealsByStageHandler(input) {
|
|
433
|
+
const deals = MOCK_DEALS.filter((d) => d.pipelineId === input.pipelineId && d.status === "OPEN");
|
|
434
|
+
const grouped = {};
|
|
435
|
+
for (const stage of MOCK_STAGES) {
|
|
436
|
+
grouped[stage.id] = deals.filter((d) => d.stageId === stage.id);
|
|
437
|
+
}
|
|
438
|
+
return grouped;
|
|
439
|
+
}
|
|
440
|
+
async function mockGetPipelineStagesHandler(input) {
|
|
441
|
+
return MOCK_STAGES.filter((s) => s.pipelineId === input.pipelineId);
|
|
442
|
+
}
|
|
443
|
+
export {
|
|
444
|
+
mockWinDealHandler,
|
|
445
|
+
mockMoveDealHandler,
|
|
446
|
+
mockLoseDealHandler,
|
|
447
|
+
mockListDealsHandler,
|
|
448
|
+
mockGetPipelineStagesHandler,
|
|
449
|
+
mockGetDealsByStageHandler,
|
|
450
|
+
mockCreateDealHandler,
|
|
451
|
+
createCrmHandlers,
|
|
452
|
+
MOCK_STAGES,
|
|
453
|
+
MOCK_DEALS,
|
|
454
|
+
MOCK_CONTACTS,
|
|
455
|
+
MOCK_COMPANIES
|
|
456
|
+
};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// src/handlers/mock-data.ts
|
|
2
|
+
var MOCK_STAGES = [
|
|
3
|
+
{ id: "stage-1", name: "Lead", position: 1, pipelineId: "pipeline-1" },
|
|
4
|
+
{ id: "stage-2", name: "Qualified", position: 2, pipelineId: "pipeline-1" },
|
|
5
|
+
{ id: "stage-3", name: "Proposal", position: 3, pipelineId: "pipeline-1" },
|
|
6
|
+
{ id: "stage-4", name: "Negotiation", position: 4, pipelineId: "pipeline-1" },
|
|
7
|
+
{ id: "stage-5", name: "Closed", position: 5, pipelineId: "pipeline-1" }
|
|
8
|
+
];
|
|
9
|
+
var MOCK_DEALS = [
|
|
10
|
+
{
|
|
11
|
+
id: "deal-1",
|
|
12
|
+
name: "Enterprise License - Acme Corp",
|
|
13
|
+
value: 75000,
|
|
14
|
+
currency: "USD",
|
|
15
|
+
pipelineId: "pipeline-1",
|
|
16
|
+
stageId: "stage-3",
|
|
17
|
+
status: "OPEN",
|
|
18
|
+
contactId: "contact-1",
|
|
19
|
+
companyId: "company-1",
|
|
20
|
+
ownerId: "user-1",
|
|
21
|
+
expectedCloseDate: new Date("2024-05-15T00:00:00Z"),
|
|
22
|
+
createdAt: new Date("2024-02-01T10:00:00Z"),
|
|
23
|
+
updatedAt: new Date("2024-04-10T14:30:00Z")
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: "deal-2",
|
|
27
|
+
name: "Startup Plan - TechStart Inc",
|
|
28
|
+
value: 12000,
|
|
29
|
+
currency: "USD",
|
|
30
|
+
pipelineId: "pipeline-1",
|
|
31
|
+
stageId: "stage-2",
|
|
32
|
+
status: "OPEN",
|
|
33
|
+
contactId: "contact-2",
|
|
34
|
+
companyId: "company-2",
|
|
35
|
+
ownerId: "user-2",
|
|
36
|
+
expectedCloseDate: new Date("2024-04-30T00:00:00Z"),
|
|
37
|
+
createdAt: new Date("2024-03-15T09:00:00Z"),
|
|
38
|
+
updatedAt: new Date("2024-04-08T11:15:00Z")
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: "deal-3",
|
|
42
|
+
name: "Professional Services - Global Ltd",
|
|
43
|
+
value: 45000,
|
|
44
|
+
currency: "USD",
|
|
45
|
+
pipelineId: "pipeline-1",
|
|
46
|
+
stageId: "stage-4",
|
|
47
|
+
status: "OPEN",
|
|
48
|
+
contactId: "contact-3",
|
|
49
|
+
companyId: "company-3",
|
|
50
|
+
ownerId: "user-1",
|
|
51
|
+
expectedCloseDate: new Date("2024-04-20T00:00:00Z"),
|
|
52
|
+
createdAt: new Date("2024-01-20T08:00:00Z"),
|
|
53
|
+
updatedAt: new Date("2024-04-12T16:45:00Z")
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "deal-4",
|
|
57
|
+
name: "Annual Contract - SmallBiz Co",
|
|
58
|
+
value: 8500,
|
|
59
|
+
currency: "USD",
|
|
60
|
+
pipelineId: "pipeline-1",
|
|
61
|
+
stageId: "stage-1",
|
|
62
|
+
status: "OPEN",
|
|
63
|
+
contactId: "contact-4",
|
|
64
|
+
companyId: "company-4",
|
|
65
|
+
ownerId: "user-3",
|
|
66
|
+
createdAt: new Date("2024-04-05T12:00:00Z"),
|
|
67
|
+
updatedAt: new Date("2024-04-05T12:00:00Z")
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: "deal-5",
|
|
71
|
+
name: "Custom Integration - MegaCorp",
|
|
72
|
+
value: 125000,
|
|
73
|
+
currency: "USD",
|
|
74
|
+
pipelineId: "pipeline-1",
|
|
75
|
+
stageId: "stage-5",
|
|
76
|
+
status: "WON",
|
|
77
|
+
contactId: "contact-5",
|
|
78
|
+
companyId: "company-5",
|
|
79
|
+
ownerId: "user-1",
|
|
80
|
+
expectedCloseDate: new Date("2024-03-31T00:00:00Z"),
|
|
81
|
+
createdAt: new Date("2023-11-10T10:00:00Z"),
|
|
82
|
+
updatedAt: new Date("2024-03-28T09:00:00Z")
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: "deal-6",
|
|
86
|
+
name: "Pilot Project - NewCo",
|
|
87
|
+
value: 5000,
|
|
88
|
+
currency: "USD",
|
|
89
|
+
pipelineId: "pipeline-1",
|
|
90
|
+
stageId: "stage-2",
|
|
91
|
+
status: "LOST",
|
|
92
|
+
contactId: "contact-6",
|
|
93
|
+
companyId: "company-6",
|
|
94
|
+
ownerId: "user-2",
|
|
95
|
+
createdAt: new Date("2024-01-15T14:00:00Z"),
|
|
96
|
+
updatedAt: new Date("2024-02-28T10:30:00Z")
|
|
97
|
+
}
|
|
98
|
+
];
|
|
99
|
+
var MOCK_COMPANIES = [
|
|
100
|
+
{
|
|
101
|
+
id: "company-1",
|
|
102
|
+
name: "Acme Corporation",
|
|
103
|
+
domain: "acme.com",
|
|
104
|
+
industry: "Technology",
|
|
105
|
+
size: "1000-5000",
|
|
106
|
+
website: "https://acme.com",
|
|
107
|
+
createdAt: new Date("2024-01-01T00:00:00Z")
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: "company-2",
|
|
111
|
+
name: "TechStart Inc",
|
|
112
|
+
domain: "techstart.io",
|
|
113
|
+
industry: "Software",
|
|
114
|
+
size: "10-50",
|
|
115
|
+
website: "https://techstart.io",
|
|
116
|
+
createdAt: new Date("2024-02-15T00:00:00Z")
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: "company-3",
|
|
120
|
+
name: "Global Ltd",
|
|
121
|
+
domain: "global.com",
|
|
122
|
+
industry: "Consulting",
|
|
123
|
+
size: "500-1000",
|
|
124
|
+
website: "https://global.com",
|
|
125
|
+
createdAt: new Date("2023-12-01T00:00:00Z")
|
|
126
|
+
}
|
|
127
|
+
];
|
|
128
|
+
var MOCK_CONTACTS = [
|
|
129
|
+
{
|
|
130
|
+
id: "contact-1",
|
|
131
|
+
firstName: "John",
|
|
132
|
+
lastName: "Smith",
|
|
133
|
+
email: "john.smith@acme.com",
|
|
134
|
+
phone: "+1-555-0101",
|
|
135
|
+
title: "VP of Engineering",
|
|
136
|
+
companyId: "company-1",
|
|
137
|
+
createdAt: new Date("2024-01-05T00:00:00Z")
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
id: "contact-2",
|
|
141
|
+
firstName: "Sarah",
|
|
142
|
+
lastName: "Johnson",
|
|
143
|
+
email: "sarah@techstart.io",
|
|
144
|
+
phone: "+1-555-0102",
|
|
145
|
+
title: "CEO",
|
|
146
|
+
companyId: "company-2",
|
|
147
|
+
createdAt: new Date("2024-02-20T00:00:00Z")
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: "contact-3",
|
|
151
|
+
firstName: "Michael",
|
|
152
|
+
lastName: "Brown",
|
|
153
|
+
email: "michael.brown@global.com",
|
|
154
|
+
phone: "+1-555-0103",
|
|
155
|
+
title: "CTO",
|
|
156
|
+
companyId: "company-3",
|
|
157
|
+
createdAt: new Date("2023-12-10T00:00:00Z")
|
|
158
|
+
}
|
|
159
|
+
];
|
|
160
|
+
export {
|
|
161
|
+
MOCK_STAGES,
|
|
162
|
+
MOCK_DEALS,
|
|
163
|
+
MOCK_CONTACTS,
|
|
164
|
+
MOCK_COMPANIES
|
|
165
|
+
};
|