yadflow 2.6.0 → 2.7.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.
Files changed (102) hide show
  1. package/CHANGELOG.md +4 -7
  2. package/README.md +23 -2
  3. package/bin/yad.mjs +22 -1
  4. package/cli/docs.mjs +298 -0
  5. package/cli/manifest.mjs +6 -1
  6. package/docs/index.html +4 -4
  7. package/package.json +2 -2
  8. package/skills/sdlc/config.yaml +19 -0
  9. package/skills/sdlc/install.sh +1 -1
  10. package/skills/sdlc/module-help.csv +4 -0
  11. package/skills/yad-connect-docs/SKILL.md +132 -0
  12. package/skills/yad-connect-docs/references/docs-registry.md +74 -0
  13. package/skills/yad-docs/SKILL.md +159 -0
  14. package/skills/yad-docs/references/data-mapping.md +75 -0
  15. package/skills/yad-docs/references/theme-map.md +69 -0
  16. package/skills/yad-docs/templates/app/README.md +31 -0
  17. package/skills/yad-docs/templates/app/eslint.config.js +23 -0
  18. package/skills/yad-docs/templates/app/index.html +17 -0
  19. package/skills/yad-docs/templates/app/package-lock.json +4030 -0
  20. package/skills/yad-docs/templates/app/package.json +35 -0
  21. package/skills/yad-docs/templates/app/public/favicon.svg +28 -0
  22. package/skills/yad-docs/templates/app/public/logo.svg +39 -0
  23. package/skills/yad-docs/templates/app/public/vite.svg +1 -0
  24. package/skills/yad-docs/templates/app/src/App.tsx +98 -0
  25. package/skills/yad-docs/templates/app/src/components/Auth/LoginPage.tsx +101 -0
  26. package/skills/yad-docs/templates/app/src/components/Canvas/AnimatedMessage.tsx +101 -0
  27. package/skills/yad-docs/templates/app/src/components/Canvas/ConnectionLine.tsx +90 -0
  28. package/skills/yad-docs/templates/app/src/components/Canvas/FlowCanvas.tsx +216 -0
  29. package/skills/yad-docs/templates/app/src/components/Canvas/SystemComponent.tsx +153 -0
  30. package/skills/yad-docs/templates/app/src/components/Controls/PlaybackBar.tsx +284 -0
  31. package/skills/yad-docs/templates/app/src/components/Controls/StepDetail.tsx +167 -0
  32. package/skills/yad-docs/templates/app/src/components/DetailPanel/HandlerLogicSnippet.tsx +41 -0
  33. package/skills/yad-docs/templates/app/src/components/DetailPanel/RequestPayloadPreview.tsx +46 -0
  34. package/skills/yad-docs/templates/app/src/components/DetailPanel/RightPanel.tsx +88 -0
  35. package/skills/yad-docs/templates/app/src/components/DetailPanel/StatusCard.tsx +76 -0
  36. package/skills/yad-docs/templates/app/src/components/DetailPanel/TriggerEventCard.tsx +45 -0
  37. package/skills/yad-docs/templates/app/src/components/DocLayout/DocPageShell.tsx +80 -0
  38. package/skills/yad-docs/templates/app/src/components/DocLayout/DocSectionCard.tsx +55 -0
  39. package/skills/yad-docs/templates/app/src/components/DocLayout/DocTableOfContents.tsx +79 -0
  40. package/skills/yad-docs/templates/app/src/components/DocLayout/RoleCard.tsx +67 -0
  41. package/skills/yad-docs/templates/app/src/components/DocSections/ApiReferenceSection.tsx +108 -0
  42. package/skills/yad-docs/templates/app/src/components/DocSections/CancelabilitySection.tsx +73 -0
  43. package/skills/yad-docs/templates/app/src/components/DocSections/CriticalRunbookSection.tsx +177 -0
  44. package/skills/yad-docs/templates/app/src/components/DocSections/DataMigrationSection.tsx +102 -0
  45. package/skills/yad-docs/templates/app/src/components/DocSections/DbSchemaSection.tsx +98 -0
  46. package/skills/yad-docs/templates/app/src/components/DocSections/DeploymentGuideSection.tsx +104 -0
  47. package/skills/yad-docs/templates/app/src/components/DocSections/DriverIntegrationSection.tsx +127 -0
  48. package/skills/yad-docs/templates/app/src/components/DocSections/ExecutiveSummarySection.tsx +69 -0
  49. package/skills/yad-docs/templates/app/src/components/DocSections/FlowOverviewSection.tsx +73 -0
  50. package/skills/yad-docs/templates/app/src/components/DocSections/FlowPathsChecklistSection.tsx +96 -0
  51. package/skills/yad-docs/templates/app/src/components/DocSections/MiddlewareChainSection.tsx +107 -0
  52. package/skills/yad-docs/templates/app/src/components/DocSections/MonitoringAlertingSection.tsx +106 -0
  53. package/skills/yad-docs/templates/app/src/components/DocSections/NotificationLocalizationSection.tsx +102 -0
  54. package/skills/yad-docs/templates/app/src/components/DocSections/PMRoadmapSection.tsx +133 -0
  55. package/skills/yad-docs/templates/app/src/components/DocSections/PerformanceTestingSection.tsx +91 -0
  56. package/skills/yad-docs/templates/app/src/components/DocSections/RiderIntegrationSection.tsx +99 -0
  57. package/skills/yad-docs/templates/app/src/components/DocSections/SecuritySection.tsx +74 -0
  58. package/skills/yad-docs/templates/app/src/components/DocSections/StatusMachineSection.tsx +90 -0
  59. package/skills/yad-docs/templates/app/src/components/DocSections/TestPlanSection.tsx +163 -0
  60. package/skills/yad-docs/templates/app/src/components/Logs/SystemLogsTerminal.tsx +126 -0
  61. package/skills/yad-docs/templates/app/src/components/Navigation/TopNavBar.tsx +90 -0
  62. package/skills/yad-docs/templates/app/src/components/Reference/BullMQJobsList.tsx +60 -0
  63. package/skills/yad-docs/templates/app/src/components/Reference/DecisionTreeView.tsx +49 -0
  64. package/skills/yad-docs/templates/app/src/components/Reference/DeeplinkActionsChips.tsx +69 -0
  65. package/skills/yad-docs/templates/app/src/components/Reference/DriverUIStatesTable.tsx +61 -0
  66. package/skills/yad-docs/templates/app/src/components/Reference/FeatureFlagMatrix.tsx +73 -0
  67. package/skills/yad-docs/templates/app/src/components/Reference/RiderUIStatesTable.tsx +61 -0
  68. package/skills/yad-docs/templates/app/src/components/Reference/RulesLegendPanel.tsx +217 -0
  69. package/skills/yad-docs/templates/app/src/components/Reference/StakeholderToggle.tsx +41 -0
  70. package/skills/yad-docs/templates/app/src/components/Reference/TroubleshootingSection.tsx +93 -0
  71. package/skills/yad-docs/templates/app/src/components/Sidebar/PathSelector.tsx +148 -0
  72. package/skills/yad-docs/templates/app/src/components/Sidebar/SidebarFooter.tsx +40 -0
  73. package/skills/yad-docs/templates/app/src/components/Sidebar/StepList.tsx +234 -0
  74. package/skills/yad-docs/templates/app/src/components/shared/Badge.tsx +28 -0
  75. package/skills/yad-docs/templates/app/src/components/shared/CommandPalette.tsx +213 -0
  76. package/skills/yad-docs/templates/app/src/components/shared/Icon.tsx +21 -0
  77. package/skills/yad-docs/templates/app/src/components/shared/Tooltip.tsx +42 -0
  78. package/skills/yad-docs/templates/app/src/data/components.ts +74 -0
  79. package/skills/yad-docs/templates/app/src/data/docSections.ts +231 -0
  80. package/skills/yad-docs/templates/app/src/data/paths.ts +2319 -0
  81. package/skills/yad-docs/templates/app/src/data/referenceData.ts +392 -0
  82. package/skills/yad-docs/templates/app/src/data/roles.ts +145 -0
  83. package/skills/yad-docs/templates/app/src/data/types.ts +79 -0
  84. package/skills/yad-docs/templates/app/src/hooks/useAnimationQueue.ts +41 -0
  85. package/skills/yad-docs/templates/app/src/hooks/usePlayback.ts +100 -0
  86. package/skills/yad-docs/templates/app/src/hooks/useStakeholderFilter.ts +10 -0
  87. package/skills/yad-docs/templates/app/src/index.css +121 -0
  88. package/skills/yad-docs/templates/app/src/main.tsx +13 -0
  89. package/skills/yad-docs/templates/app/src/pages/RoleSelectPage.tsx +34 -0
  90. package/skills/yad-docs/templates/app/src/pages/StakeholderDocPage.tsx +98 -0
  91. package/skills/yad-docs/templates/app/src/pages/SubPathDetailPage.tsx +282 -0
  92. package/skills/yad-docs/templates/app/src/store/useAuthStore.ts +42 -0
  93. package/skills/yad-docs/templates/app/src/store/useFlowStore.ts +197 -0
  94. package/skills/yad-docs/templates/app/src/utils/iconMap.ts +46 -0
  95. package/skills/yad-docs/templates/app/tsconfig.app.json +28 -0
  96. package/skills/yad-docs/templates/app/tsconfig.json +7 -0
  97. package/skills/yad-docs/templates/app/tsconfig.node.json +26 -0
  98. package/skills/yad-docs/templates/app/vite.config.ts +10 -0
  99. package/skills/yad-docs-overview/SKILL.md +129 -0
  100. package/skills/yad-docs-overview/references/pipeline-model.md +102 -0
  101. package/skills/yad-docs-sync/SKILL.md +99 -0
  102. package/skills/yad-docs-sync/references/staleness.md +81 -0
@@ -0,0 +1,104 @@
1
+ import { Icon } from '../shared/Icon';
2
+
3
+ const ENV_CONFIGS = [
4
+ { env: 'Staging', flags: { ENABLE_BOOKING_JOBS: true, ENABLE_PRE_TRIP_RIDER_CONFIRMATION: true, ENABLE_DRIVER_CONFIRMATION: false }, color: '#f59e0b' },
5
+ { env: 'Production', flags: { ENABLE_BOOKING_JOBS: false, ENABLE_PRE_TRIP_RIDER_CONFIRMATION: false, ENABLE_DRIVER_CONFIRMATION: false }, color: '#ef4444' },
6
+ ];
7
+
8
+ const ROLLOUT_STEPS = [
9
+ { step: 'Deploy backend with all flags OFF', detail: 'Code ships but nothing executes — zero risk' },
10
+ { step: 'Enable ENABLE_BOOKING_JOBS in staging', detail: 'Master switch: allows BullMQ job scheduling' },
11
+ { step: 'Enable ENABLE_PRE_TRIP_RIDER_CONFIRMATION in staging', detail: 'Enables the 24h-before-trip rider confirmation flow' },
12
+ { step: 'QA validates all 11 flow paths in staging', detail: 'Full regression: happy path, cancellations, timeouts' },
13
+ { step: 'Enable ENABLE_BOOKING_JOBS in production', detail: 'Production rollout — monitor BullMQ dashboard and error rates' },
14
+ { step: 'Enable ENABLE_PRE_TRIP_RIDER_CONFIRMATION in production', detail: 'Rider confirmation goes live — monitor notification delivery' },
15
+ { step: 'Enable ENABLE_DRIVER_CONFIRMATION when ready', detail: 'Last phase: driver confirmation flow (currently false everywhere)' },
16
+ ];
17
+
18
+ const ROLLBACK = [
19
+ 'Set ENABLE_BOOKING_JOBS=false to disable all job scheduling immediately',
20
+ 'Existing in-flight jobs will still process — they are idempotent',
21
+ 'No database migration needed — booking_status field is additive, not destructive',
22
+ 'Mobile apps degrade gracefully: they simply won\'t see booking-specific UI states',
23
+ ];
24
+
25
+ export function DeploymentGuideSection() {
26
+ return (
27
+ <div className="space-y-5">
28
+ <div
29
+ className="rounded-xl border p-5"
30
+ style={{ background: 'rgba(20,17,24,0.5)', borderColor: 'var(--color-border-default)' }}
31
+ >
32
+ <h4 className="text-sm font-bold text-slate-200 mb-3">Environment Configuration</h4>
33
+ <div className="space-y-3">
34
+ {ENV_CONFIGS.map((env) => (
35
+ <div key={env.env} className="flex items-center gap-3">
36
+ <span
37
+ className="text-xs font-bold w-24 px-2 py-1 rounded text-center"
38
+ style={{ background: `${env.color}15`, color: env.color, border: `1px solid ${env.color}25` }}
39
+ >
40
+ {env.env}
41
+ </span>
42
+ <div className="flex flex-wrap gap-2">
43
+ {Object.entries(env.flags).map(([key, val]) => (
44
+ <span
45
+ key={key}
46
+ className="text-[11px] font-mono px-2 py-0.5 rounded border"
47
+ style={{
48
+ color: val ? '#22c55e' : '#ef4444',
49
+ background: val ? 'rgba(34,197,94,0.1)' : 'rgba(239,68,68,0.1)',
50
+ borderColor: val ? 'rgba(34,197,94,0.2)' : 'rgba(239,68,68,0.2)',
51
+ }}
52
+ >
53
+ {key}={val ? 'true' : 'false'}
54
+ </span>
55
+ ))}
56
+ </div>
57
+ </div>
58
+ ))}
59
+ </div>
60
+ </div>
61
+
62
+ <div
63
+ className="rounded-xl border p-5"
64
+ style={{ background: 'rgba(20,17,24,0.5)', borderColor: 'var(--color-border-default)' }}
65
+ >
66
+ <h4 className="text-sm font-bold text-slate-200 mb-3">Rollout Steps</h4>
67
+ <div className="space-y-3">
68
+ {ROLLOUT_STEPS.map((s, i) => (
69
+ <div key={i} className="flex items-start gap-3">
70
+ <div
71
+ className="w-6 h-6 rounded-full flex items-center justify-center text-[10px] font-bold shrink-0 mt-0.5"
72
+ style={{ background: 'rgba(123,89,230,0.15)', color: '#7b59e6' }}
73
+ >
74
+ {i + 1}
75
+ </div>
76
+ <div>
77
+ <div className="text-sm text-slate-200 font-medium">{s.step}</div>
78
+ <p className="text-xs text-slate-500 mt-0.5">{s.detail}</p>
79
+ </div>
80
+ </div>
81
+ ))}
82
+ </div>
83
+ </div>
84
+
85
+ <div
86
+ className="rounded-xl border p-5"
87
+ style={{ background: 'rgba(239,68,68,0.05)', borderColor: 'rgba(239,68,68,0.2)' }}
88
+ >
89
+ <div className="flex items-center gap-2 mb-3">
90
+ <Icon name="replay" size={18} className="text-red-400" />
91
+ <h4 className="text-sm font-bold text-red-300">Rollback Procedure</h4>
92
+ </div>
93
+ <ul className="space-y-2">
94
+ {ROLLBACK.map((item, i) => (
95
+ <li key={i} className="flex items-start gap-2">
96
+ <Icon name="arrow_right" size={14} className="text-red-400 mt-0.5 shrink-0" />
97
+ <span className="text-xs text-slate-400">{item}</span>
98
+ </li>
99
+ ))}
100
+ </ul>
101
+ </div>
102
+ </div>
103
+ );
104
+ }
@@ -0,0 +1,127 @@
1
+ import { Icon } from '../shared/Icon';
2
+
3
+ const ENDPOINTS = [
4
+ {
5
+ method: 'PUT',
6
+ path: '/b2c/driver/trips/:tripId/booking-status',
7
+ body: '{ "booking_status": "BOOK_ACCEPTED" | "BOOK_DRIVER_CANCELED" }',
8
+ description: 'Driver updates their booking status — accept or cancel the assigned ride.',
9
+ },
10
+ ];
11
+
12
+ const TRANSITIONS = [
13
+ { from: 'TRIP_BOOK_PENDING', to: 'BOOK_ACCEPTED', action: 'Driver accepts the assignment' },
14
+ { from: 'TRIP_BOOK_PENDING', to: 'BOOK_DRIVER_CANCELED', action: 'Driver cancels the assignment' },
15
+ { from: 'TRIP_BOOK_OPERATION_DRIVER_CONFIRMED', to: 'BOOK_DRIVER_CANCELED', action: 'Driver cancels after confirming' },
16
+ ];
17
+
18
+ const DAC_CARDS = [
19
+ { action: 'confirm', description: 'Shown when driver is assigned and needs to confirm availability', triggers: 'BOOK_ACCEPTED on tap' },
20
+ { action: 'cancel', description: 'Shown alongside confirm — driver can decline', triggers: 'BOOK_DRIVER_CANCELED on tap' },
21
+ { action: 'view_ride', description: 'Shown after confirmation — ride details view', triggers: 'Opens ride detail screen' },
22
+ ];
23
+
24
+ const INTEGRATION_CHECKLIST = [
25
+ 'Handle push notification with action "confirm_driver_booking" — show confirmation DAC card',
26
+ 'Handle push notification with action "driver_booking_timeout" — show timeout warning',
27
+ 'Handle push notification with action "driver_booking_ops_cancelled" — remove DAC card',
28
+ 'Handle push notification with action "booking_driver_assigned" — show new assignment card',
29
+ 'Handle push notification with action "booking_canceled_by_rider" — remove DAC card',
30
+ 'Implement DAC card rendering for confirm/cancel actions',
31
+ 'Handle HTTP 409 responses (concurrent update / invalid transition)',
32
+ 'Handle re-dispatch scenario: after driver cancel, ride goes back to dispatch queue',
33
+ 'Handle the publishRideDispatchBookingMW side effect: new driver may be assigned',
34
+ ];
35
+
36
+ export function DriverIntegrationSection() {
37
+ return (
38
+ <div className="space-y-5">
39
+ {ENDPOINTS.map((ep) => (
40
+ <div
41
+ key={ep.path}
42
+ className="rounded-xl border overflow-hidden"
43
+ style={{ background: 'rgba(20,17,24,0.5)', borderColor: 'var(--color-border-default)' }}
44
+ >
45
+ <div className="px-4 py-3 flex items-center gap-3 border-b" style={{ borderColor: 'var(--color-border-default)' }}>
46
+ <span className="text-[10px] font-bold px-2 py-0.5 rounded" style={{ background: 'rgba(251,191,36,0.15)', color: '#fbbf24' }}>
47
+ {ep.method}
48
+ </span>
49
+ <code className="text-sm text-slate-200 font-mono">{ep.path}</code>
50
+ </div>
51
+ <div className="px-4 py-3">
52
+ <p className="text-xs text-slate-400 mb-2">{ep.description}</p>
53
+ <span className="text-[10px] uppercase tracking-wider text-slate-500 font-semibold">Request Body</span>
54
+ <pre className="mt-1 text-[11px] font-mono text-emerald-400 bg-black/30 rounded-lg px-3 py-2">{ep.body}</pre>
55
+ </div>
56
+ </div>
57
+ ))}
58
+
59
+ <div
60
+ className="rounded-xl border overflow-hidden"
61
+ style={{ borderColor: 'var(--color-border-default)', background: 'rgba(20,17,24,0.5)' }}
62
+ >
63
+ <div className="px-4 py-3 border-b" style={{ borderColor: 'var(--color-border-default)', background: 'rgba(255,255,255,0.03)' }}>
64
+ <span className="text-sm font-bold text-slate-200">Valid Driver Transitions</span>
65
+ </div>
66
+ <table className="w-full text-sm">
67
+ <thead style={{ background: 'rgba(255,255,255,0.05)' }}>
68
+ <tr>
69
+ <th className="px-4 py-2 text-left text-xs font-semibold text-slate-400">From</th>
70
+ <th className="px-4 py-2 text-center text-xs font-semibold text-slate-400"></th>
71
+ <th className="px-4 py-2 text-left text-xs font-semibold text-slate-400">To</th>
72
+ <th className="px-4 py-2 text-left text-xs font-semibold text-slate-400">Action</th>
73
+ </tr>
74
+ </thead>
75
+ <tbody>
76
+ {TRANSITIONS.map((t, i) => (
77
+ <tr key={i} className="border-t hover:bg-white/5 transition-colors" style={{ borderColor: 'var(--color-border-default)' }}>
78
+ <td className="px-4 py-2 font-mono text-[11px] text-slate-400">{t.from}</td>
79
+ <td className="px-4 py-2 text-center"><Icon name="arrow_forward" size={14} className="text-slate-600" /></td>
80
+ <td className="px-4 py-2 font-mono text-[11px] text-cyan-400">{t.to}</td>
81
+ <td className="px-4 py-2 text-xs text-slate-400">{t.action}</td>
82
+ </tr>
83
+ ))}
84
+ </tbody>
85
+ </table>
86
+ </div>
87
+
88
+ <div
89
+ className="rounded-xl border overflow-hidden"
90
+ style={{ borderColor: 'var(--color-border-default)', background: 'rgba(20,17,24,0.5)' }}
91
+ >
92
+ <div className="px-4 py-3 border-b" style={{ borderColor: 'var(--color-border-default)', background: 'rgba(255,255,255,0.03)' }}>
93
+ <span className="text-sm font-bold text-slate-200">DAC (Driver Action Cards)</span>
94
+ </div>
95
+ <div className="p-3 space-y-2">
96
+ {DAC_CARDS.map((card) => (
97
+ <div key={card.action} className="flex items-start gap-3 p-2.5 rounded-lg" style={{ background: 'rgba(255,255,255,0.02)' }}>
98
+ <Icon name="credit_card" size={16} className="text-cyan-400 mt-0.5 shrink-0" />
99
+ <div>
100
+ <div className="flex items-center gap-2">
101
+ <span className="text-xs font-mono font-semibold text-slate-200">{card.action}</span>
102
+ <span className="text-[10px] text-slate-500">→ {card.triggers}</span>
103
+ </div>
104
+ <p className="text-[11px] text-slate-400 mt-0.5">{card.description}</p>
105
+ </div>
106
+ </div>
107
+ ))}
108
+ </div>
109
+ </div>
110
+
111
+ <div
112
+ className="rounded-xl border p-4"
113
+ style={{ background: 'rgba(20,17,24,0.5)', borderColor: 'var(--color-border-default)' }}
114
+ >
115
+ <h4 className="text-sm font-bold text-slate-200 mb-3">Integration Checklist</h4>
116
+ <ul className="space-y-2">
117
+ {INTEGRATION_CHECKLIST.map((item, i) => (
118
+ <li key={i} className="flex items-start gap-2">
119
+ <Icon name="check_box_outline_blank" size={16} className="text-slate-600 mt-0.5 shrink-0" />
120
+ <span className="text-xs text-slate-400">{item}</span>
121
+ </li>
122
+ ))}
123
+ </ul>
124
+ </div>
125
+ </div>
126
+ );
127
+ }
@@ -0,0 +1,69 @@
1
+ import { Icon } from '../shared/Icon';
2
+
3
+ const METRICS = [
4
+ { label: 'Flow Paths', value: '11', icon: 'route', color: '#7b59e6' },
5
+ { label: 'Status Mappings', value: '12', icon: 'swap_horiz', color: '#06b6d4' },
6
+ { label: 'BullMQ Jobs', value: '6', icon: 'schedule', color: '#a855f7' },
7
+ { label: 'Feature Flags', value: '3', icon: 'flag', color: '#f59e0b' },
8
+ ];
9
+
10
+ const KEY_POINTS = [
11
+ 'Syncs internal trip status changes to a rider/driver-facing booking_status field on the Trip schema',
12
+ 'Uses optimistic locking (updateOne with status guard) to prevent race conditions',
13
+ 'All side effects (notifications, DAC, cleanup) are fire-and-forget — never block the response',
14
+ 'Feature flags control rollout: ENABLE_BOOKING_JOBS, ENABLE_PRE_TRIP_RIDER_CONFIRMATION, ENABLE_DRIVER_CONFIRMATION',
15
+ 'Two entry points: rider endpoint (PUT /rider/trips/:tripId/booking-status) and driver endpoint (PUT /b2c/driver/trips/:tripId/booking-status)',
16
+ ];
17
+
18
+ export function ExecutiveSummarySection() {
19
+ return (
20
+ <div className="space-y-5">
21
+ <div
22
+ className="rounded-xl border p-5"
23
+ style={{ background: 'rgba(20,17,24,0.5)', borderColor: 'var(--color-border-default)' }}
24
+ >
25
+ <h4 className="text-sm font-bold text-slate-200 mb-2">What is Sync Booking Status?</h4>
26
+ <p className="text-sm text-slate-400 leading-relaxed">
27
+ The Scheduled Ride Booking Status Sync feature maintains a parallel <code className="text-xs bg-white/5 px-1.5 py-0.5 rounded text-slate-300">booking_status</code> field
28
+ on the Trip schema that reflects the lifecycle of a scheduled (booked) ride. When internal trip statuses change
29
+ (e.g., driver assigned, trip started, rider cancelled), the middleware automatically maps these to
30
+ booking-specific statuses that the mobile apps consume.
31
+ </p>
32
+ </div>
33
+
34
+ <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
35
+ {METRICS.map((m) => (
36
+ <div
37
+ key={m.label}
38
+ className="rounded-lg border p-3 text-center"
39
+ style={{ background: 'rgba(20,17,24,0.5)', borderColor: 'var(--color-border-default)' }}
40
+ >
41
+ <div
42
+ className="w-8 h-8 rounded-lg flex items-center justify-center mx-auto mb-2"
43
+ style={{ background: `${m.color}20`, color: m.color }}
44
+ >
45
+ <Icon name={m.icon} size={18} />
46
+ </div>
47
+ <div className="text-2xl font-bold text-white">{m.value}</div>
48
+ <div className="text-[10px] text-slate-500 uppercase tracking-wider font-semibold mt-0.5">{m.label}</div>
49
+ </div>
50
+ ))}
51
+ </div>
52
+
53
+ <div
54
+ className="rounded-xl border p-5"
55
+ style={{ background: 'rgba(20,17,24,0.5)', borderColor: 'var(--color-border-default)' }}
56
+ >
57
+ <h4 className="text-sm font-bold text-slate-200 mb-3">Key Points</h4>
58
+ <ul className="space-y-2">
59
+ {KEY_POINTS.map((point, i) => (
60
+ <li key={i} className="flex items-start gap-2">
61
+ <Icon name="check_circle" size={16} className="text-emerald-400 mt-0.5 shrink-0" />
62
+ <span className="text-sm text-slate-400 leading-relaxed">{point}</span>
63
+ </li>
64
+ ))}
65
+ </ul>
66
+ </div>
67
+ </div>
68
+ );
69
+ }
@@ -0,0 +1,73 @@
1
+ import { Icon } from '../shared/Icon';
2
+ import { PATHS } from '../../data/paths';
3
+
4
+ const CATEGORY_COLORS: Record<string, string> = {
5
+ success: '#22c55e',
6
+ 'rider-cancel': '#ef4444',
7
+ 'driver-cancel': '#f97316',
8
+ timeout: '#eab308',
9
+ ops: '#8b5cf6',
10
+ 'active-cancel': '#ec4899',
11
+ };
12
+
13
+ export function FlowOverviewSection() {
14
+ const grouped = PATHS.reduce<Record<string, typeof PATHS>>((acc, path) => {
15
+ const cat = path.category;
16
+ if (!acc[cat]) acc[cat] = [];
17
+ acc[cat].push(path);
18
+ return acc;
19
+ }, {});
20
+
21
+ return (
22
+ <div className="space-y-4">
23
+ <div
24
+ className="rounded-xl border p-5"
25
+ style={{ background: 'rgba(20,17,24,0.5)', borderColor: 'var(--color-border-default)' }}
26
+ >
27
+ <p className="text-sm text-slate-400 leading-relaxed">
28
+ The booking status sync feature covers <strong className="text-white">{PATHS.length} distinct flow paths</strong> organized
29
+ by category. Each path represents a complete lifecycle scenario from trip creation through terminal state.
30
+ </p>
31
+ </div>
32
+
33
+ {Object.entries(grouped).map(([category, paths]) => {
34
+ const color = CATEGORY_COLORS[category] || '#64748b';
35
+ return (
36
+ <div key={category}>
37
+ <div className="flex items-center gap-2 mb-2">
38
+ <span
39
+ className="h-2 w-2 rounded-full"
40
+ style={{ background: color }}
41
+ />
42
+ <span className="text-xs font-bold uppercase tracking-wider" style={{ color }}>
43
+ {category.replace(/-/g, ' ')} ({paths.length})
44
+ </span>
45
+ </div>
46
+ <div className="space-y-1.5">
47
+ {paths.map((path) => (
48
+ <div
49
+ key={path.id}
50
+ className="flex items-center gap-3 px-3 py-2.5 rounded-lg border hover:bg-white/5 transition-colors"
51
+ style={{
52
+ background: 'rgba(20,17,24,0.3)',
53
+ borderColor: 'var(--color-border-default)',
54
+ }}
55
+ >
56
+ <Icon name={path.icon} size={18} className={`text-[${path.color}]`} />
57
+ <div className="flex-1 min-w-0">
58
+ <span className="text-sm text-slate-200 font-medium">{path.label}</span>
59
+ <p className="text-xs text-slate-500 truncate">{path.description}</p>
60
+ </div>
61
+ <span className="text-[10px] text-slate-500 font-mono">
62
+ {path.steps.length} steps
63
+ {path.subPaths ? ` + ${path.subPaths.length} sub-paths` : ''}
64
+ </span>
65
+ </div>
66
+ ))}
67
+ </div>
68
+ </div>
69
+ );
70
+ })}
71
+ </div>
72
+ );
73
+ }
@@ -0,0 +1,96 @@
1
+ import { useState } from 'react';
2
+ import { Icon } from '../shared/Icon';
3
+ import { PATHS } from '../../data/paths';
4
+
5
+ const CATEGORY_COLORS: Record<string, string> = {
6
+ success: '#22c55e',
7
+ 'rider-cancel': '#ef4444',
8
+ 'driver-cancel': '#f97316',
9
+ timeout: '#eab308',
10
+ ops: '#8b5cf6',
11
+ 'active-cancel': '#ec4899',
12
+ };
13
+
14
+ export function FlowPathsChecklistSection() {
15
+ const [checked, setChecked] = useState<Set<number>>(new Set());
16
+
17
+ const toggle = (id: number) => {
18
+ setChecked((prev) => {
19
+ const next = new Set(prev);
20
+ if (next.has(id)) next.delete(id);
21
+ else next.add(id);
22
+ return next;
23
+ });
24
+ };
25
+
26
+ const total = PATHS.length;
27
+ const done = checked.size;
28
+ const pct = total > 0 ? Math.round((done / total) * 100) : 0;
29
+
30
+ return (
31
+ <div className="space-y-4">
32
+ <div
33
+ className="rounded-xl border p-4"
34
+ style={{ background: 'rgba(20,17,24,0.5)', borderColor: 'var(--color-border-default)' }}
35
+ >
36
+ <div className="flex items-center justify-between mb-3">
37
+ <span className="text-sm font-bold text-slate-200">Verification Progress</span>
38
+ <span className="text-sm font-bold" style={{ color: pct === 100 ? '#22c55e' : '#f59e0b' }}>
39
+ {done}/{total} ({pct}%)
40
+ </span>
41
+ </div>
42
+ <div className="w-full h-2 rounded-full overflow-hidden" style={{ background: 'rgba(255,255,255,0.05)' }}>
43
+ <div
44
+ className="h-full rounded-full transition-all"
45
+ style={{
46
+ width: `${pct}%`,
47
+ background: pct === 100 ? '#22c55e' : 'var(--color-primary)',
48
+ }}
49
+ />
50
+ </div>
51
+ </div>
52
+
53
+ <div className="space-y-1.5">
54
+ {PATHS.map((path) => {
55
+ const isChecked = checked.has(path.id);
56
+ const catColor = CATEGORY_COLORS[path.category] || '#64748b';
57
+ return (
58
+ <button
59
+ key={path.id}
60
+ onClick={() => toggle(path.id)}
61
+ className="w-full flex items-center gap-3 px-3 py-2.5 rounded-lg border text-left transition-all"
62
+ style={{
63
+ background: isChecked ? 'rgba(34,197,94,0.05)' : 'rgba(20,17,24,0.3)',
64
+ borderColor: isChecked ? 'rgba(34,197,94,0.2)' : 'var(--color-border-default)',
65
+ }}
66
+ >
67
+ <Icon
68
+ name={isChecked ? 'check_box' : 'check_box_outline_blank'}
69
+ size={20}
70
+ className={isChecked ? 'text-emerald-400' : 'text-slate-600'}
71
+ />
72
+ <Icon name={path.icon} size={18} className="text-slate-400" />
73
+ <div className="flex-1 min-w-0">
74
+ <span
75
+ className="text-sm font-medium"
76
+ style={{ color: isChecked ? '#94a3b8' : '#e2e8f0', textDecoration: isChecked ? 'line-through' : 'none' }}
77
+ >
78
+ Path {path.id}: {path.label}
79
+ </span>
80
+ </div>
81
+ <span
82
+ className="text-[9px] font-bold px-1.5 py-0.5 rounded shrink-0"
83
+ style={{ background: `${catColor}15`, color: catColor }}
84
+ >
85
+ {path.category}
86
+ </span>
87
+ <span className="text-[10px] text-slate-500 font-mono shrink-0">
88
+ {path.steps.length}s{path.subPaths ? `+${path.subPaths.length}sp` : ''}
89
+ </span>
90
+ </button>
91
+ );
92
+ })}
93
+ </div>
94
+ </div>
95
+ );
96
+ }
@@ -0,0 +1,107 @@
1
+ interface MiddlewareStep {
2
+ name: string;
3
+ description: string;
4
+ type: 'validate' | 'persist' | 'sideEffect' | 'notify';
5
+ }
6
+
7
+ const TYPE_COLORS = {
8
+ validate: { color: '#60a5fa', bg: 'rgba(96,165,250,0.1)' },
9
+ persist: { color: '#22c55e', bg: 'rgba(34,197,94,0.1)' },
10
+ sideEffect: { color: '#f59e0b', bg: 'rgba(245,158,11,0.1)' },
11
+ notify: { color: '#fb2576', bg: 'rgba(251,37,118,0.1)' },
12
+ };
13
+
14
+ const CHAINS: { title: string; endpoint: string; color: string; steps: MiddlewareStep[] }[] = [
15
+ {
16
+ title: 'Internal Trip Status Path',
17
+ endpoint: 'PUT /b2c/rider/services/v6/request',
18
+ color: '#7b59e6',
19
+ steps: [
20
+ { name: 'validateTripStatus', description: 'Validates trip status transition is allowed', type: 'validate' },
21
+ { name: 'fnUpdateBookingStatus', description: 'Maps trip status to booking_status using TRIP_STATUS_TO_BOOKING_STATUS, writes with optimistic lock', type: 'persist' },
22
+ { name: 'fnUpdateCancelBookingStatus', description: 'Handles cancel-specific booking status updates (rider/driver/system cancels)', type: 'persist' },
23
+ { name: 'fnCancelBookedTripScheduledJobs', description: 'Removes pending BullMQ jobs on cancellation', type: 'sideEffect' },
24
+ { name: 'fnDeleteScheduledRideDac', description: 'Deletes DAC card via Pub/Sub when trip ends or is cancelled', type: 'sideEffect' },
25
+ { name: 'publishScheduledRideDacMW', description: 'Publishes new DAC card for driver actions (confirm/cancel)', type: 'sideEffect' },
26
+ { name: 'scheduleBookingJobs', description: 'Schedules BullMQ jobs on assignment (pre-trip confirmation timers)', type: 'sideEffect' },
27
+ ],
28
+ },
29
+ {
30
+ title: 'Rider Booking Endpoint',
31
+ endpoint: 'PUT /rider/trips/:tripId/booking-status',
32
+ color: '#06b6d4',
33
+ steps: [
34
+ { name: 'validateBookingStatusTransition', description: 'Checks VALID_RIDER_TRANSITIONS map', type: 'validate' },
35
+ { name: 'saveBookingStatusUpdate', description: 'Persists new booking_status with optimistic lock', type: 'persist' },
36
+ { name: 'fnCancelBookedTripScheduledJobs', description: 'Cleans up BullMQ jobs if cancelled', type: 'sideEffect' },
37
+ { name: 'fnDeleteScheduledRideDac', description: 'Deletes DAC card on cancellation', type: 'sideEffect' },
38
+ { name: 'publishScheduledRideDacMW', description: 'Publishes updated DAC card', type: 'sideEffect' },
39
+ { name: 'sendBookingNotification', description: 'Sends push notification to driver about rider action', type: 'notify' },
40
+ ],
41
+ },
42
+ {
43
+ title: 'Driver Booking Endpoint',
44
+ endpoint: 'PUT /b2c/driver/trips/:tripId/booking-status',
45
+ color: '#10b981',
46
+ steps: [
47
+ { name: 'validateDriverBookingTransition', description: 'Checks VALID_DRIVER_TRANSITIONS map', type: 'validate' },
48
+ { name: 'saveBookingStatusUpdate', description: 'Persists new booking_status with optimistic lock', type: 'persist' },
49
+ { name: 'fnCancelBookedTripScheduledJobs', description: 'Cleans up BullMQ jobs on driver cancel', type: 'sideEffect' },
50
+ { name: 'publishRideDispatchBookingMW', description: 'Re-dispatches ride when driver cancels', type: 'sideEffect' },
51
+ { name: 'publishScheduledRideDacMW', description: 'Publishes/deletes DAC card', type: 'sideEffect' },
52
+ { name: 'sendBookingNotification', description: 'Sends push notification to rider about driver action', type: 'notify' },
53
+ ],
54
+ },
55
+ ];
56
+
57
+ export function MiddlewareChainSection() {
58
+ return (
59
+ <div className="space-y-5">
60
+ {CHAINS.map((chain) => (
61
+ <div
62
+ key={chain.endpoint}
63
+ className="rounded-xl border overflow-hidden"
64
+ style={{ background: 'rgba(20,17,24,0.5)', borderColor: 'var(--color-border-default)' }}
65
+ >
66
+ <div className="px-4 py-3 border-b flex items-center gap-3" style={{ borderColor: 'var(--color-border-default)', background: 'rgba(255,255,255,0.03)' }}>
67
+ <div className="w-2 h-2 rounded-full" style={{ background: chain.color }} />
68
+ <span className="text-sm font-bold text-slate-200">{chain.title}</span>
69
+ <code className="text-[10px] font-mono text-slate-500 ml-auto">{chain.endpoint}</code>
70
+ </div>
71
+ <div className="p-3 space-y-1.5">
72
+ {chain.steps.map((step, i) => {
73
+ const tc = TYPE_COLORS[step.type];
74
+ return (
75
+ <div key={step.name} className="flex items-start gap-3 group">
76
+ <div className="flex flex-col items-center pt-1">
77
+ <div
78
+ className="w-5 h-5 rounded-full flex items-center justify-center text-[9px] font-bold"
79
+ style={{ background: tc.bg, color: tc.color }}
80
+ >
81
+ {i + 1}
82
+ </div>
83
+ {i < chain.steps.length - 1 && (
84
+ <div className="w-px h-6 mt-0.5" style={{ background: 'var(--color-border-default)' }} />
85
+ )}
86
+ </div>
87
+ <div className="flex-1 min-w-0 pb-1">
88
+ <div className="flex items-center gap-2">
89
+ <span className="text-xs font-mono font-semibold text-slate-200">{step.name}</span>
90
+ <span
91
+ className="text-[9px] px-1.5 py-0.5 rounded font-medium"
92
+ style={{ background: tc.bg, color: tc.color }}
93
+ >
94
+ {step.type}
95
+ </span>
96
+ </div>
97
+ <p className="text-[11px] text-slate-500 mt-0.5">{step.description}</p>
98
+ </div>
99
+ </div>
100
+ );
101
+ })}
102
+ </div>
103
+ </div>
104
+ ))}
105
+ </div>
106
+ );
107
+ }