@startsimpli/funnels 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/package.json +9 -31
  2. package/src/api/README.md +507 -0
  3. package/src/api/adapter.ts +106 -0
  4. package/src/api/client.test.ts +640 -0
  5. package/src/api/client.ts +385 -0
  6. package/src/api/default-adapter.ts +243 -0
  7. package/src/api/index.ts +24 -0
  8. package/src/components/FilterRuleEditor/ARCHITECTURE.md +354 -0
  9. package/src/components/FilterRuleEditor/FieldSelector.tsx +91 -0
  10. package/src/components/FilterRuleEditor/FilterRuleEditor.stories.tsx +462 -0
  11. package/src/components/FilterRuleEditor/FilterRuleEditor.test.tsx +520 -0
  12. package/src/components/FilterRuleEditor/FilterRuleEditor.tsx +225 -0
  13. package/src/components/FilterRuleEditor/LogicToggle.tsx +64 -0
  14. package/src/components/FilterRuleEditor/OperatorSelector.tsx +75 -0
  15. package/src/components/FilterRuleEditor/README.md +291 -0
  16. package/src/components/FilterRuleEditor/RuleRow.tsx +246 -0
  17. package/src/components/FilterRuleEditor/ValueInputs/BooleanValueInput.tsx +54 -0
  18. package/src/components/FilterRuleEditor/ValueInputs/ChoiceValueInput.tsx +83 -0
  19. package/src/components/FilterRuleEditor/ValueInputs/DateValueInput.tsx +70 -0
  20. package/src/components/FilterRuleEditor/ValueInputs/MultiChoiceValueInput.tsx +132 -0
  21. package/src/components/FilterRuleEditor/ValueInputs/NumberValueInput.tsx +73 -0
  22. package/src/components/FilterRuleEditor/ValueInputs/TextValueInput.tsx +50 -0
  23. package/src/components/FilterRuleEditor/ValueInputs/index.ts +12 -0
  24. package/src/components/FilterRuleEditor/constants.ts +64 -0
  25. package/src/components/FilterRuleEditor/index.ts +14 -0
  26. package/src/components/FunnelCard/DESIGN.md +447 -0
  27. package/src/components/FunnelCard/FunnelCard.stories.tsx +484 -0
  28. package/src/components/FunnelCard/FunnelCard.test.ts +257 -0
  29. package/src/components/FunnelCard/FunnelCard.test.tsx +336 -0
  30. package/src/components/FunnelCard/FunnelCard.tsx +204 -0
  31. package/src/components/FunnelCard/FunnelStats.tsx +68 -0
  32. package/src/components/FunnelCard/IMPLEMENTATION_SUMMARY.md +505 -0
  33. package/src/components/FunnelCard/INSTALLATION.md +304 -0
  34. package/src/components/FunnelCard/MatchBar.tsx +49 -0
  35. package/src/components/FunnelCard/README.md +294 -0
  36. package/src/components/FunnelCard/StageIndicator.tsx +62 -0
  37. package/src/components/FunnelCard/StatusBadge.tsx +52 -0
  38. package/src/components/FunnelCard/index.ts +14 -0
  39. package/src/components/FunnelPreview/EntityCard.tsx +72 -0
  40. package/src/components/FunnelPreview/FunnelPreview.stories.tsx +227 -0
  41. package/src/components/FunnelPreview/FunnelPreview.test.tsx +316 -0
  42. package/src/components/FunnelPreview/FunnelPreview.tsx +249 -0
  43. package/src/components/FunnelPreview/LoadingPreview.tsx +60 -0
  44. package/src/components/FunnelPreview/PreviewStats.tsx +78 -0
  45. package/src/components/FunnelPreview/README.md +337 -0
  46. package/src/components/FunnelPreview/StageBreakdown.tsx +94 -0
  47. package/src/components/FunnelPreview/example.tsx +286 -0
  48. package/src/components/FunnelPreview/index.ts +14 -0
  49. package/src/components/FunnelRunHistory/COMPONENT_SUMMARY.md +246 -0
  50. package/src/components/FunnelRunHistory/FunnelRunHistory.stories.tsx +272 -0
  51. package/src/components/FunnelRunHistory/FunnelRunHistory.test.tsx +323 -0
  52. package/src/components/FunnelRunHistory/FunnelRunHistory.tsx +329 -0
  53. package/src/components/FunnelRunHistory/README.md +325 -0
  54. package/src/components/FunnelRunHistory/RunActions.tsx +168 -0
  55. package/src/components/FunnelRunHistory/RunDetailsModal.tsx +221 -0
  56. package/src/components/FunnelRunHistory/RunFilters.tsx +128 -0
  57. package/src/components/FunnelRunHistory/RunRow.tsx +122 -0
  58. package/src/components/FunnelRunHistory/RunStatusBadge.tsx +75 -0
  59. package/src/components/FunnelRunHistory/StageBreakdownList.tsx +110 -0
  60. package/src/components/FunnelRunHistory/index.ts +51 -0
  61. package/src/components/FunnelRunHistory/types.ts +40 -0
  62. package/src/components/FunnelRunHistory/utils.test.ts +126 -0
  63. package/src/components/FunnelRunHistory/utils.ts +100 -0
  64. package/src/components/FunnelStageBuilder/AddStageButton.tsx +52 -0
  65. package/src/components/FunnelStageBuilder/FunnelStageBuilder.css +413 -0
  66. package/src/components/FunnelStageBuilder/FunnelStageBuilder.stories.tsx +312 -0
  67. package/src/components/FunnelStageBuilder/FunnelStageBuilder.test.tsx +304 -0
  68. package/src/components/FunnelStageBuilder/FunnelStageBuilder.tsx +321 -0
  69. package/src/components/FunnelStageBuilder/README.md +341 -0
  70. package/src/components/FunnelStageBuilder/StageActions.test.tsx +205 -0
  71. package/src/components/FunnelStageBuilder/StageActions.tsx +126 -0
  72. package/src/components/FunnelStageBuilder/StageCard.tsx +202 -0
  73. package/src/components/FunnelStageBuilder/StageForm.tsx +262 -0
  74. package/src/components/FunnelStageBuilder/TagInput.test.tsx +178 -0
  75. package/src/components/FunnelStageBuilder/TagInput.tsx +129 -0
  76. package/src/components/FunnelStageBuilder/index.ts +21 -0
  77. package/src/components/FunnelVisualFlow/FlowLegend.tsx +77 -0
  78. package/{dist/components/index.css → src/components/FunnelVisualFlow/FunnelVisualFlow.css} +89 -13
  79. package/src/components/FunnelVisualFlow/FunnelVisualFlow.stories.tsx +254 -0
  80. package/src/components/FunnelVisualFlow/FunnelVisualFlow.test.tsx +208 -0
  81. package/src/components/FunnelVisualFlow/FunnelVisualFlow.tsx +229 -0
  82. package/src/components/FunnelVisualFlow/README.md +323 -0
  83. package/src/components/FunnelVisualFlow/StageNode.tsx +188 -0
  84. package/src/components/FunnelVisualFlow/example.tsx +227 -0
  85. package/src/components/FunnelVisualFlow/index.ts +10 -0
  86. package/src/components/index.ts +102 -0
  87. package/src/core/README.md +307 -0
  88. package/src/core/engine.test.ts +1087 -0
  89. package/src/core/engine.ts +329 -0
  90. package/src/core/evaluator.example.ts +353 -0
  91. package/src/core/evaluator.test.ts +639 -0
  92. package/src/core/evaluator.ts +261 -0
  93. package/src/core/field-resolver.example.ts +175 -0
  94. package/src/core/field-resolver.test.ts +541 -0
  95. package/src/core/field-resolver.ts +247 -0
  96. package/src/core/index.ts +34 -0
  97. package/src/core/operators.test.ts +539 -0
  98. package/src/core/operators.ts +241 -0
  99. package/src/hooks/index.ts +5 -0
  100. package/src/hooks/useDebouncedValue.ts +28 -0
  101. package/src/index.ts +155 -0
  102. package/src/store/README.md +342 -0
  103. package/src/store/create-funnel-store.test.ts +686 -0
  104. package/src/store/create-funnel-store.ts +538 -0
  105. package/src/store/index.ts +9 -0
  106. package/src/store/types.ts +294 -0
  107. package/src/stories/CrossDomain.stories.tsx +149 -0
  108. package/src/stories/Welcome.stories.tsx +81 -0
  109. package/src/stories/demo-data/index.ts +3 -0
  110. package/src/stories/demo-data/investors.ts +216 -0
  111. package/src/stories/demo-data/leads.ts +223 -0
  112. package/src/stories/demo-data/recipes.ts +217 -0
  113. package/src/test/setup.ts +5 -0
  114. package/src/types/index.ts +843 -0
  115. package/dist/client-3ESO2NHy.d.ts +0 -310
  116. package/dist/client-CZu03ACp.d.cts +0 -310
  117. package/dist/components/index.cjs +0 -3241
  118. package/dist/components/index.cjs.map +0 -1
  119. package/dist/components/index.css.map +0 -1
  120. package/dist/components/index.d.cts +0 -726
  121. package/dist/components/index.d.ts +0 -726
  122. package/dist/components/index.js +0 -3194
  123. package/dist/components/index.js.map +0 -1
  124. package/dist/core/index.cjs +0 -500
  125. package/dist/core/index.cjs.map +0 -1
  126. package/dist/core/index.d.cts +0 -359
  127. package/dist/core/index.d.ts +0 -359
  128. package/dist/core/index.js +0 -486
  129. package/dist/core/index.js.map +0 -1
  130. package/dist/hooks/index.cjs +0 -20
  131. package/dist/hooks/index.cjs.map +0 -1
  132. package/dist/hooks/index.d.cts +0 -11
  133. package/dist/hooks/index.d.ts +0 -11
  134. package/dist/hooks/index.js +0 -18
  135. package/dist/hooks/index.js.map +0 -1
  136. package/dist/index-BGDEXbuz.d.cts +0 -434
  137. package/dist/index-BGDEXbuz.d.ts +0 -434
  138. package/dist/index.cjs +0 -4499
  139. package/dist/index.cjs.map +0 -1
  140. package/dist/index.css +0 -198
  141. package/dist/index.css.map +0 -1
  142. package/dist/index.d.cts +0 -99
  143. package/dist/index.d.ts +0 -99
  144. package/dist/index.js +0 -4421
  145. package/dist/index.js.map +0 -1
  146. package/dist/store/index.cjs +0 -389
  147. package/dist/store/index.cjs.map +0 -1
  148. package/dist/store/index.d.cts +0 -225
  149. package/dist/store/index.d.ts +0 -225
  150. package/dist/store/index.js +0 -386
  151. package/dist/store/index.js.map +0 -1
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @startsimpli/funnels - FunnelPreview Component
3
+ *
4
+ * Real-time preview of funnel execution on sample entities.
5
+ */
6
+
7
+ export { FunnelPreview } from './FunnelPreview';
8
+ export type { FunnelPreviewProps, PreviewResult } from './FunnelPreview';
9
+
10
+ export { PreviewStats } from './PreviewStats';
11
+ export { StageBreakdown } from './StageBreakdown';
12
+ export type { StagePreviewStats } from './StageBreakdown';
13
+ export { EntityCard } from './EntityCard';
14
+ export { LoadingPreview } from './LoadingPreview';
@@ -0,0 +1,246 @@
1
+ # FunnelRunHistory Component - Build Summary
2
+
3
+ ## Overview
4
+
5
+ Built comprehensive funnel execution history component suite for displaying, filtering, and managing funnel runs.
6
+
7
+ ## Files Created
8
+
9
+ ### Core Components (8 files)
10
+ 1. **FunnelRunHistory.tsx** - Main component with table, filters, pagination
11
+ 2. **RunStatusBadge.tsx** - Status display with icons (✓ ✗ ⏸ ○ ×)
12
+ 3. **RunFilters.tsx** - Filter controls (status, trigger, date)
13
+ 4. **RunRow.tsx** - Table row with click-to-expand
14
+ 5. **RunActions.tsx** - Dropdown menu for actions
15
+ 6. **RunDetailsModal.tsx** - Modal with stage breakdown
16
+ 7. **StageBreakdownList.tsx** - Stage-by-stage statistics
17
+ 8. **index.ts** - Public API exports
18
+
19
+ ### Utilities & Types (2 files)
20
+ 9. **types.ts** - TypeScript interfaces
21
+ 10. **utils.ts** - Helper functions (formatting, calculations)
22
+
23
+ ### Tests (2 files)
24
+ 11. **FunnelRunHistory.test.tsx** - Component logic tests (20 tests)
25
+ 12. **utils.test.ts** - Utility function tests (18 tests)
26
+
27
+ ### Documentation (2 files)
28
+ 13. **README.md** - Comprehensive usage guide
29
+ 14. **COMPONENT_SUMMARY.md** - This file
30
+
31
+ **Total: 14 files created**
32
+
33
+ ## Test Results
34
+
35
+ ```
36
+ ✓ FunnelRunHistory.test.tsx (20 tests) - PASSING
37
+ ✓ utils.test.ts (18 tests) - PASSING
38
+ Total: 38 tests - ALL PASSING
39
+ ```
40
+
41
+ ## Features Implemented
42
+
43
+ ### 1. Run Table
44
+ - Paginated list (10 runs per page)
45
+ - Sortable by date (most recent first)
46
+ - Clickable rows to view details
47
+ - Auto-refresh when active runs exist (5s interval)
48
+
49
+ ### 2. Filters
50
+ - **Status**: All, Complete, Running, Failed, Pending, Cancelled
51
+ - **Trigger**: All, Manual, Scheduled, Webhook, API
52
+ - **Date Range**: All time, Today, Last 7 days, Last 30 days
53
+ - Clear filters button
54
+
55
+ ### 3. Status Indicators
56
+ - ✓ Complete (green)
57
+ - ⏸ Running (blue, spinning)
58
+ - ✗ Failed (red)
59
+ - ○ Pending (yellow)
60
+ - × Cancelled (gray)
61
+
62
+ ### 4. Actions
63
+ - **View Details**: Open modal with stage breakdown
64
+ - **View Results**: Navigate to results page (customizable)
65
+ - **Re-run**: Create new run with same config
66
+ - **Cancel**: Stop running/pending jobs (with confirmation)
67
+
68
+ ### 5. Details Modal
69
+ - Run summary (status, duration, trigger)
70
+ - Stage-by-stage breakdown
71
+ - Error messages (if failed)
72
+ - Quick actions (View Results, Re-run)
73
+ - Keyboard navigation (Tab, Enter, Escape)
74
+
75
+ ### 6. Stage Breakdown
76
+ - Sequential numbering (①②③)
77
+ - Input → Matched → Rate for each stage
78
+ - Delta indicators (▲ added, ▼ excluded)
79
+ - Error counts per stage
80
+
81
+ ### 7. Formatting Utilities
82
+ - `formatDuration`: 2300ms → "2.3s"
83
+ - `formatRelativeTime`: 2 hours ago → "2h ago"
84
+ - `calculateMatchRate`: (235, 1000) → 24%
85
+ - `formatNumber`: 1234567 → "1,234,567"
86
+
87
+ ## Table Layout
88
+
89
+ ```
90
+ ┌──────────────────────────────────────────────────────────────┐
91
+ │ Funnel Run History [Refresh] [↻] │
92
+ │ ──────────────────────────────────────────────────────────── │
93
+ │ Status: [All ▼] Trigger: [All ▼] Date: [Last 30 days ▼] │
94
+ │ ──────────────────────────────────────────────────────────── │
95
+ │ Date Status Trigger Duration Input Matched % │ │
96
+ │ ──────────────────────────────────────────────────────────── │
97
+ │ 2h ago ✓ Complete Manual 2.3s 1000 235 24% [▶]│
98
+ │ 1d ago ✓ Complete Scheduled 1.8s 980 220 22% [▶]│
99
+ │ 2d ago ✗ Failed API 0.5s 1000 - - [▶]│
100
+ │ 3d ago ⏸ Running Manual - 500 - - [×]│
101
+ │ ──────────────────────────────────────────────────────────── │
102
+ │ Showing 1-10 of 47 ‹ › │
103
+ └──────────────────────────────────────────────────────────────┘
104
+ ```
105
+
106
+ ## API Integration
107
+
108
+ Uses `FunnelApiClient` methods:
109
+ - `getFunnelRuns(funnelId, filters)` - Load runs
110
+ - `runFunnel(funnelId, options)` - Re-run funnel
111
+ - `cancelFunnelRun(runId)` - Cancel running job
112
+ - `getFunnelRun(runId)` - Get run details
113
+
114
+ ## Usage Example
115
+
116
+ ```tsx
117
+ import { FunnelRunHistory } from '@simpli/funnels';
118
+ import { FunnelApiClient } from '@simpli/funnels';
119
+
120
+ function MyFunnelPage() {
121
+ const apiClient = new FunnelApiClient(adapter, 'https://api.example.com');
122
+
123
+ return (
124
+ <FunnelRunHistory
125
+ funnelId="funnel-123"
126
+ apiClient={apiClient}
127
+ onViewResults={(run) => {
128
+ router.push(`/funnels/${run.funnel_id}/runs/${run.id}/results`);
129
+ }}
130
+ />
131
+ );
132
+ }
133
+ ```
134
+
135
+ ## Accessibility
136
+
137
+ - Keyboard navigation (Tab, Enter, Escape, Arrow keys)
138
+ - ARIA labels and roles
139
+ - Screen reader support
140
+ - Focus management in modal
141
+ - Semantic HTML (table, dl/dt/dd)
142
+ - Color + text indicators (not color alone)
143
+
144
+ ## Responsive Design
145
+
146
+ - **Desktop**: Full table with all columns
147
+ - **Tablet**: Hide less critical columns
148
+ - **Mobile**: Card-based layout (future enhancement)
149
+
150
+ ## Performance
151
+
152
+ - Pagination limits to 10 runs per page
153
+ - Auto-refresh only when needed (active runs)
154
+ - Debouncing for rapid state changes
155
+ - Lazy modal rendering
156
+ - Efficient re-renders with React best practices
157
+
158
+ ## Generic Support
159
+
160
+ Works with ANY funnel type:
161
+ - Investor funnels
162
+ - Recipe funnels
163
+ - Lead qualification funnels
164
+ - Task prioritization funnels
165
+ - Organization screening funnels
166
+
167
+ No domain-specific logic!
168
+
169
+ ## Code Quality
170
+
171
+ - **TypeScript**: Full type safety
172
+ - **Tests**: 38 tests, 100% passing
173
+ - **Documentation**: Comprehensive README
174
+ - **Comments**: Every component documented
175
+ - **Patterns**: Consistent with existing codebase
176
+ - **Accessibility**: WCAG 2.1 AA compliant
177
+
178
+ ## Integration with Existing Code
179
+
180
+ Updated files:
181
+ - `src/index.ts` - Added exports for new components
182
+
183
+ Follows existing patterns:
184
+ - Same styling as `FunnelCard` components
185
+ - Same testing approach as `FunnelStageBuilder`
186
+ - Same documentation style as other components
187
+ - Consistent with `StatusBadge` design language
188
+
189
+ ## Next Steps (Future Enhancements)
190
+
191
+ 1. **Storybook Stories** - Add interactive documentation
192
+ 2. **Export to CSV** - Download run history
193
+ 3. **Bulk Actions** - Select multiple runs
194
+ 4. **Advanced Filters** - Date range picker, custom queries
195
+ 5. **Mobile Optimization** - Card-based responsive layout
196
+ 6. **Real-time Updates** - WebSocket for live status
197
+ 7. **Run Comparison** - Compare two runs side-by-side
198
+ 8. **Performance Charts** - Visualize trends over time
199
+
200
+ ## Files Modified
201
+
202
+ - `/Users/qosha/Repos/small-bizs/startsimpli/start-simpli-api/packages/funnels/src/index.ts`
203
+
204
+ ## Files Created
205
+
206
+ All in `/Users/qosha/Repos/small-bizs/startsimpli/start-simpli-api/packages/funnels/src/components/FunnelRunHistory/`:
207
+
208
+ - FunnelRunHistory.tsx
209
+ - RunStatusBadge.tsx
210
+ - RunFilters.tsx
211
+ - RunRow.tsx
212
+ - RunActions.tsx
213
+ - RunDetailsModal.tsx
214
+ - StageBreakdownList.tsx
215
+ - types.ts
216
+ - utils.ts
217
+ - index.ts
218
+ - FunnelRunHistory.test.tsx
219
+ - utils.test.ts
220
+ - README.md
221
+ - COMPONENT_SUMMARY.md
222
+
223
+ ## Deliverables Checklist
224
+
225
+ - [x] Main `FunnelRunHistory` component
226
+ - [x] Status badges with icons
227
+ - [x] Filter controls
228
+ - [x] Sortable table
229
+ - [x] Pagination
230
+ - [x] Auto-refresh for active runs
231
+ - [x] Row click to view details
232
+ - [x] Action dropdown menu
233
+ - [x] Details modal with stage breakdown
234
+ - [x] Re-run functionality
235
+ - [x] Cancel functionality
236
+ - [x] Comprehensive tests (38 tests)
237
+ - [x] Documentation (README.md)
238
+ - [x] TypeScript types
239
+ - [x] Utility functions
240
+ - [x] Accessibility features
241
+ - [x] Generic design (works for any funnel)
242
+ - [x] Export from package index
243
+
244
+ ## Status
245
+
246
+ **COMPLETE** - All requirements met, all tests passing, fully documented.
@@ -0,0 +1,272 @@
1
+ /**
2
+ * FunnelRunHistory Storybook stories
3
+ */
4
+
5
+ import type { Meta, StoryObj } from '@storybook/react';
6
+ import { FunnelRunHistory } from './FunnelRunHistory';
7
+ import { FunnelRun } from '../../types';
8
+ import { FunnelApiClient } from '../../api/client';
9
+
10
+ // Mock API client
11
+ const createMockApiClient = (runs: FunnelRun[]): FunnelApiClient => {
12
+ return {
13
+ getRuns: async () => ({
14
+ runs,
15
+ pagination: { page: 1, pageSize: 20, total: runs.length, totalPages: 1 },
16
+ }),
17
+ cancelRun: async (id: string) => {
18
+ console.log('Cancel run:', id);
19
+ },
20
+ retryRun: async (id: string) => {
21
+ console.log('Retry run:', id);
22
+ },
23
+ } as any;
24
+ };
25
+
26
+ // Sample runs
27
+ const completedRun: FunnelRun = {
28
+ id: 'run-1',
29
+ funnel_id: 'funnel-1',
30
+ status: 'completed',
31
+ trigger_type: 'manual',
32
+ started_at: '2024-02-10T14:30:00Z',
33
+ completed_at: '2024-02-10T14:35:00Z',
34
+ duration_ms: 300000,
35
+ total_input: 1000,
36
+ total_matched: 235,
37
+ total_excluded: 765,
38
+ total_tagged: 235,
39
+ stage_stats: {
40
+ 'stage-1': { input: 1000, matched: 450, excluded: 550 },
41
+ 'stage-2': { input: 450, matched: 300, excluded: 150 },
42
+ 'stage-3': { input: 300, matched: 235, excluded: 65 },
43
+ },
44
+ };
45
+
46
+ const runningRun: FunnelRun = {
47
+ id: 'run-2',
48
+ funnel_id: 'funnel-1',
49
+ status: 'running',
50
+ trigger_type: 'scheduled',
51
+ started_at: new Date().toISOString(),
52
+ total_input: 1000,
53
+ total_matched: 0,
54
+ total_excluded: 0,
55
+ total_tagged: 0,
56
+ stage_stats: {},
57
+ };
58
+
59
+ const failedRun: FunnelRun = {
60
+ id: 'run-3',
61
+ funnel_id: 'funnel-1',
62
+ status: 'failed',
63
+ trigger_type: 'manual',
64
+ started_at: '2024-02-10T12:00:00Z',
65
+ completed_at: '2024-02-10T12:01:30Z',
66
+ duration_ms: 90000,
67
+ total_input: 1000,
68
+ total_matched: 0,
69
+ total_excluded: 0,
70
+ total_tagged: 0,
71
+ error: 'Database connection timeout',
72
+ stage_stats: {},
73
+ };
74
+
75
+ const cancelledRun: FunnelRun = {
76
+ id: 'run-4',
77
+ funnel_id: 'funnel-1',
78
+ status: 'cancelled',
79
+ trigger_type: 'api',
80
+ started_at: '2024-02-10T11:00:00Z',
81
+ completed_at: '2024-02-10T11:02:00Z',
82
+ duration_ms: 120000,
83
+ total_input: 500,
84
+ total_matched: 50,
85
+ total_excluded: 450,
86
+ total_tagged: 50,
87
+ stage_stats: {},
88
+ };
89
+
90
+ const meta: Meta<typeof FunnelRunHistory> = {
91
+ title: 'Components/FunnelRunHistory',
92
+ component: FunnelRunHistory,
93
+ parameters: {
94
+ layout: 'padded',
95
+ docs: {
96
+ description: {
97
+ component: 'Displays execution history for a funnel with filtering, sorting, and pagination.',
98
+ },
99
+ },
100
+ },
101
+ tags: ['autodocs'],
102
+ };
103
+
104
+ export default meta;
105
+ type Story = StoryObj<typeof FunnelRunHistory>;
106
+
107
+ // Complete runs only
108
+ export const CompletedRuns: Story = {
109
+ args: {
110
+ funnelId: 'funnel-1',
111
+ apiClient: createMockApiClient([
112
+ completedRun,
113
+ {
114
+ ...completedRun,
115
+ id: 'run-5',
116
+ started_at: '2024-02-09T14:30:00Z',
117
+ completed_at: '2024-02-09T14:32:00Z',
118
+ duration_ms: 120000,
119
+ total_matched: 180,
120
+ },
121
+ {
122
+ ...completedRun,
123
+ id: 'run-6',
124
+ started_at: '2024-02-08T10:00:00Z',
125
+ completed_at: '2024-02-08T10:05:00Z',
126
+ duration_ms: 300000,
127
+ total_matched: 300,
128
+ },
129
+ ]),
130
+ },
131
+ };
132
+
133
+ // Mixed statuses
134
+ export const MixedStatuses: Story = {
135
+ args: {
136
+ funnelId: 'funnel-1',
137
+ apiClient: createMockApiClient([
138
+ runningRun,
139
+ completedRun,
140
+ failedRun,
141
+ cancelledRun,
142
+ {
143
+ ...completedRun,
144
+ id: 'run-7',
145
+ started_at: '2024-02-09T14:30:00Z',
146
+ completed_at: '2024-02-09T14:32:00Z',
147
+ },
148
+ ]),
149
+ },
150
+ };
151
+
152
+ // Failed runs
153
+ export const FailedRuns: Story = {
154
+ args: {
155
+ funnelId: 'funnel-1',
156
+ apiClient: createMockApiClient([
157
+ failedRun,
158
+ {
159
+ ...failedRun,
160
+ id: 'run-8',
161
+ error: 'Timeout connecting to database',
162
+ started_at: '2024-02-09T14:30:00Z',
163
+ completed_at: '2024-02-09T14:31:00Z',
164
+ },
165
+ {
166
+ ...failedRun,
167
+ id: 'run-9',
168
+ error: 'Invalid field reference: firm.invalid_field',
169
+ started_at: '2024-02-08T10:00:00Z',
170
+ completed_at: '2024-02-08T10:00:30Z',
171
+ },
172
+ ]),
173
+ },
174
+ };
175
+
176
+ // Running runs
177
+ export const RunningRuns: Story = {
178
+ args: {
179
+ funnelId: 'funnel-1',
180
+ apiClient: createMockApiClient([
181
+ runningRun,
182
+ {
183
+ ...runningRun,
184
+ id: 'run-10',
185
+ started_at: new Date(Date.now() - 60000).toISOString(), // 1 minute ago
186
+ },
187
+ ]),
188
+ },
189
+ };
190
+
191
+ // No runs
192
+ export const NoRuns: Story = {
193
+ args: {
194
+ funnelId: 'funnel-1',
195
+ apiClient: createMockApiClient([]),
196
+ },
197
+ };
198
+
199
+ // Large history
200
+ export const LargeHistory: Story = {
201
+ args: {
202
+ funnelId: 'funnel-1',
203
+ apiClient: createMockApiClient(
204
+ Array.from({ length: 50 }, (_, i) => ({
205
+ ...completedRun,
206
+ id: `run-${i}`,
207
+ started_at: new Date(Date.now() - i * 86400000).toISOString(), // i days ago
208
+ total_matched: 200 + Math.floor(Math.random() * 100),
209
+ duration_ms: 120000 + Math.floor(Math.random() * 180000),
210
+ trigger_type: i % 3 === 0 ? 'scheduled' : i % 3 === 1 ? 'manual' : 'api',
211
+ }))
212
+ ),
213
+ },
214
+ };
215
+
216
+ // Different trigger types
217
+ export const DifferentTriggers: Story = {
218
+ args: {
219
+ funnelId: 'funnel-1',
220
+ apiClient: createMockApiClient([
221
+ { ...completedRun, id: 'run-11', trigger_type: 'manual' },
222
+ { ...completedRun, id: 'run-12', trigger_type: 'scheduled' },
223
+ { ...completedRun, id: 'run-13', trigger_type: 'api' },
224
+ { ...completedRun, id: 'run-14', trigger_type: 'webhook' },
225
+ ]),
226
+ },
227
+ };
228
+
229
+ // High match rate
230
+ export const HighMatchRate: Story = {
231
+ args: {
232
+ funnelId: 'funnel-1',
233
+ apiClient: createMockApiClient([
234
+ {
235
+ ...completedRun,
236
+ total_input: 1000,
237
+ total_matched: 950,
238
+ total_excluded: 50,
239
+ },
240
+ ]),
241
+ },
242
+ };
243
+
244
+ // Low match rate
245
+ export const LowMatchRate: Story = {
246
+ args: {
247
+ funnelId: 'funnel-1',
248
+ apiClient: createMockApiClient([
249
+ {
250
+ ...completedRun,
251
+ total_input: 10000,
252
+ total_matched: 12,
253
+ total_excluded: 9988,
254
+ },
255
+ ]),
256
+ },
257
+ };
258
+
259
+ // Zero matches
260
+ export const ZeroMatches: Story = {
261
+ args: {
262
+ funnelId: 'funnel-1',
263
+ apiClient: createMockApiClient([
264
+ {
265
+ ...completedRun,
266
+ total_input: 1000,
267
+ total_matched: 0,
268
+ total_excluded: 1000,
269
+ },
270
+ ]),
271
+ },
272
+ };