@contractspec/example.crm-pipeline 1.46.1 → 1.47.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$colon$bundle.log +106 -31
- package/.turbo/turbo-build.log +109 -34
- package/CHANGELOG.md +44 -0
- package/dist/crm-pipeline.feature.d.ts +2 -2
- package/dist/crm-pipeline.feature.d.ts.map +1 -1
- package/dist/crm-pipeline.feature.js +9 -2
- package/dist/crm-pipeline.feature.js.map +1 -1
- package/dist/deal/deal.operation.d.ts +6 -6
- package/dist/deal/deal.test-spec.d.ts +8 -0
- package/dist/deal/deal.test-spec.d.ts.map +1 -0
- package/dist/deal/deal.test-spec.js +65 -0
- package/dist/deal/deal.test-spec.js.map +1 -0
- package/dist/entities/company.entity.d.ts +28 -28
- package/dist/entities/contact.entity.d.ts +32 -32
- package/dist/entities/index.js.map +1 -1
- package/dist/entities/task.entity.d.ts +43 -43
- package/dist/events/contact.event.d.ts +8 -8
- package/dist/events/contact.event.js +1 -1
- package/dist/events/deal.event.d.ts +5 -5
- package/dist/events/deal.event.js +1 -1
- package/dist/events/task.event.d.ts +2 -2
- package/dist/events/task.event.d.ts.map +1 -1
- package/dist/events/task.event.js +1 -1
- package/dist/example.d.ts +2 -2
- package/dist/example.d.ts.map +1 -1
- package/dist/example.js +4 -2
- package/dist/example.js.map +1 -1
- package/dist/handlers/crm.handlers.d.ts +89 -0
- package/dist/handlers/crm.handlers.d.ts.map +1 -0
- package/dist/handlers/crm.handlers.js +172 -0
- package/dist/handlers/crm.handlers.js.map +1 -0
- package/dist/handlers/deal.handlers.js.map +1 -1
- package/dist/handlers/index.d.ts +2 -1
- package/dist/handlers/index.js +2 -1
- package/dist/handlers/mock-data.js.map +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/presentations/dashboard.presentation.d.ts +3 -4
- package/dist/presentations/dashboard.presentation.d.ts.map +1 -1
- package/dist/presentations/dashboard.presentation.js +8 -5
- package/dist/presentations/dashboard.presentation.js.map +1 -1
- package/dist/presentations/pipeline.presentation.d.ts +5 -6
- package/dist/presentations/pipeline.presentation.d.ts.map +1 -1
- package/dist/presentations/pipeline.presentation.js +12 -9
- package/dist/presentations/pipeline.presentation.js.map +1 -1
- package/dist/seeders/index.d.ts +10 -0
- package/dist/seeders/index.d.ts.map +1 -0
- package/dist/seeders/index.js +47 -0
- package/dist/seeders/index.js.map +1 -0
- package/dist/shared/overlay-types.d.ts +34 -0
- package/dist/shared/overlay-types.d.ts.map +1 -0
- package/dist/shared/overlay-types.js +0 -0
- package/dist/ui/CrmDashboard.d.ts +7 -0
- package/dist/ui/CrmDashboard.d.ts.map +1 -0
- package/dist/ui/CrmDashboard.js +304 -0
- package/dist/ui/CrmDashboard.js.map +1 -0
- package/dist/ui/CrmDealCard.d.ts +15 -0
- package/dist/ui/CrmDealCard.d.ts.map +1 -0
- package/dist/ui/CrmDealCard.js +49 -0
- package/dist/ui/CrmDealCard.js.map +1 -0
- package/dist/ui/CrmPipelineBoard.d.ts +23 -0
- package/dist/ui/CrmPipelineBoard.d.ts.map +1 -0
- package/dist/ui/CrmPipelineBoard.js +98 -0
- package/dist/ui/CrmPipelineBoard.js.map +1 -0
- package/dist/ui/hooks/index.d.ts +3 -0
- package/dist/ui/hooks/index.js +6 -0
- package/dist/ui/hooks/useDealList.d.ts +35 -0
- package/dist/ui/hooks/useDealList.d.ts.map +1 -0
- package/dist/ui/hooks/useDealList.js +94 -0
- package/dist/ui/hooks/useDealList.js.map +1 -0
- package/dist/ui/hooks/useDealMutations.d.ts +26 -0
- package/dist/ui/hooks/useDealMutations.d.ts.map +1 -0
- package/dist/ui/hooks/useDealMutations.js +159 -0
- package/dist/ui/hooks/useDealMutations.js.map +1 -0
- package/dist/ui/index.d.ts +14 -0
- package/dist/ui/index.js +15 -0
- package/dist/ui/modals/CreateDealModal.d.ts +33 -0
- package/dist/ui/modals/CreateDealModal.d.ts.map +1 -0
- package/dist/ui/modals/CreateDealModal.js +183 -0
- package/dist/ui/modals/CreateDealModal.js.map +1 -0
- package/dist/ui/modals/DealActionsModal.d.ts +51 -0
- package/dist/ui/modals/DealActionsModal.d.ts.map +1 -0
- package/dist/ui/modals/DealActionsModal.js +372 -0
- package/dist/ui/modals/DealActionsModal.js.map +1 -0
- package/dist/ui/modals/index.d.ts +3 -0
- package/dist/ui/modals/index.js +4 -0
- package/dist/ui/overlays/demo-overlays.d.ts +19 -0
- package/dist/ui/overlays/demo-overlays.d.ts.map +1 -0
- package/dist/ui/overlays/demo-overlays.js +68 -0
- package/dist/ui/overlays/demo-overlays.js.map +1 -0
- package/dist/ui/overlays/index.d.ts +2 -0
- package/dist/ui/overlays/index.js +3 -0
- package/dist/ui/renderers/index.d.ts +3 -0
- package/dist/ui/renderers/index.js +4 -0
- package/dist/ui/renderers/pipeline.markdown.d.ts +23 -0
- package/dist/ui/renderers/pipeline.markdown.d.ts.map +1 -0
- package/dist/ui/renderers/pipeline.markdown.js +118 -0
- package/dist/ui/renderers/pipeline.markdown.js.map +1 -0
- package/dist/ui/renderers/pipeline.renderer.d.ts +9 -0
- package/dist/ui/renderers/pipeline.renderer.d.ts.map +1 -0
- package/dist/ui/renderers/pipeline.renderer.js +28 -0
- package/dist/ui/renderers/pipeline.renderer.js.map +1 -0
- package/package.json +38 -13
- package/src/crm-pipeline.feature.ts +3 -3
- package/src/deal/deal.test-spec.ts +55 -0
- package/src/example.ts +3 -3
- package/src/handlers/crm.handlers.ts +415 -0
- package/src/handlers/index.ts +3 -0
- package/src/index.ts +1 -0
- package/src/presentations/dashboard.presentation.ts +5 -6
- package/src/presentations/pipeline.presentation.ts +9 -10
- package/src/seeders/index.ts +35 -0
- package/src/shared/overlay-types.ts +39 -0
- package/src/ui/CrmDashboard.tsx +311 -0
- package/src/ui/CrmDealCard.tsx +83 -0
- package/src/ui/CrmPipelineBoard.tsx +136 -0
- package/src/ui/hooks/index.ts +10 -0
- package/src/ui/hooks/useDealList.ts +113 -0
- package/src/ui/hooks/useDealMutations.ts +174 -0
- package/src/ui/index.ts +18 -0
- package/src/ui/modals/CreateDealModal.tsx +239 -0
- package/src/ui/modals/DealActionsModal.tsx +424 -0
- package/src/ui/modals/index.ts +2 -0
- package/src/ui/overlays/demo-overlays.ts +68 -0
- package/src/ui/overlays/index.ts +1 -0
- package/src/ui/renderers/index.ts +6 -0
- package/src/ui/renderers/pipeline.markdown.ts +198 -0
- package/src/ui/renderers/pipeline.renderer.tsx +35 -0
- package/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { DatabasePort } from "@contractspec/lib.runtime-sandbox";
|
|
2
|
+
|
|
3
|
+
//#region src/handlers/crm.handlers.d.ts
|
|
4
|
+
|
|
5
|
+
interface Deal {
|
|
6
|
+
id: string;
|
|
7
|
+
projectId: string;
|
|
8
|
+
name: string;
|
|
9
|
+
value: number;
|
|
10
|
+
currency: string;
|
|
11
|
+
pipelineId: string;
|
|
12
|
+
stageId: string;
|
|
13
|
+
status: 'OPEN' | 'WON' | 'LOST' | 'STALE';
|
|
14
|
+
contactId?: string;
|
|
15
|
+
companyId?: string;
|
|
16
|
+
ownerId: string;
|
|
17
|
+
expectedCloseDate?: Date;
|
|
18
|
+
wonSource?: string;
|
|
19
|
+
lostReason?: string;
|
|
20
|
+
notes?: string;
|
|
21
|
+
createdAt: Date;
|
|
22
|
+
updatedAt: Date;
|
|
23
|
+
}
|
|
24
|
+
interface Stage {
|
|
25
|
+
id: string;
|
|
26
|
+
pipelineId: string;
|
|
27
|
+
name: string;
|
|
28
|
+
position: number;
|
|
29
|
+
}
|
|
30
|
+
interface CreateDealInput {
|
|
31
|
+
name: string;
|
|
32
|
+
value: number;
|
|
33
|
+
currency?: string;
|
|
34
|
+
pipelineId: string;
|
|
35
|
+
stageId: string;
|
|
36
|
+
contactId?: string;
|
|
37
|
+
companyId?: string;
|
|
38
|
+
expectedCloseDate?: Date;
|
|
39
|
+
}
|
|
40
|
+
interface MoveDealInput {
|
|
41
|
+
dealId: string;
|
|
42
|
+
stageId: string;
|
|
43
|
+
}
|
|
44
|
+
interface WinDealInput {
|
|
45
|
+
dealId: string;
|
|
46
|
+
wonSource?: string;
|
|
47
|
+
notes?: string;
|
|
48
|
+
}
|
|
49
|
+
interface LoseDealInput {
|
|
50
|
+
dealId: string;
|
|
51
|
+
lostReason: string;
|
|
52
|
+
notes?: string;
|
|
53
|
+
}
|
|
54
|
+
interface ListDealsInput {
|
|
55
|
+
projectId: string;
|
|
56
|
+
pipelineId?: string;
|
|
57
|
+
stageId?: string;
|
|
58
|
+
status?: 'OPEN' | 'WON' | 'LOST' | 'all';
|
|
59
|
+
ownerId?: string;
|
|
60
|
+
search?: string;
|
|
61
|
+
limit?: number;
|
|
62
|
+
offset?: number;
|
|
63
|
+
}
|
|
64
|
+
interface ListDealsOutput {
|
|
65
|
+
deals: Deal[];
|
|
66
|
+
total: number;
|
|
67
|
+
totalValue: number;
|
|
68
|
+
}
|
|
69
|
+
declare function createCrmHandlers(db: DatabasePort): {
|
|
70
|
+
listDeals: (input: ListDealsInput) => Promise<ListDealsOutput>;
|
|
71
|
+
createDeal: (input: CreateDealInput, context: {
|
|
72
|
+
projectId: string;
|
|
73
|
+
ownerId: string;
|
|
74
|
+
}) => Promise<Deal>;
|
|
75
|
+
moveDeal: (input: MoveDealInput) => Promise<Deal>;
|
|
76
|
+
winDeal: (input: WinDealInput) => Promise<Deal>;
|
|
77
|
+
loseDeal: (input: LoseDealInput) => Promise<Deal>;
|
|
78
|
+
getDealsByStage: (input: {
|
|
79
|
+
projectId: string;
|
|
80
|
+
pipelineId: string;
|
|
81
|
+
}) => Promise<Record<string, Deal[]>>;
|
|
82
|
+
getPipelineStages: (input: {
|
|
83
|
+
pipelineId: string;
|
|
84
|
+
}) => Promise<Stage[]>;
|
|
85
|
+
};
|
|
86
|
+
type CrmHandlers = ReturnType<typeof createCrmHandlers>;
|
|
87
|
+
//#endregion
|
|
88
|
+
export { CreateDealInput, CrmHandlers, Deal, ListDealsInput, ListDealsOutput, LoseDealInput, MoveDealInput, Stage, WinDealInput, createCrmHandlers };
|
|
89
|
+
//# sourceMappingURL=crm.handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crm.handlers.d.ts","names":[],"sources":["../../src/handlers/crm.handlers.ts"],"sourcesContent":[],"mappings":";;;;AA8BiB,UAjBA,IAAA,CAiBA;EAGA,EAAA,EAAA,MAAK;EAOL,SAAA,EAAA,MAAA;EAWA,IAAA,EAAA,MAAA;EAKA,KAAA,EAAA,MAAA;EAMA,QAAA,EAAA,MAAa;EAMb,UAAA,EAAA,MAAc;EAWd,OAAA,EAAA,MAAA;EAgED,MAAA,EAAA,MAAA,GAAA,KAAiB,GAAA,MAAA,GAAA,OAAA;EAAK,SAAA,CAAA,EAAA,MAAA;EAIJ,SAAA,CAAA,EAAA,MAAA;EAAyB,OAAA,EAAA,MAAA;EAAR,iBAAA,CAAA,EA1H7B,IA0H6B;EA6ExC,SAAA,CAAA,EAAA,MAAA;EAEE,UAAA,CAAA,EAAA,MAAA;EAAR,KAAA,CAAA,EAAA,MAAA;EAsC4B,SAAA,EA3OpB,IA2OoB;EAAwB,SAAA,EA1O5C,IA0O4C;;AAoCzB,UA3Qf,KAAA,CA2Qe;EAAuB,EAAA,EAAA,MAAA;EAAR,UAAA,EAAA,MAAA;EA2Bd,IAAA,EAAA,MAAA;EAAwB,QAAA,EAAA,MAAA;;AA8B5B,UA7TZ,eAAA,CA6TY;EAAf,IAAA,EAAA,MAAA;EAAR,KAAA,EAAA,MAAA;EA8BQ,QAAA,CAAA,EAAA,MAAA;EAAR,UAAA,EAAA,MAAA;EAAO,OAAA,EAAA,MAAA;EA2BD,SAAA,CAAA,EAAA,MAAW;;sBA9WD;;UAGL,aAAA;;;;UAKA,YAAA;;;;;UAMA,aAAA;;;;;UAMA,cAAA;;;;;;;;;;UAWA,eAAA;SACR;;;;iBA+DO,iBAAA,KAAsB;qBAIJ,mBAAiB,QAAQ;sBA6EhD;;;QAEN,QAAQ;oBAsCoB,kBAAgB,QAAQ;mBAoCzB,iBAAe,QAAQ;oBA2BtB,kBAAgB,QAAQ;;;;QA8BnD,QAAQ,eAAe;;;QA8BvB,QAAQ;;KA2BF,WAAA,GAAc,kBAAkB"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { web } from "@contractspec/lib.runtime-sandbox";
|
|
2
|
+
|
|
3
|
+
//#region src/handlers/crm.handlers.ts
|
|
4
|
+
const { generateId } = web;
|
|
5
|
+
function rowToDeal(row) {
|
|
6
|
+
return {
|
|
7
|
+
id: row.id,
|
|
8
|
+
projectId: row.projectId,
|
|
9
|
+
name: row.name,
|
|
10
|
+
value: row.value,
|
|
11
|
+
currency: row.currency,
|
|
12
|
+
pipelineId: row.pipelineId,
|
|
13
|
+
stageId: row.stageId,
|
|
14
|
+
status: row.status,
|
|
15
|
+
contactId: row.contactId ?? void 0,
|
|
16
|
+
companyId: row.companyId ?? void 0,
|
|
17
|
+
ownerId: row.ownerId,
|
|
18
|
+
expectedCloseDate: row.expectedCloseDate ? new Date(row.expectedCloseDate) : void 0,
|
|
19
|
+
wonSource: row.wonSource ?? void 0,
|
|
20
|
+
lostReason: row.lostReason ?? void 0,
|
|
21
|
+
notes: row.notes ?? void 0,
|
|
22
|
+
createdAt: new Date(row.createdAt),
|
|
23
|
+
updatedAt: new Date(row.updatedAt)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function createCrmHandlers(db) {
|
|
27
|
+
/**
|
|
28
|
+
* List deals with filtering
|
|
29
|
+
*/
|
|
30
|
+
async function listDeals(input) {
|
|
31
|
+
const { projectId, pipelineId, stageId, status, ownerId, search, limit = 20, offset = 0 } = input;
|
|
32
|
+
let whereClause = "WHERE projectId = ?";
|
|
33
|
+
const params = [projectId];
|
|
34
|
+
if (pipelineId) {
|
|
35
|
+
whereClause += " AND pipelineId = ?";
|
|
36
|
+
params.push(pipelineId);
|
|
37
|
+
}
|
|
38
|
+
if (stageId) {
|
|
39
|
+
whereClause += " AND stageId = ?";
|
|
40
|
+
params.push(stageId);
|
|
41
|
+
}
|
|
42
|
+
if (status && status !== "all") {
|
|
43
|
+
whereClause += " AND status = ?";
|
|
44
|
+
params.push(status);
|
|
45
|
+
}
|
|
46
|
+
if (ownerId) {
|
|
47
|
+
whereClause += " AND ownerId = ?";
|
|
48
|
+
params.push(ownerId);
|
|
49
|
+
}
|
|
50
|
+
if (search) {
|
|
51
|
+
whereClause += " AND name LIKE ?";
|
|
52
|
+
params.push(`%${search}%`);
|
|
53
|
+
}
|
|
54
|
+
const total = (await db.query(`SELECT COUNT(*) as count FROM crm_deal ${whereClause}`, params)).rows[0]?.count ?? 0;
|
|
55
|
+
const totalValue = (await db.query(`SELECT COALESCE(SUM(value), 0) as total FROM crm_deal ${whereClause}`, params)).rows[0]?.total ?? 0;
|
|
56
|
+
return {
|
|
57
|
+
deals: (await db.query(`SELECT * FROM crm_deal ${whereClause} ORDER BY value DESC LIMIT ? OFFSET ?`, [
|
|
58
|
+
...params,
|
|
59
|
+
limit,
|
|
60
|
+
offset
|
|
61
|
+
])).rows.map(rowToDeal),
|
|
62
|
+
total,
|
|
63
|
+
totalValue
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create a new deal
|
|
68
|
+
*/
|
|
69
|
+
async function createDeal(input, context) {
|
|
70
|
+
const id = generateId("deal");
|
|
71
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
72
|
+
await db.execute(`INSERT INTO crm_deal (id, projectId, pipelineId, stageId, name, value, currency, status, contactId, companyId, ownerId, expectedCloseDate, createdAt, updatedAt)
|
|
73
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
74
|
+
id,
|
|
75
|
+
context.projectId,
|
|
76
|
+
input.pipelineId,
|
|
77
|
+
input.stageId,
|
|
78
|
+
input.name,
|
|
79
|
+
input.value,
|
|
80
|
+
input.currency ?? "USD",
|
|
81
|
+
"OPEN",
|
|
82
|
+
input.contactId ?? null,
|
|
83
|
+
input.companyId ?? null,
|
|
84
|
+
context.ownerId,
|
|
85
|
+
input.expectedCloseDate?.toISOString() ?? null,
|
|
86
|
+
now,
|
|
87
|
+
now
|
|
88
|
+
]);
|
|
89
|
+
const rows = (await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [id])).rows;
|
|
90
|
+
if (!rows[0]) throw new Error("Failed to create deal");
|
|
91
|
+
return rowToDeal(rows[0]);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Move a deal to a different stage
|
|
95
|
+
*/
|
|
96
|
+
async function moveDeal(input) {
|
|
97
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
98
|
+
if (!(await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])).rows[0]) throw new Error("NOT_FOUND");
|
|
99
|
+
if (!(await db.query(`SELECT * FROM crm_stage WHERE id = ?`, [input.stageId])).rows[0]) throw new Error("INVALID_STAGE");
|
|
100
|
+
await db.execute(`UPDATE crm_deal SET stageId = ?, updatedAt = ? WHERE id = ?`, [
|
|
101
|
+
input.stageId,
|
|
102
|
+
now,
|
|
103
|
+
input.dealId
|
|
104
|
+
]);
|
|
105
|
+
const rows = (await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])).rows;
|
|
106
|
+
return rowToDeal(rows[0]);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Mark a deal as won
|
|
110
|
+
*/
|
|
111
|
+
async function winDeal(input) {
|
|
112
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
113
|
+
if (!(await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])).rows[0]) throw new Error("NOT_FOUND");
|
|
114
|
+
await db.execute(`UPDATE crm_deal SET status = 'WON', wonSource = ?, notes = ?, updatedAt = ? WHERE id = ?`, [
|
|
115
|
+
input.wonSource ?? null,
|
|
116
|
+
input.notes ?? null,
|
|
117
|
+
now,
|
|
118
|
+
input.dealId
|
|
119
|
+
]);
|
|
120
|
+
const rows = (await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])).rows;
|
|
121
|
+
return rowToDeal(rows[0]);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Mark a deal as lost
|
|
125
|
+
*/
|
|
126
|
+
async function loseDeal(input) {
|
|
127
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
128
|
+
if (!(await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])).rows[0]) throw new Error("NOT_FOUND");
|
|
129
|
+
await db.execute(`UPDATE crm_deal SET status = 'LOST', lostReason = ?, notes = ?, updatedAt = ? WHERE id = ?`, [
|
|
130
|
+
input.lostReason,
|
|
131
|
+
input.notes ?? null,
|
|
132
|
+
now,
|
|
133
|
+
input.dealId
|
|
134
|
+
]);
|
|
135
|
+
const rows = (await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])).rows;
|
|
136
|
+
return rowToDeal(rows[0]);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get deals grouped by stage
|
|
140
|
+
*/
|
|
141
|
+
async function getDealsByStage(input) {
|
|
142
|
+
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;
|
|
143
|
+
const stages = (await db.query(`SELECT * FROM crm_stage WHERE pipelineId = ? ORDER BY position`, [input.pipelineId])).rows;
|
|
144
|
+
const grouped = {};
|
|
145
|
+
for (const stage of stages) grouped[stage.id] = deals.filter((d) => d.stageId === stage.id).map(rowToDeal);
|
|
146
|
+
return grouped;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get pipeline stages
|
|
150
|
+
*/
|
|
151
|
+
async function getPipelineStages(input) {
|
|
152
|
+
return (await db.query(`SELECT * FROM crm_stage WHERE pipelineId = ? ORDER BY position`, [input.pipelineId])).rows.map((row) => ({
|
|
153
|
+
id: row.id,
|
|
154
|
+
pipelineId: row.pipelineId,
|
|
155
|
+
name: row.name,
|
|
156
|
+
position: row.position
|
|
157
|
+
}));
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
listDeals,
|
|
161
|
+
createDeal,
|
|
162
|
+
moveDeal,
|
|
163
|
+
winDeal,
|
|
164
|
+
loseDeal,
|
|
165
|
+
getDealsByStage,
|
|
166
|
+
getPipelineStages
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
//#endregion
|
|
171
|
+
export { createCrmHandlers };
|
|
172
|
+
//# sourceMappingURL=crm.handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crm.handlers.js","names":[],"sources":["../../src/handlers/crm.handlers.ts"],"sourcesContent":["/**\n * Runtime-local CRM handlers\n *\n * These handlers work with the in-browser SQLite database\n * instead of in-memory mock arrays.\n */\nimport type { DatabasePort, DbRow } from '@contractspec/lib.runtime-sandbox';\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport { web } from '@contractspec/lib.runtime-sandbox';\nconst { generateId } = web;\n\n// ============ Types ============\n\nexport interface Deal {\n id: string;\n projectId: string;\n name: string;\n value: number;\n currency: string;\n pipelineId: string;\n stageId: string;\n status: 'OPEN' | 'WON' | 'LOST' | 'STALE';\n contactId?: string;\n companyId?: string;\n ownerId: string;\n expectedCloseDate?: Date;\n wonSource?: string;\n lostReason?: string;\n notes?: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface Stage {\n id: string;\n pipelineId: string;\n name: string;\n position: number;\n}\n\nexport interface CreateDealInput {\n name: string;\n value: number;\n currency?: string;\n pipelineId: string;\n stageId: string;\n contactId?: string;\n companyId?: string;\n expectedCloseDate?: Date;\n}\n\nexport interface MoveDealInput {\n dealId: string;\n stageId: string;\n}\n\nexport interface WinDealInput {\n dealId: string;\n wonSource?: string;\n notes?: string;\n}\n\nexport interface LoseDealInput {\n dealId: string;\n lostReason: string;\n notes?: string;\n}\n\nexport interface ListDealsInput {\n projectId: string;\n pipelineId?: string;\n stageId?: string;\n status?: 'OPEN' | 'WON' | 'LOST' | 'all';\n ownerId?: string;\n search?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface ListDealsOutput {\n deals: Deal[];\n total: number;\n totalValue: number;\n}\n\n// ============ Row Type ============\n\n// Note: We don't use DbRow generics here - just cast the results\n// to the expected types since we know the schema\n\ninterface DealRow {\n id: string;\n projectId: string;\n name: string;\n value: number;\n currency: string;\n pipelineId: string;\n stageId: string;\n status: string;\n contactId: string | null;\n companyId: string | null;\n ownerId: string;\n expectedCloseDate: string | null;\n wonSource: string | null;\n lostReason: string | null;\n notes: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface StageRow {\n id: string;\n pipelineId: string;\n name: string;\n position: number;\n}\n\nfunction rowToDeal(row: DealRow): Deal {\n return {\n id: row.id,\n projectId: row.projectId,\n name: row.name,\n value: row.value,\n currency: row.currency,\n pipelineId: row.pipelineId,\n stageId: row.stageId,\n status: row.status as Deal['status'],\n contactId: row.contactId ?? undefined,\n companyId: row.companyId ?? undefined,\n ownerId: row.ownerId,\n expectedCloseDate: row.expectedCloseDate\n ? new Date(row.expectedCloseDate)\n : undefined,\n wonSource: row.wonSource ?? undefined,\n lostReason: row.lostReason ?? undefined,\n notes: row.notes ?? undefined,\n createdAt: new Date(row.createdAt),\n updatedAt: new Date(row.updatedAt),\n };\n}\n\n// ============ Handler Factory ============\n\nexport function createCrmHandlers(db: DatabasePort) {\n /**\n * List deals with filtering\n */\n async function listDeals(input: ListDealsInput): Promise<ListDealsOutput> {\n const {\n projectId,\n pipelineId,\n stageId,\n status,\n ownerId,\n search,\n limit = 20,\n offset = 0,\n } = input;\n\n let whereClause = 'WHERE projectId = ?';\n const params: (string | number)[] = [projectId];\n\n if (pipelineId) {\n whereClause += ' AND pipelineId = ?';\n params.push(pipelineId);\n }\n\n if (stageId) {\n whereClause += ' AND stageId = ?';\n params.push(stageId);\n }\n\n if (status && status !== 'all') {\n whereClause += ' AND status = ?';\n params.push(status);\n }\n\n if (ownerId) {\n whereClause += ' AND ownerId = ?';\n params.push(ownerId);\n }\n\n if (search) {\n whereClause += ' AND name LIKE ?';\n params.push(`%${search}%`);\n }\n\n // Get total count\n const countResult = (\n await db.query(\n `SELECT COUNT(*) as count FROM crm_deal ${whereClause}`,\n params\n )\n ).rows as DbRow[];\n const total = (countResult[0]?.count as number) ?? 0;\n\n // Get total value\n const valueResult = (\n await db.query(\n `SELECT COALESCE(SUM(value), 0) as total FROM crm_deal ${whereClause}`,\n params\n )\n ).rows as DbRow[];\n const totalValue = (valueResult[0]?.total as number) ?? 0;\n\n // Get paginated deals\n const dealRows = (\n await db.query(\n `SELECT * FROM crm_deal ${whereClause} ORDER BY value DESC LIMIT ? OFFSET ?`,\n [...params, limit, offset]\n )\n ).rows as unknown as DealRow[];\n\n return {\n deals: dealRows.map(rowToDeal),\n total,\n totalValue,\n };\n }\n\n /**\n * Create a new deal\n */\n async function createDeal(\n input: CreateDealInput,\n context: { projectId: string; ownerId: string }\n ): Promise<Deal> {\n const id = generateId('deal');\n const now = new Date().toISOString();\n\n await db.execute(\n `INSERT INTO crm_deal (id, projectId, pipelineId, stageId, name, value, currency, status, contactId, companyId, ownerId, expectedCloseDate, createdAt, updatedAt)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n id,\n context.projectId,\n input.pipelineId,\n input.stageId,\n input.name,\n input.value,\n input.currency ?? 'USD',\n 'OPEN',\n input.contactId ?? null,\n input.companyId ?? null,\n context.ownerId,\n input.expectedCloseDate?.toISOString() ?? null,\n now,\n now,\n ]\n );\n\n const rows = (await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [id]))\n .rows as unknown as DealRow[];\n\n if (!rows[0]) {\n throw new Error('Failed to create deal');\n }\n\n return rowToDeal(rows[0]);\n }\n\n /**\n * Move a deal to a different stage\n */\n async function moveDeal(input: MoveDealInput): Promise<Deal> {\n const now = new Date().toISOString();\n\n // Verify deal exists\n const existing = (\n await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])\n ).rows as unknown as DealRow[];\n\n if (!existing[0]) {\n throw new Error('NOT_FOUND');\n }\n\n // Verify stage exists\n const stage = (\n await db.query(`SELECT * FROM crm_stage WHERE id = ?`, [input.stageId])\n ).rows as unknown as StageRow[];\n\n if (!stage[0]) {\n throw new Error('INVALID_STAGE');\n }\n\n await db.execute(\n `UPDATE crm_deal SET stageId = ?, updatedAt = ? WHERE id = ?`,\n [input.stageId, now, input.dealId]\n );\n\n const rows = (\n await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])\n ).rows as unknown as DealRow[];\n\n return rowToDeal(rows[0]!);\n }\n\n /**\n * Mark a deal as won\n */\n async function winDeal(input: WinDealInput): Promise<Deal> {\n const now = new Date().toISOString();\n\n // Verify deal exists\n const existing = (\n await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])\n ).rows as unknown as DealRow[];\n\n if (!existing[0]) {\n throw new Error('NOT_FOUND');\n }\n\n await db.execute(\n `UPDATE crm_deal SET status = 'WON', wonSource = ?, notes = ?, updatedAt = ? WHERE id = ?`,\n [input.wonSource ?? null, input.notes ?? null, now, input.dealId]\n );\n\n const rows = (\n await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])\n ).rows as unknown as DealRow[];\n\n return rowToDeal(rows[0]!);\n }\n\n /**\n * Mark a deal as lost\n */\n async function loseDeal(input: LoseDealInput): Promise<Deal> {\n const now = new Date().toISOString();\n\n // Verify deal exists\n const existing = (\n await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])\n ).rows as unknown as DealRow[];\n\n if (!existing[0]) {\n throw new Error('NOT_FOUND');\n }\n\n await db.execute(\n `UPDATE crm_deal SET status = 'LOST', lostReason = ?, notes = ?, updatedAt = ? WHERE id = ?`,\n [input.lostReason, input.notes ?? null, now, input.dealId]\n );\n\n const rows = (\n await db.query(`SELECT * FROM crm_deal WHERE id = ?`, [input.dealId])\n ).rows as unknown as DealRow[];\n\n return rowToDeal(rows[0]!);\n }\n\n /**\n * Get deals grouped by stage\n */\n async function getDealsByStage(input: {\n projectId: string;\n pipelineId: string;\n }): Promise<Record<string, Deal[]>> {\n const deals = (\n await db.query(\n `SELECT * FROM crm_deal WHERE projectId = ? AND pipelineId = ? AND status = 'OPEN' ORDER BY value DESC`,\n [input.projectId, input.pipelineId]\n )\n ).rows as unknown as DealRow[];\n\n const stages = (\n await db.query(\n `SELECT * FROM crm_stage WHERE pipelineId = ? ORDER BY position`,\n [input.pipelineId]\n )\n ).rows as unknown as StageRow[];\n\n const grouped: Record<string, Deal[]> = {};\n for (const stage of stages) {\n grouped[stage.id] = deals\n .filter((d) => d.stageId === stage.id)\n .map(rowToDeal);\n }\n\n return grouped;\n }\n\n /**\n * Get pipeline stages\n */\n async function getPipelineStages(input: {\n pipelineId: string;\n }): Promise<Stage[]> {\n const rows = (\n await db.query(\n `SELECT * FROM crm_stage WHERE pipelineId = ? ORDER BY position`,\n [input.pipelineId]\n )\n ).rows as unknown as StageRow[];\n\n return rows.map((row) => ({\n id: row.id,\n pipelineId: row.pipelineId,\n name: row.name,\n position: row.position,\n }));\n }\n\n return {\n listDeals,\n createDeal,\n moveDeal,\n winDeal,\n loseDeal,\n getDealsByStage,\n getPipelineStages,\n };\n}\n\nexport type CrmHandlers = ReturnType<typeof createCrmHandlers>;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deal.handlers.js","names":[
|
|
1
|
+
{"version":3,"file":"deal.handlers.js","names":[],"sources":["../../src/handlers/deal.handlers.ts"],"sourcesContent":["/**\n * Mock handlers for Deal contracts\n */\nimport { MOCK_DEALS, MOCK_STAGES } from './mock-data';\n\n// Types inferred from contract schemas\nexport interface Deal {\n id: string;\n name: string;\n value: number;\n currency: string;\n pipelineId: string;\n stageId: string;\n status: 'OPEN' | 'WON' | 'LOST' | 'STALE';\n contactId?: string;\n companyId?: string;\n ownerId: string;\n expectedCloseDate?: Date;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface CreateDealInput {\n name: string;\n value: number;\n currency?: string;\n pipelineId: string;\n stageId: string;\n contactId?: string;\n companyId?: string;\n expectedCloseDate?: Date;\n}\n\nexport interface MoveDealInput {\n dealId: string;\n stageId: string;\n position?: number;\n}\n\nexport interface WinDealInput {\n dealId: string;\n wonSource?: string;\n notes?: string;\n}\n\nexport interface LoseDealInput {\n dealId: string;\n lostReason: string;\n notes?: string;\n}\n\nexport interface ListDealsInput {\n pipelineId?: string;\n stageId?: string;\n status?: 'OPEN' | 'WON' | 'LOST' | 'all';\n ownerId?: string;\n search?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface ListDealsOutput {\n deals: Deal[];\n total: number;\n totalValue: number;\n}\n\n/**\n * Mock handler for ListDealsContract\n */\nexport async function mockListDealsHandler(\n input: ListDealsInput\n): Promise<ListDealsOutput> {\n const {\n pipelineId,\n stageId,\n status,\n ownerId,\n search,\n limit = 20,\n offset = 0,\n } = input;\n\n let filtered = [...MOCK_DEALS];\n\n if (pipelineId) {\n filtered = filtered.filter((d) => d.pipelineId === pipelineId);\n }\n\n if (stageId) {\n filtered = filtered.filter((d) => d.stageId === stageId);\n }\n\n if (status && status !== 'all') {\n filtered = filtered.filter((d) => d.status === status);\n }\n\n if (ownerId) {\n filtered = filtered.filter((d) => d.ownerId === ownerId);\n }\n\n if (search) {\n const q = search.toLowerCase();\n filtered = filtered.filter((d) => d.name.toLowerCase().includes(q));\n }\n\n // Sort by value descending\n filtered.sort((a, b) => b.value - a.value);\n\n const total = filtered.length;\n const totalValue = filtered.reduce((sum, d) => sum + d.value, 0);\n const deals = filtered.slice(offset, offset + limit);\n\n return {\n deals,\n total,\n totalValue,\n };\n}\n\n/**\n * Mock handler for CreateDealContract\n */\nexport async function mockCreateDealHandler(\n input: CreateDealInput,\n context: { ownerId: string }\n): Promise<Deal> {\n const now = new Date();\n\n const deal: Deal = {\n id: `deal-${Date.now()}`,\n name: input.name,\n value: input.value,\n currency: input.currency ?? 'USD',\n pipelineId: input.pipelineId,\n stageId: input.stageId,\n status: 'OPEN',\n contactId: input.contactId,\n companyId: input.companyId,\n ownerId: context.ownerId,\n expectedCloseDate: input.expectedCloseDate,\n createdAt: now,\n updatedAt: now,\n };\n\n MOCK_DEALS.push(deal);\n\n return deal;\n}\n\n/**\n * Mock handler for MoveDealContract\n */\nexport async function mockMoveDealHandler(input: MoveDealInput): Promise<Deal> {\n const dealIndex = MOCK_DEALS.findIndex((d) => d.id === input.dealId);\n if (dealIndex === -1) {\n throw new Error('NOT_FOUND');\n }\n const deal = MOCK_DEALS[dealIndex];\n if (!deal) {\n throw new Error('NOT_FOUND');\n }\n\n const stage = MOCK_STAGES.find((s) => s.id === input.stageId);\n if (!stage) {\n throw new Error('INVALID_STAGE');\n }\n\n const updatedDeal: Deal = {\n ...deal,\n stageId: input.stageId,\n updatedAt: new Date(),\n };\n\n MOCK_DEALS[dealIndex] = updatedDeal;\n\n return updatedDeal;\n}\n\n/**\n * Mock handler for WinDealContract\n */\nexport async function mockWinDealHandler(input: WinDealInput): Promise<Deal> {\n const dealIndex = MOCK_DEALS.findIndex((d) => d.id === input.dealId);\n if (dealIndex === -1) {\n throw new Error('NOT_FOUND');\n }\n const deal = MOCK_DEALS[dealIndex];\n if (!deal) {\n throw new Error('NOT_FOUND');\n }\n\n const updatedDeal: Deal = {\n ...deal,\n status: 'WON' as const,\n updatedAt: new Date(),\n };\n\n MOCK_DEALS[dealIndex] = updatedDeal;\n\n return updatedDeal;\n}\n\n/**\n * Mock handler for LoseDealContract\n */\nexport async function mockLoseDealHandler(input: LoseDealInput): Promise<Deal> {\n const dealIndex = MOCK_DEALS.findIndex((d) => d.id === input.dealId);\n if (dealIndex === -1) {\n throw new Error('NOT_FOUND');\n }\n const deal = MOCK_DEALS[dealIndex];\n if (!deal) {\n throw new Error('NOT_FOUND');\n }\n\n const updatedDeal: Deal = {\n ...deal,\n status: 'LOST' as const,\n updatedAt: new Date(),\n };\n\n MOCK_DEALS[dealIndex] = updatedDeal;\n\n return updatedDeal;\n}\n\n/**\n * Get deals grouped by stage for Kanban view\n */\nexport async function mockGetDealsByStageHandler(input: {\n pipelineId: string;\n}): Promise<Record<string, Deal[]>> {\n const deals = MOCK_DEALS.filter(\n (d) => d.pipelineId === input.pipelineId && d.status === 'OPEN'\n );\n\n const grouped: Record<string, Deal[]> = {};\n for (const stage of MOCK_STAGES) {\n grouped[stage.id] = deals.filter((d) => d.stageId === stage.id);\n }\n\n return grouped;\n}\n\n/**\n * Get pipeline stages\n */\nexport async function mockGetPipelineStagesHandler(input: {\n pipelineId: string;\n}) {\n return MOCK_STAGES.filter((s) => s.pipelineId === input.pipelineId);\n}\n"],"mappings":"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"}
|
package/dist/handlers/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CrmHandlers, Stage, createCrmHandlers } from "./crm.handlers.js";
|
|
1
2
|
import { MOCK_COMPANIES, MOCK_CONTACTS, MOCK_DEALS, MOCK_STAGES, MockDeal, MockStage } from "./mock-data.js";
|
|
2
3
|
import { CreateDealInput, Deal, ListDealsInput, ListDealsOutput, LoseDealInput, MoveDealInput, WinDealInput, mockCreateDealHandler, mockGetDealsByStageHandler, mockGetPipelineStagesHandler, mockListDealsHandler, mockLoseDealHandler, mockMoveDealHandler, mockWinDealHandler } from "./deal.handlers.js";
|
|
3
|
-
export { type CreateDealInput, type Deal, type ListDealsInput, type ListDealsOutput, type LoseDealInput, MOCK_COMPANIES, MOCK_CONTACTS, MOCK_DEALS, MOCK_STAGES, MockDeal, MockStage, type MoveDealInput, type WinDealInput, mockCreateDealHandler, mockGetDealsByStageHandler, mockGetPipelineStagesHandler, mockListDealsHandler, mockLoseDealHandler, mockMoveDealHandler, mockWinDealHandler };
|
|
4
|
+
export { type CreateDealInput, CrmHandlers, type Deal, type ListDealsInput, type ListDealsOutput, type LoseDealInput, MOCK_COMPANIES, MOCK_CONTACTS, MOCK_DEALS, MOCK_STAGES, MockDeal, MockStage, type MoveDealInput, Stage, type WinDealInput, createCrmHandlers, mockCreateDealHandler, mockGetDealsByStageHandler, mockGetPipelineStagesHandler, mockListDealsHandler, mockLoseDealHandler, mockMoveDealHandler, mockWinDealHandler };
|
package/dist/handlers/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MOCK_COMPANIES, MOCK_CONTACTS, MOCK_DEALS, MOCK_STAGES } from "./mock-data.js";
|
|
2
2
|
import { mockCreateDealHandler, mockGetDealsByStageHandler, mockGetPipelineStagesHandler, mockListDealsHandler, mockLoseDealHandler, mockMoveDealHandler, mockWinDealHandler } from "./deal.handlers.js";
|
|
3
|
+
import { createCrmHandlers } from "./crm.handlers.js";
|
|
3
4
|
|
|
4
|
-
export { MOCK_COMPANIES, MOCK_CONTACTS, MOCK_DEALS, MOCK_STAGES, mockCreateDealHandler, mockGetDealsByStageHandler, mockGetPipelineStagesHandler, mockListDealsHandler, mockLoseDealHandler, mockMoveDealHandler, mockWinDealHandler };
|
|
5
|
+
export { MOCK_COMPANIES, MOCK_CONTACTS, MOCK_DEALS, MOCK_STAGES, createCrmHandlers, mockCreateDealHandler, mockGetDealsByStageHandler, mockGetPipelineStagesHandler, mockListDealsHandler, mockLoseDealHandler, mockMoveDealHandler, mockWinDealHandler };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-data.js","names":[
|
|
1
|
+
{"version":3,"file":"mock-data.js","names":[],"sources":["../../src/handlers/mock-data.ts"],"sourcesContent":["/**\n * Mock data for crm-pipeline handlers\n */\n\n// ============ Types for Mock Data ============\n\nexport interface MockDeal {\n id: string;\n name: string;\n value: number;\n currency: string;\n pipelineId: string;\n stageId: string;\n status: 'OPEN' | 'WON' | 'LOST' | 'STALE';\n contactId?: string;\n companyId?: string;\n ownerId: string;\n expectedCloseDate?: Date;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface MockStage {\n id: string;\n name: string;\n position: number;\n pipelineId: string;\n}\n\n// ============ Pipeline Stages Mock Data ============\n\nexport const MOCK_STAGES: MockStage[] = [\n { id: 'stage-1', name: 'Lead', position: 1, pipelineId: 'pipeline-1' },\n { id: 'stage-2', name: 'Qualified', position: 2, pipelineId: 'pipeline-1' },\n { id: 'stage-3', name: 'Proposal', position: 3, pipelineId: 'pipeline-1' },\n { id: 'stage-4', name: 'Negotiation', position: 4, pipelineId: 'pipeline-1' },\n { id: 'stage-5', name: 'Closed', position: 5, pipelineId: 'pipeline-1' },\n];\n\n// ============ Deal Mock Data ============\n\nexport const MOCK_DEALS: MockDeal[] = [\n {\n id: 'deal-1',\n name: 'Enterprise License - Acme Corp',\n value: 75000,\n currency: 'USD',\n pipelineId: 'pipeline-1',\n stageId: 'stage-3',\n status: 'OPEN',\n contactId: 'contact-1',\n companyId: 'company-1',\n ownerId: 'user-1',\n expectedCloseDate: new Date('2024-05-15T00:00:00Z'),\n createdAt: new Date('2024-02-01T10:00:00Z'),\n updatedAt: new Date('2024-04-10T14:30:00Z'),\n },\n {\n id: 'deal-2',\n name: 'Startup Plan - TechStart Inc',\n value: 12000,\n currency: 'USD',\n pipelineId: 'pipeline-1',\n stageId: 'stage-2',\n status: 'OPEN',\n contactId: 'contact-2',\n companyId: 'company-2',\n ownerId: 'user-2',\n expectedCloseDate: new Date('2024-04-30T00:00:00Z'),\n createdAt: new Date('2024-03-15T09:00:00Z'),\n updatedAt: new Date('2024-04-08T11:15:00Z'),\n },\n {\n id: 'deal-3',\n name: 'Professional Services - Global Ltd',\n value: 45000,\n currency: 'USD',\n pipelineId: 'pipeline-1',\n stageId: 'stage-4',\n status: 'OPEN',\n contactId: 'contact-3',\n companyId: 'company-3',\n ownerId: 'user-1',\n expectedCloseDate: new Date('2024-04-20T00:00:00Z'),\n createdAt: new Date('2024-01-20T08:00:00Z'),\n updatedAt: new Date('2024-04-12T16:45:00Z'),\n },\n {\n id: 'deal-4',\n name: 'Annual Contract - SmallBiz Co',\n value: 8500,\n currency: 'USD',\n pipelineId: 'pipeline-1',\n stageId: 'stage-1',\n status: 'OPEN',\n contactId: 'contact-4',\n companyId: 'company-4',\n ownerId: 'user-3',\n createdAt: new Date('2024-04-05T12:00:00Z'),\n updatedAt: new Date('2024-04-05T12:00:00Z'),\n },\n {\n id: 'deal-5',\n name: 'Custom Integration - MegaCorp',\n value: 125000,\n currency: 'USD',\n pipelineId: 'pipeline-1',\n stageId: 'stage-5',\n status: 'WON',\n contactId: 'contact-5',\n companyId: 'company-5',\n ownerId: 'user-1',\n expectedCloseDate: new Date('2024-03-31T00:00:00Z'),\n createdAt: new Date('2023-11-10T10:00:00Z'),\n updatedAt: new Date('2024-03-28T09:00:00Z'),\n },\n {\n id: 'deal-6',\n name: 'Pilot Project - NewCo',\n value: 5000,\n currency: 'USD',\n pipelineId: 'pipeline-1',\n stageId: 'stage-2',\n status: 'LOST',\n contactId: 'contact-6',\n companyId: 'company-6',\n ownerId: 'user-2',\n createdAt: new Date('2024-01-15T14:00:00Z'),\n updatedAt: new Date('2024-02-28T10:30:00Z'),\n },\n];\n\n// ============ Company Mock Data ============\n\nexport const MOCK_COMPANIES = [\n {\n id: 'company-1',\n name: 'Acme Corporation',\n domain: 'acme.com',\n industry: 'Technology',\n size: '1000-5000',\n website: 'https://acme.com',\n createdAt: new Date('2024-01-01T00:00:00Z'),\n },\n {\n id: 'company-2',\n name: 'TechStart Inc',\n domain: 'techstart.io',\n industry: 'Software',\n size: '10-50',\n website: 'https://techstart.io',\n createdAt: new Date('2024-02-15T00:00:00Z'),\n },\n {\n id: 'company-3',\n name: 'Global Ltd',\n domain: 'global.com',\n industry: 'Consulting',\n size: '500-1000',\n website: 'https://global.com',\n createdAt: new Date('2023-12-01T00:00:00Z'),\n },\n];\n\n// ============ Contact Mock Data ============\n\nexport const MOCK_CONTACTS = [\n {\n id: 'contact-1',\n firstName: 'John',\n lastName: 'Smith',\n email: 'john.smith@acme.com',\n phone: '+1-555-0101',\n title: 'VP of Engineering',\n companyId: 'company-1',\n createdAt: new Date('2024-01-05T00:00:00Z'),\n },\n {\n id: 'contact-2',\n firstName: 'Sarah',\n lastName: 'Johnson',\n email: 'sarah@techstart.io',\n phone: '+1-555-0102',\n title: 'CEO',\n companyId: 'company-2',\n createdAt: new Date('2024-02-20T00:00:00Z'),\n },\n {\n id: 'contact-3',\n firstName: 'Michael',\n lastName: 'Brown',\n email: 'michael.brown@global.com',\n phone: '+1-555-0103',\n title: 'CTO',\n companyId: 'company-3',\n createdAt: new Date('2023-12-10T00:00:00Z'),\n },\n];\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,12 +12,25 @@ import { DealCreatedEvent, DealLostEvent, DealMovedEvent, DealWonEvent } from ".
|
|
|
12
12
|
import { TaskCompletedEvent } from "./events/task.event.js";
|
|
13
13
|
import "./events/index.js";
|
|
14
14
|
import example from "./example.js";
|
|
15
|
+
import { CrmHandlers, Stage, createCrmHandlers } from "./handlers/crm.handlers.js";
|
|
15
16
|
import { MOCK_COMPANIES, MOCK_CONTACTS, MOCK_DEALS, MOCK_STAGES, MockDeal, MockStage } from "./handlers/mock-data.js";
|
|
16
17
|
import { CreateDealInput, Deal, ListDealsInput, ListDealsOutput, LoseDealInput, MoveDealInput, WinDealInput, mockCreateDealHandler, mockGetDealsByStageHandler, mockGetPipelineStagesHandler, mockListDealsHandler, mockLoseDealHandler, mockMoveDealHandler, mockWinDealHandler } from "./handlers/deal.handlers.js";
|
|
18
|
+
import "./handlers/index.js";
|
|
17
19
|
import "./operations/index.js";
|
|
18
20
|
import { CrmDashboardPresentation, PipelineMetricsPresentation } from "./presentations/dashboard.presentation.js";
|
|
19
21
|
import { DealCardPresentation, DealDetailPresentation, DealListPresentation, PipelineKanbanPresentation } from "./presentations/pipeline.presentation.js";
|
|
20
22
|
import "./presentations/index.js";
|
|
23
|
+
import { CrmDashboard } from "./ui/CrmDashboard.js";
|
|
24
|
+
import { UseDealListOptions, useDealList } from "./ui/hooks/useDealList.js";
|
|
25
|
+
import { CrmPipelineBoard } from "./ui/CrmPipelineBoard.js";
|
|
26
|
+
import { CrmDealCard } from "./ui/CrmDealCard.js";
|
|
27
|
+
import { CreateDealModal } from "./ui/modals/CreateDealModal.js";
|
|
28
|
+
import { DealActionsModal } from "./ui/modals/DealActionsModal.js";
|
|
29
|
+
import { UseDealMutationsOptions, useDealMutations } from "./ui/hooks/useDealMutations.js";
|
|
30
|
+
import { crmPipelineReactRenderer } from "./ui/renderers/pipeline.renderer.js";
|
|
31
|
+
import { crmDashboardMarkdownRenderer, crmPipelineMarkdownRenderer } from "./ui/renderers/pipeline.markdown.js";
|
|
32
|
+
import { crmDemoOverlay, crmOverlays, crmSalesRepOverlay } from "./ui/overlays/demo-overlays.js";
|
|
33
|
+
import "./ui/index.js";
|
|
21
34
|
import * as _contractspec_lib_schema0 from "@contractspec/lib.schema";
|
|
22
35
|
|
|
23
36
|
//#region src/index.d.ts
|
|
@@ -30,5 +43,5 @@ declare const schemaComposition: {
|
|
|
30
43
|
outputPath: string;
|
|
31
44
|
};
|
|
32
45
|
//#endregion
|
|
33
|
-
export { ActivityEntity, CompanyEntity, CompanySizeEnum, ContactCreatedEvent, ContactEntity, ContactStatusEnum, CreateDealContract, CreateDealInput, CreateDealInputModel, CrmDashboardPresentation, CrmPipelineFeature, Deal, DealCardPresentation, DealCreatedEvent, DealDetailPresentation, DealEntity, DealListPresentation, DealLostEvent, DealLostPayloadModel, DealModel, DealMovedEvent, DealMovedPayloadModel, DealStatusEnum, DealStatusFilterEnum, DealWonEvent, DealWonPayloadModel, ListDealsContract, ListDealsInput, ListDealsInputModel, ListDealsOutput, ListDealsOutputModel, LoseDealContract, LoseDealInput, LoseDealInputModel, MOCK_COMPANIES, MOCK_CONTACTS, MOCK_DEALS, MOCK_STAGES, MockDeal, MockStage, MoveDealContract, MoveDealInput, MoveDealInputModel, PipelineEntity, PipelineKanbanPresentation, PipelineMetricsPresentation, StageEntity, TaskCompletedEvent, TaskEntity, TaskPriorityEnum, TaskStatusEnum, TaskTypeEnum, WinDealContract, WinDealInput, WinDealInputModel, crmPipelineSchemaContribution, example, mockCreateDealHandler, mockGetDealsByStageHandler, mockGetPipelineStagesHandler, mockListDealsHandler, mockLoseDealHandler, mockMoveDealHandler, mockWinDealHandler, schemaComposition };
|
|
46
|
+
export { ActivityEntity, CompanyEntity, CompanySizeEnum, ContactCreatedEvent, ContactEntity, ContactStatusEnum, CreateDealContract, CreateDealInput, CreateDealInputModel, CreateDealModal, CrmDashboard, CrmDashboardPresentation, CrmDealCard, CrmHandlers, CrmPipelineBoard, CrmPipelineFeature, Deal, DealActionsModal, DealCardPresentation, DealCreatedEvent, DealDetailPresentation, DealEntity, DealListPresentation, DealLostEvent, DealLostPayloadModel, DealModel, DealMovedEvent, DealMovedPayloadModel, DealStatusEnum, DealStatusFilterEnum, DealWonEvent, DealWonPayloadModel, ListDealsContract, ListDealsInput, ListDealsInputModel, ListDealsOutput, ListDealsOutputModel, LoseDealContract, LoseDealInput, LoseDealInputModel, MOCK_COMPANIES, MOCK_CONTACTS, MOCK_DEALS, MOCK_STAGES, MockDeal, MockStage, MoveDealContract, MoveDealInput, MoveDealInputModel, PipelineEntity, PipelineKanbanPresentation, PipelineMetricsPresentation, Stage, StageEntity, TaskCompletedEvent, TaskEntity, TaskPriorityEnum, TaskStatusEnum, TaskTypeEnum, UseDealListOptions, UseDealMutationsOptions, WinDealContract, WinDealInput, WinDealInputModel, createCrmHandlers, crmDashboardMarkdownRenderer, crmDemoOverlay, crmOverlays, crmPipelineMarkdownRenderer, crmPipelineReactRenderer, crmPipelineSchemaContribution, crmSalesRepOverlay, example, mockCreateDealHandler, mockGetDealsByStageHandler, mockGetPipelineStagesHandler, mockListDealsHandler, mockLoseDealHandler, mockMoveDealHandler, mockWinDealHandler, schemaComposition, useDealList, useDealMutations };
|
|
34
47
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAsBa;WASZ,yBAAA,CAAA,wBAAA"}
|
package/dist/index.js
CHANGED
|
@@ -15,9 +15,22 @@ import { TaskCompletedEvent } from "./events/task.event.js";
|
|
|
15
15
|
import "./events/index.js";
|
|
16
16
|
import { MOCK_COMPANIES, MOCK_CONTACTS, MOCK_DEALS, MOCK_STAGES } from "./handlers/mock-data.js";
|
|
17
17
|
import { mockCreateDealHandler, mockGetDealsByStageHandler, mockGetPipelineStagesHandler, mockListDealsHandler, mockLoseDealHandler, mockMoveDealHandler, mockWinDealHandler } from "./handlers/deal.handlers.js";
|
|
18
|
+
import { createCrmHandlers } from "./handlers/crm.handlers.js";
|
|
19
|
+
import "./handlers/index.js";
|
|
18
20
|
import { CrmDashboardPresentation, PipelineMetricsPresentation } from "./presentations/dashboard.presentation.js";
|
|
19
21
|
import { DealCardPresentation, DealDetailPresentation, DealListPresentation, PipelineKanbanPresentation } from "./presentations/pipeline.presentation.js";
|
|
20
22
|
import "./presentations/index.js";
|
|
23
|
+
import { useDealList } from "./ui/hooks/useDealList.js";
|
|
24
|
+
import { useDealMutations } from "./ui/hooks/useDealMutations.js";
|
|
25
|
+
import { CrmDealCard } from "./ui/CrmDealCard.js";
|
|
26
|
+
import { CrmPipelineBoard } from "./ui/CrmPipelineBoard.js";
|
|
27
|
+
import { CreateDealModal } from "./ui/modals/CreateDealModal.js";
|
|
28
|
+
import { DealActionsModal } from "./ui/modals/DealActionsModal.js";
|
|
29
|
+
import { CrmDashboard } from "./ui/CrmDashboard.js";
|
|
30
|
+
import { crmPipelineReactRenderer } from "./ui/renderers/pipeline.renderer.js";
|
|
31
|
+
import { crmDashboardMarkdownRenderer, crmPipelineMarkdownRenderer } from "./ui/renderers/pipeline.markdown.js";
|
|
32
|
+
import { crmDemoOverlay, crmOverlays, crmSalesRepOverlay } from "./ui/overlays/demo-overlays.js";
|
|
33
|
+
import "./ui/index.js";
|
|
21
34
|
import "./docs/index.js";
|
|
22
35
|
import { identityRbacSchemaContribution } from "@contractspec/lib.identity-rbac";
|
|
23
36
|
import { auditTrailSchemaContribution } from "@contractspec/module.audit-trail";
|
|
@@ -39,5 +52,5 @@ const schemaComposition = {
|
|
|
39
52
|
};
|
|
40
53
|
|
|
41
54
|
//#endregion
|
|
42
|
-
export { ActivityEntity, CompanyEntity, CompanySizeEnum, ContactCreatedEvent, ContactEntity, ContactStatusEnum, CreateDealContract, CreateDealInputModel, CrmDashboardPresentation, CrmPipelineFeature, DealCardPresentation, DealCreatedEvent, DealDetailPresentation, DealEntity, DealListPresentation, DealLostEvent, DealLostPayloadModel, DealModel, DealMovedEvent, DealMovedPayloadModel, DealStatusEnum, DealStatusFilterEnum, DealWonEvent, DealWonPayloadModel, ListDealsContract, ListDealsInputModel, ListDealsOutputModel, LoseDealContract, LoseDealInputModel, MOCK_COMPANIES, MOCK_CONTACTS, MOCK_DEALS, MOCK_STAGES, MoveDealContract, MoveDealInputModel, PipelineEntity, PipelineKanbanPresentation, PipelineMetricsPresentation, StageEntity, TaskCompletedEvent, TaskEntity, TaskPriorityEnum, TaskStatusEnum, TaskTypeEnum, WinDealContract, WinDealInputModel, crmPipelineSchemaContribution, example_default as example, mockCreateDealHandler, mockGetDealsByStageHandler, mockGetPipelineStagesHandler, mockListDealsHandler, mockLoseDealHandler, mockMoveDealHandler, mockWinDealHandler, schemaComposition };
|
|
55
|
+
export { ActivityEntity, CompanyEntity, CompanySizeEnum, ContactCreatedEvent, ContactEntity, ContactStatusEnum, CreateDealContract, CreateDealInputModel, CreateDealModal, CrmDashboard, CrmDashboardPresentation, CrmDealCard, CrmPipelineBoard, CrmPipelineFeature, DealActionsModal, DealCardPresentation, DealCreatedEvent, DealDetailPresentation, DealEntity, DealListPresentation, DealLostEvent, DealLostPayloadModel, DealModel, DealMovedEvent, DealMovedPayloadModel, DealStatusEnum, DealStatusFilterEnum, DealWonEvent, DealWonPayloadModel, ListDealsContract, ListDealsInputModel, ListDealsOutputModel, LoseDealContract, LoseDealInputModel, MOCK_COMPANIES, MOCK_CONTACTS, MOCK_DEALS, MOCK_STAGES, MoveDealContract, MoveDealInputModel, PipelineEntity, PipelineKanbanPresentation, PipelineMetricsPresentation, StageEntity, TaskCompletedEvent, TaskEntity, TaskPriorityEnum, TaskStatusEnum, TaskTypeEnum, WinDealContract, WinDealInputModel, createCrmHandlers, crmDashboardMarkdownRenderer, crmDemoOverlay, crmOverlays, crmPipelineMarkdownRenderer, crmPipelineReactRenderer, crmPipelineSchemaContribution, crmSalesRepOverlay, example_default as example, mockCreateDealHandler, mockGetDealsByStageHandler, mockGetPipelineStagesHandler, mockListDealsHandler, mockLoseDealHandler, mockMoveDealHandler, mockWinDealHandler, schemaComposition, useDealList, useDealMutations };
|
|
43
56
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["// CRM Pipeline Example\n// Demonstrates ContractSpec principles for a CRM application\n\nexport * from './entities';\nexport * from './operations';\nexport * from './events';\nexport * from './handlers';\nexport * from './presentations';\nexport * from './crm-pipeline.feature';\nexport { default as example } from './example';\nimport './docs';\n\n// Schema composition configuration\nimport { identityRbacSchemaContribution } from '@contractspec/lib.identity-rbac';\nimport { auditTrailSchemaContribution } from '@contractspec/module.audit-trail';\nimport { notificationsSchemaContribution } from '@contractspec/module.notifications';\nimport { crmPipelineSchemaContribution } from './entities';\n\n/**\n * Complete schema composition for CRM Pipeline.\n */\nexport const schemaComposition = {\n modules: [\n identityRbacSchemaContribution,\n auditTrailSchemaContribution,\n notificationsSchemaContribution,\n crmPipelineSchemaContribution,\n ],\n provider: 'postgresql' as const,\n outputPath: './prisma/schema/generated.prisma',\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["// CRM Pipeline Example\n// Demonstrates ContractSpec principles for a CRM application\n\nexport * from './entities';\nexport * from './operations';\nexport * from './events';\nexport * from './handlers';\nexport * from './presentations';\nexport * from './ui';\nexport * from './crm-pipeline.feature';\nexport { default as example } from './example';\nimport './docs';\n\n// Schema composition configuration\nimport { identityRbacSchemaContribution } from '@contractspec/lib.identity-rbac';\nimport { auditTrailSchemaContribution } from '@contractspec/module.audit-trail';\nimport { notificationsSchemaContribution } from '@contractspec/module.notifications';\nimport { crmPipelineSchemaContribution } from './entities';\n\n/**\n * Complete schema composition for CRM Pipeline.\n */\nexport const schemaComposition = {\n modules: [\n identityRbacSchemaContribution,\n auditTrailSchemaContribution,\n notificationsSchemaContribution,\n crmPipelineSchemaContribution,\n ],\n provider: 'postgresql' as const,\n outputPath: './prisma/schema/generated.prisma',\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAa,oBAAoB;CAC/B,SAAS;EACP;EACA;EACA;EACA;EACD;CACD,UAAU;CACV,YAAY;CACb"}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as _contractspec_lib_contracts18 from "@contractspec/lib.contracts";
|
|
2
2
|
|
|
3
3
|
//#region src/presentations/dashboard.presentation.d.ts
|
|
4
|
-
|
|
5
4
|
/**
|
|
6
5
|
* Main CRM dashboard presentation.
|
|
7
6
|
*/
|
|
8
|
-
declare const CrmDashboardPresentation: PresentationSpec;
|
|
7
|
+
declare const CrmDashboardPresentation: _contractspec_lib_contracts18.PresentationSpec;
|
|
9
8
|
/**
|
|
10
9
|
* Pipeline metrics presentation.
|
|
11
10
|
*/
|
|
12
|
-
declare const PipelineMetricsPresentation: PresentationSpec;
|
|
11
|
+
declare const PipelineMetricsPresentation: _contractspec_lib_contracts18.PresentationSpec;
|
|
13
12
|
//#endregion
|
|
14
13
|
export { CrmDashboardPresentation, PipelineMetricsPresentation };
|
|
15
14
|
//# sourceMappingURL=dashboard.presentation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.presentation.d.ts","names":[],"sources":["../../src/presentations/dashboard.presentation.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dashboard.presentation.d.ts","names":[],"sources":["../../src/presentations/dashboard.presentation.ts"],"sourcesContent":[],"mappings":";;;;;;AAQa,cAAA,wBAuBX,EAAA,6BAAA,CAvBmC,gBAuBnC;AAKF;;;cAAa,6BAsBX,6BAAA,CAtBsC"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { StabilityEnum } from "@contractspec/lib.contracts";
|
|
1
|
+
import { StabilityEnum, definePresentation } from "@contractspec/lib.contracts";
|
|
2
2
|
|
|
3
3
|
//#region src/presentations/dashboard.presentation.ts
|
|
4
4
|
/**
|
|
5
|
+
* CRM Dashboard Presentation Descriptor
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
5
8
|
* Main CRM dashboard presentation.
|
|
6
9
|
*/
|
|
7
|
-
const CrmDashboardPresentation = {
|
|
10
|
+
const CrmDashboardPresentation = definePresentation({
|
|
8
11
|
meta: {
|
|
9
12
|
key: "crm.dashboard",
|
|
10
13
|
version: "1.0.0",
|
|
@@ -24,11 +27,11 @@ const CrmDashboardPresentation = {
|
|
|
24
27
|
},
|
|
25
28
|
targets: ["react", "markdown"],
|
|
26
29
|
policy: { flags: ["crm.enabled"] }
|
|
27
|
-
};
|
|
30
|
+
});
|
|
28
31
|
/**
|
|
29
32
|
* Pipeline metrics presentation.
|
|
30
33
|
*/
|
|
31
|
-
const PipelineMetricsPresentation = {
|
|
34
|
+
const PipelineMetricsPresentation = definePresentation({
|
|
32
35
|
meta: {
|
|
33
36
|
key: "crm.pipeline.metrics",
|
|
34
37
|
version: "1.0.0",
|
|
@@ -52,7 +55,7 @@ const PipelineMetricsPresentation = {
|
|
|
52
55
|
},
|
|
53
56
|
targets: ["react", "markdown"],
|
|
54
57
|
policy: { flags: ["crm.metrics.enabled"] }
|
|
55
|
-
};
|
|
58
|
+
});
|
|
56
59
|
|
|
57
60
|
//#endregion
|
|
58
61
|
export { CrmDashboardPresentation, PipelineMetricsPresentation };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.presentation.js","names":[
|
|
1
|
+
{"version":3,"file":"dashboard.presentation.js","names":[],"sources":["../../src/presentations/dashboard.presentation.ts"],"sourcesContent":["/**\n * CRM Dashboard Presentation Descriptor\n */\nimport { definePresentation, StabilityEnum } from '@contractspec/lib.contracts';\n\n/**\n * Main CRM dashboard presentation.\n */\nexport const CrmDashboardPresentation = definePresentation({\n meta: {\n key: 'crm.dashboard',\n version: '1.0.0',\n title: 'CRM Dashboard',\n description:\n 'Main CRM dashboard with pipeline overview, deal stats, and activities',\n domain: 'crm-pipeline',\n owners: ['@crm-team'],\n tags: ['dashboard', 'overview'],\n stability: StabilityEnum.Experimental,\n goal: 'Provide a high-level overview of CRM performance and active deals.',\n context: 'The landing page for CRM users.',\n },\n source: {\n type: 'component',\n framework: 'react',\n componentKey: 'CrmDashboard',\n },\n targets: ['react', 'markdown'],\n policy: {\n flags: ['crm.enabled'],\n },\n});\n\n/**\n * Pipeline metrics presentation.\n */\nexport const PipelineMetricsPresentation = definePresentation({\n meta: {\n key: 'crm.pipeline.metrics',\n version: '1.0.0',\n title: 'Pipeline Metrics',\n description: 'Pipeline metrics and forecasting view',\n domain: 'crm-pipeline',\n owners: ['@crm-team'],\n tags: ['pipeline', 'metrics', 'forecast'],\n stability: StabilityEnum.Experimental,\n goal: 'Track pipeline health and sales forecasts.',\n context: 'Data-intensive widget for sales managers.',\n },\n source: {\n type: 'component',\n framework: 'react',\n componentKey: 'PipelineMetricsView',\n },\n targets: ['react', 'markdown'],\n policy: {\n flags: ['crm.metrics.enabled'],\n },\n});\n"],"mappings":";;;;;;;;;AAQA,MAAa,2BAA2B,mBAAmB;CACzD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,OAAO;EACP,aACE;EACF,QAAQ;EACR,QAAQ,CAAC,YAAY;EACrB,MAAM,CAAC,aAAa,WAAW;EAC/B,WAAW,cAAc;EACzB,MAAM;EACN,SAAS;EACV;CACD,QAAQ;EACN,MAAM;EACN,WAAW;EACX,cAAc;EACf;CACD,SAAS,CAAC,SAAS,WAAW;CAC9B,QAAQ,EACN,OAAO,CAAC,cAAc,EACvB;CACF,CAAC;;;;AAKF,MAAa,8BAA8B,mBAAmB;CAC5D,MAAM;EACJ,KAAK;EACL,SAAS;EACT,OAAO;EACP,aAAa;EACb,QAAQ;EACR,QAAQ,CAAC,YAAY;EACrB,MAAM;GAAC;GAAY;GAAW;GAAW;EACzC,WAAW,cAAc;EACzB,MAAM;EACN,SAAS;EACV;CACD,QAAQ;EACN,MAAM;EACN,WAAW;EACX,cAAc;EACf;CACD,SAAS,CAAC,SAAS,WAAW;CAC9B,QAAQ,EACN,OAAO,CAAC,sBAAsB,EAC/B;CACF,CAAC"}
|
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as _contractspec_lib_contracts14 from "@contractspec/lib.contracts";
|
|
2
2
|
|
|
3
3
|
//#region src/presentations/pipeline.presentation.d.ts
|
|
4
|
-
|
|
5
4
|
/**
|
|
6
5
|
* Kanban board presentation for the sales pipeline.
|
|
7
6
|
*/
|
|
8
|
-
declare const PipelineKanbanPresentation: PresentationSpec;
|
|
7
|
+
declare const PipelineKanbanPresentation: _contractspec_lib_contracts14.PresentationSpec;
|
|
9
8
|
/**
|
|
10
9
|
* List view of deals with filtering.
|
|
11
10
|
*/
|
|
12
|
-
declare const DealListPresentation: PresentationSpec;
|
|
11
|
+
declare const DealListPresentation: _contractspec_lib_contracts14.PresentationSpec;
|
|
13
12
|
/**
|
|
14
13
|
* Deal detail presentation.
|
|
15
14
|
*/
|
|
16
|
-
declare const DealDetailPresentation: PresentationSpec;
|
|
15
|
+
declare const DealDetailPresentation: _contractspec_lib_contracts14.PresentationSpec;
|
|
17
16
|
/**
|
|
18
17
|
* Deal card for kanban board.
|
|
19
18
|
*/
|
|
20
|
-
declare const DealCardPresentation: PresentationSpec;
|
|
19
|
+
declare const DealCardPresentation: _contractspec_lib_contracts14.PresentationSpec;
|
|
21
20
|
//#endregion
|
|
22
21
|
export { DealCardPresentation, DealDetailPresentation, DealListPresentation, PipelineKanbanPresentation };
|
|
23
22
|
//# sourceMappingURL=pipeline.presentation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.presentation.d.ts","names":[],"sources":["../../src/presentations/pipeline.presentation.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pipeline.presentation.d.ts","names":[],"sources":["../../src/presentations/pipeline.presentation.ts"],"sourcesContent":[],"mappings":";;;;;;AASa,cAAA,0BAuBX,EAAA,6BAAA,CAvBqC,gBAuBrC;AAKF;AA4BA;AA4BA;cAxDa,sBAuBX,6BAAA,CAvB+B;;;;cA4BpB,wBAuBX,6BAAA,CAvBiC;;;;cA4BtB,sBAuBX,6BAAA,CAvB+B"}
|