@contractspec/example.crm-pipeline 3.7.6 → 3.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +8 -8
- package/AGENTS.md +51 -33
- package/README.md +66 -148
- package/dist/browser/events/contact.event.js +1 -1
- package/dist/browser/events/deal.event.js +1 -1
- package/dist/browser/events/index.js +3 -3
- package/dist/browser/events/task.event.js +1 -1
- package/dist/browser/index.js +293 -293
- package/dist/browser/ui/CrmDashboard.js +221 -221
- package/dist/browser/ui/CrmDealCard.js +5 -5
- package/dist/browser/ui/CrmPipelineBoard.js +13 -13
- package/dist/browser/ui/hooks/index.js +2 -2
- package/dist/browser/ui/hooks/useDealList.js +1 -1
- package/dist/browser/ui/hooks/useDealMutations.js +1 -1
- package/dist/browser/ui/index.js +290 -290
- package/dist/browser/ui/modals/CreateDealModal.js +12 -12
- package/dist/browser/ui/modals/DealActionsModal.js +21 -21
- package/dist/browser/ui/modals/index.js +33 -33
- package/dist/browser/ui/renderers/index.js +116 -116
- package/dist/browser/ui/renderers/pipeline.renderer.js +97 -97
- package/dist/deal/index.d.ts +2 -2
- package/dist/events/contact.event.js +1 -1
- package/dist/events/deal.event.js +1 -1
- package/dist/events/index.js +3 -3
- package/dist/events/task.event.js +1 -1
- package/dist/handlers/index.d.ts +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +293 -293
- package/dist/node/events/contact.event.js +1 -1
- package/dist/node/events/deal.event.js +1 -1
- package/dist/node/events/index.js +3 -3
- package/dist/node/events/task.event.js +1 -1
- package/dist/node/index.js +293 -293
- package/dist/node/ui/CrmDashboard.js +221 -221
- package/dist/node/ui/CrmDealCard.js +5 -5
- package/dist/node/ui/CrmPipelineBoard.js +13 -13
- package/dist/node/ui/hooks/index.js +2 -2
- package/dist/node/ui/hooks/useDealList.js +1 -1
- package/dist/node/ui/hooks/useDealMutations.js +1 -1
- package/dist/node/ui/index.js +290 -290
- package/dist/node/ui/modals/CreateDealModal.js +12 -12
- package/dist/node/ui/modals/DealActionsModal.js +21 -21
- package/dist/node/ui/modals/index.js +33 -33
- package/dist/node/ui/renderers/index.js +116 -116
- package/dist/node/ui/renderers/pipeline.renderer.js +97 -97
- package/dist/operations/index.d.ts +1 -1
- package/dist/ui/CrmDashboard.js +221 -221
- package/dist/ui/CrmDealCard.js +5 -5
- package/dist/ui/CrmPipelineBoard.js +13 -13
- package/dist/ui/hooks/index.d.ts +2 -2
- package/dist/ui/hooks/index.js +2 -2
- package/dist/ui/hooks/useDealList.js +1 -1
- package/dist/ui/hooks/useDealMutations.d.ts +9 -0
- package/dist/ui/hooks/useDealMutations.js +1 -1
- package/dist/ui/index.d.ts +3 -3
- package/dist/ui/index.js +290 -290
- package/dist/ui/modals/CreateDealModal.js +12 -12
- package/dist/ui/modals/DealActionsModal.js +21 -21
- package/dist/ui/modals/index.js +33 -33
- package/dist/ui/renderers/index.d.ts +1 -1
- package/dist/ui/renderers/index.js +116 -116
- package/dist/ui/renderers/pipeline.renderer.d.ts +1 -1
- package/dist/ui/renderers/pipeline.renderer.js +97 -97
- package/package.json +10 -10
- package/src/crm-pipeline.feature.ts +86 -86
- package/src/deal/deal.enum.ts +8 -8
- package/src/deal/deal.operation.ts +255 -255
- package/src/deal/deal.schema.ts +92 -92
- package/src/deal/deal.test-spec.ts +48 -48
- package/src/deal/index.ts +17 -19
- package/src/docs/crm-pipeline.docblock.ts +43 -43
- package/src/entities/company.entity.ts +52 -52
- package/src/entities/contact.entity.ts +67 -67
- package/src/entities/deal.entity.ts +134 -134
- package/src/entities/index.ts +27 -27
- package/src/entities/task.entity.ts +105 -105
- package/src/events/contact.event.ts +22 -22
- package/src/events/deal.event.ts +77 -77
- package/src/events/task.event.ts +19 -19
- package/src/example.ts +32 -32
- package/src/handlers/crm.handlers.ts +358 -357
- package/src/handlers/deal.handlers.ts +179 -179
- package/src/handlers/index.ts +18 -19
- package/src/handlers/mock-data.ts +167 -167
- package/src/index.ts +11 -11
- package/src/operations/index.ts +16 -16
- package/src/presentations/dashboard.presentation.ts +45 -45
- package/src/presentations/pipeline.presentation.ts +90 -90
- package/src/seeders/index.ts +26 -26
- package/src/shared/overlay-types.ts +23 -23
- package/src/ui/CrmDashboard.tsx +256 -256
- package/src/ui/CrmDealCard.tsx +64 -64
- package/src/ui/CrmPipelineBoard.tsx +105 -105
- package/src/ui/hooks/index.ts +3 -3
- package/src/ui/hooks/useDealList.ts +85 -85
- package/src/ui/hooks/useDealMutations.ts +151 -150
- package/src/ui/index.ts +5 -10
- package/src/ui/modals/CreateDealModal.tsx +217 -217
- package/src/ui/modals/DealActionsModal.tsx +390 -390
- package/src/ui/overlays/demo-overlays.ts +43 -43
- package/src/ui/renderers/index.ts +4 -3
- package/src/ui/renderers/pipeline.markdown.ts +165 -165
- package/src/ui/renderers/pipeline.renderer.tsx +17 -16
- package/tsconfig.json +7 -8
- package/tsdown.config.js +7 -3
|
@@ -5,249 +5,249 @@ import { MOCK_DEALS, MOCK_STAGES } from './mock-data';
|
|
|
5
5
|
|
|
6
6
|
// Types inferred from contract schemas
|
|
7
7
|
export interface Deal {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
value: number;
|
|
11
|
+
currency: string;
|
|
12
|
+
pipelineId: string;
|
|
13
|
+
stageId: string;
|
|
14
|
+
status: 'OPEN' | 'WON' | 'LOST' | 'STALE';
|
|
15
|
+
contactId?: string;
|
|
16
|
+
companyId?: string;
|
|
17
|
+
ownerId: string;
|
|
18
|
+
expectedCloseDate?: Date;
|
|
19
|
+
createdAt: Date;
|
|
20
|
+
updatedAt: Date;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export interface CreateDealInput {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
name: string;
|
|
25
|
+
value: number;
|
|
26
|
+
currency?: string;
|
|
27
|
+
pipelineId: string;
|
|
28
|
+
stageId: string;
|
|
29
|
+
contactId?: string;
|
|
30
|
+
companyId?: string;
|
|
31
|
+
expectedCloseDate?: Date;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
export interface MoveDealInput {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
dealId: string;
|
|
36
|
+
stageId: string;
|
|
37
|
+
position?: number;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export interface WinDealInput {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
dealId: string;
|
|
42
|
+
wonSource?: string;
|
|
43
|
+
notes?: string;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export interface LoseDealInput {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
dealId: string;
|
|
48
|
+
lostReason: string;
|
|
49
|
+
notes?: string;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export interface ListDealsInput {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
pipelineId?: string;
|
|
54
|
+
stageId?: string;
|
|
55
|
+
status?: 'OPEN' | 'WON' | 'LOST' | 'all';
|
|
56
|
+
ownerId?: string;
|
|
57
|
+
search?: string;
|
|
58
|
+
limit?: number;
|
|
59
|
+
offset?: number;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
export interface ListDealsOutput {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
deals: Deal[];
|
|
64
|
+
total: number;
|
|
65
|
+
totalValue: number;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
69
|
* Mock handler for ListDealsContract
|
|
70
70
|
*/
|
|
71
71
|
export async function mockListDealsHandler(
|
|
72
|
-
|
|
72
|
+
input: ListDealsInput
|
|
73
73
|
): Promise<ListDealsOutput> {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
74
|
+
const {
|
|
75
|
+
pipelineId,
|
|
76
|
+
stageId,
|
|
77
|
+
status,
|
|
78
|
+
ownerId,
|
|
79
|
+
search,
|
|
80
|
+
limit = 20,
|
|
81
|
+
offset = 0,
|
|
82
|
+
} = input;
|
|
83
|
+
|
|
84
|
+
let filtered = [...MOCK_DEALS];
|
|
85
|
+
|
|
86
|
+
if (pipelineId) {
|
|
87
|
+
filtered = filtered.filter((d) => d.pipelineId === pipelineId);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (stageId) {
|
|
91
|
+
filtered = filtered.filter((d) => d.stageId === stageId);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (status && status !== 'all') {
|
|
95
|
+
filtered = filtered.filter((d) => d.status === status);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (ownerId) {
|
|
99
|
+
filtered = filtered.filter((d) => d.ownerId === ownerId);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (search) {
|
|
103
|
+
const q = search.toLowerCase();
|
|
104
|
+
filtered = filtered.filter((d) => d.name.toLowerCase().includes(q));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Sort by value descending
|
|
108
|
+
filtered.sort((a, b) => b.value - a.value);
|
|
109
|
+
|
|
110
|
+
const total = filtered.length;
|
|
111
|
+
const totalValue = filtered.reduce((sum, d) => sum + d.value, 0);
|
|
112
|
+
const deals = filtered.slice(offset, offset + limit);
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
deals,
|
|
116
|
+
total,
|
|
117
|
+
totalValue,
|
|
118
|
+
};
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
/**
|
|
122
122
|
* Mock handler for CreateDealContract
|
|
123
123
|
*/
|
|
124
124
|
export async function mockCreateDealHandler(
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
input: CreateDealInput,
|
|
126
|
+
context: { ownerId: string }
|
|
127
127
|
): Promise<Deal> {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
128
|
+
const now = new Date();
|
|
129
|
+
|
|
130
|
+
const deal: Deal = {
|
|
131
|
+
id: `deal-${Date.now()}`,
|
|
132
|
+
name: input.name,
|
|
133
|
+
value: input.value,
|
|
134
|
+
currency: input.currency ?? 'USD',
|
|
135
|
+
pipelineId: input.pipelineId,
|
|
136
|
+
stageId: input.stageId,
|
|
137
|
+
status: 'OPEN',
|
|
138
|
+
contactId: input.contactId,
|
|
139
|
+
companyId: input.companyId,
|
|
140
|
+
ownerId: context.ownerId,
|
|
141
|
+
expectedCloseDate: input.expectedCloseDate,
|
|
142
|
+
createdAt: now,
|
|
143
|
+
updatedAt: now,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
MOCK_DEALS.push(deal);
|
|
147
|
+
|
|
148
|
+
return deal;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
/**
|
|
152
152
|
* Mock handler for MoveDealContract
|
|
153
153
|
*/
|
|
154
154
|
export async function mockMoveDealHandler(input: MoveDealInput): Promise<Deal> {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
155
|
+
const dealIndex = MOCK_DEALS.findIndex((d) => d.id === input.dealId);
|
|
156
|
+
if (dealIndex === -1) {
|
|
157
|
+
throw new Error('NOT_FOUND');
|
|
158
|
+
}
|
|
159
|
+
const deal = MOCK_DEALS[dealIndex];
|
|
160
|
+
if (!deal) {
|
|
161
|
+
throw new Error('NOT_FOUND');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const stage = MOCK_STAGES.find((s) => s.id === input.stageId);
|
|
165
|
+
if (!stage) {
|
|
166
|
+
throw new Error('INVALID_STAGE');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const updatedDeal: Deal = {
|
|
170
|
+
...deal,
|
|
171
|
+
stageId: input.stageId,
|
|
172
|
+
updatedAt: new Date(),
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
MOCK_DEALS[dealIndex] = updatedDeal;
|
|
176
|
+
|
|
177
|
+
return updatedDeal;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
/**
|
|
181
181
|
* Mock handler for WinDealContract
|
|
182
182
|
*/
|
|
183
183
|
export async function mockWinDealHandler(input: WinDealInput): Promise<Deal> {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
184
|
+
const dealIndex = MOCK_DEALS.findIndex((d) => d.id === input.dealId);
|
|
185
|
+
if (dealIndex === -1) {
|
|
186
|
+
throw new Error('NOT_FOUND');
|
|
187
|
+
}
|
|
188
|
+
const deal = MOCK_DEALS[dealIndex];
|
|
189
|
+
if (!deal) {
|
|
190
|
+
throw new Error('NOT_FOUND');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const updatedDeal: Deal = {
|
|
194
|
+
...deal,
|
|
195
|
+
status: 'WON' as const,
|
|
196
|
+
updatedAt: new Date(),
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
MOCK_DEALS[dealIndex] = updatedDeal;
|
|
200
|
+
|
|
201
|
+
return updatedDeal;
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
/**
|
|
205
205
|
* Mock handler for LoseDealContract
|
|
206
206
|
*/
|
|
207
207
|
export async function mockLoseDealHandler(input: LoseDealInput): Promise<Deal> {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
208
|
+
const dealIndex = MOCK_DEALS.findIndex((d) => d.id === input.dealId);
|
|
209
|
+
if (dealIndex === -1) {
|
|
210
|
+
throw new Error('NOT_FOUND');
|
|
211
|
+
}
|
|
212
|
+
const deal = MOCK_DEALS[dealIndex];
|
|
213
|
+
if (!deal) {
|
|
214
|
+
throw new Error('NOT_FOUND');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const updatedDeal: Deal = {
|
|
218
|
+
...deal,
|
|
219
|
+
status: 'LOST' as const,
|
|
220
|
+
updatedAt: new Date(),
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
MOCK_DEALS[dealIndex] = updatedDeal;
|
|
224
|
+
|
|
225
|
+
return updatedDeal;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
/**
|
|
229
229
|
* Get deals grouped by stage for Kanban view
|
|
230
230
|
*/
|
|
231
231
|
export async function mockGetDealsByStageHandler(input: {
|
|
232
|
-
|
|
232
|
+
pipelineId: string;
|
|
233
233
|
}): Promise<Record<string, Deal[]>> {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
234
|
+
const deals = MOCK_DEALS.filter(
|
|
235
|
+
(d) => d.pipelineId === input.pipelineId && d.status === 'OPEN'
|
|
236
|
+
);
|
|
237
237
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
238
|
+
const grouped: Record<string, Deal[]> = {};
|
|
239
|
+
for (const stage of MOCK_STAGES) {
|
|
240
|
+
grouped[stage.id] = deals.filter((d) => d.stageId === stage.id);
|
|
241
|
+
}
|
|
242
242
|
|
|
243
|
-
|
|
243
|
+
return grouped;
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
/**
|
|
247
247
|
* Get pipeline stages
|
|
248
248
|
*/
|
|
249
249
|
export async function mockGetPipelineStagesHandler(input: {
|
|
250
|
-
|
|
250
|
+
pipelineId: string;
|
|
251
251
|
}) {
|
|
252
|
-
|
|
252
|
+
return MOCK_STAGES.filter((s) => s.pipelineId === input.pipelineId);
|
|
253
253
|
}
|
package/src/handlers/index.ts
CHANGED
|
@@ -5,26 +5,25 @@
|
|
|
5
5
|
* for use in demos, tests, and the sandbox environment.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
//
|
|
9
|
-
export * from './
|
|
8
|
+
// Runtime handlers (PGLite)
|
|
9
|
+
export * from './crm.handlers';
|
|
10
10
|
|
|
11
11
|
// Deal handlers
|
|
12
12
|
export {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
13
|
+
type CreateDealInput,
|
|
14
|
+
type Deal,
|
|
15
|
+
type ListDealsInput,
|
|
16
|
+
type ListDealsOutput,
|
|
17
|
+
type LoseDealInput,
|
|
18
|
+
type MoveDealInput,
|
|
19
|
+
mockCreateDealHandler,
|
|
20
|
+
mockGetDealsByStageHandler,
|
|
21
|
+
mockGetPipelineStagesHandler,
|
|
22
|
+
mockListDealsHandler,
|
|
23
|
+
mockLoseDealHandler,
|
|
24
|
+
mockMoveDealHandler,
|
|
25
|
+
mockWinDealHandler,
|
|
26
|
+
type WinDealInput,
|
|
27
27
|
} from './deal.handlers';
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
export * from './crm.handlers';
|
|
28
|
+
// Mock data
|
|
29
|
+
export * from './mock-data';
|