yadflow 2.5.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.
- package/CHANGELOG.md +8 -2
- package/README.md +65 -22
- package/bin/yad.mjs +27 -1
- package/cli/docs.mjs +298 -0
- package/cli/doctor.mjs +1 -0
- package/cli/manifest.mjs +23 -2
- package/cli/ship.mjs +37 -0
- package/docs/index.html +44 -13
- package/package.json +2 -2
- package/skills/sdlc/config.yaml +26 -2
- package/skills/sdlc/install.sh +1 -1
- package/skills/sdlc/module-help.csv +11 -4
- package/skills/yad-checks/references/check-gates.md +58 -2
- package/skills/yad-checks/templates/checks/commit-message.sh +82 -0
- package/skills/yad-checks/templates/github/yad-checks.yml +27 -0
- package/skills/yad-checks/templates/github/yad-hub-checks.yml +36 -0
- package/skills/yad-checks/templates/gitlab/yad-checks.gitlab-ci.yml +20 -0
- package/skills/yad-checks/templates/gitlab/yad-hub-checks.gitlab-ci.yml +39 -0
- package/skills/yad-commit/SKILL.md +66 -0
- package/skills/yad-connect-docs/SKILL.md +132 -0
- package/skills/yad-connect-docs/references/docs-registry.md +74 -0
- package/skills/yad-docs/SKILL.md +159 -0
- package/skills/yad-docs/references/data-mapping.md +75 -0
- package/skills/yad-docs/references/theme-map.md +69 -0
- package/skills/yad-docs/templates/app/README.md +31 -0
- package/skills/yad-docs/templates/app/eslint.config.js +23 -0
- package/skills/yad-docs/templates/app/index.html +17 -0
- package/skills/yad-docs/templates/app/package-lock.json +4030 -0
- package/skills/yad-docs/templates/app/package.json +35 -0
- package/skills/yad-docs/templates/app/public/favicon.svg +28 -0
- package/skills/yad-docs/templates/app/public/logo.svg +39 -0
- package/skills/yad-docs/templates/app/public/vite.svg +1 -0
- package/skills/yad-docs/templates/app/src/App.tsx +98 -0
- package/skills/yad-docs/templates/app/src/components/Auth/LoginPage.tsx +101 -0
- package/skills/yad-docs/templates/app/src/components/Canvas/AnimatedMessage.tsx +101 -0
- package/skills/yad-docs/templates/app/src/components/Canvas/ConnectionLine.tsx +90 -0
- package/skills/yad-docs/templates/app/src/components/Canvas/FlowCanvas.tsx +216 -0
- package/skills/yad-docs/templates/app/src/components/Canvas/SystemComponent.tsx +153 -0
- package/skills/yad-docs/templates/app/src/components/Controls/PlaybackBar.tsx +284 -0
- package/skills/yad-docs/templates/app/src/components/Controls/StepDetail.tsx +167 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/HandlerLogicSnippet.tsx +41 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/RequestPayloadPreview.tsx +46 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/RightPanel.tsx +88 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/StatusCard.tsx +76 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/TriggerEventCard.tsx +45 -0
- package/skills/yad-docs/templates/app/src/components/DocLayout/DocPageShell.tsx +80 -0
- package/skills/yad-docs/templates/app/src/components/DocLayout/DocSectionCard.tsx +55 -0
- package/skills/yad-docs/templates/app/src/components/DocLayout/DocTableOfContents.tsx +79 -0
- package/skills/yad-docs/templates/app/src/components/DocLayout/RoleCard.tsx +67 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/ApiReferenceSection.tsx +108 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/CancelabilitySection.tsx +73 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/CriticalRunbookSection.tsx +177 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/DataMigrationSection.tsx +102 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/DbSchemaSection.tsx +98 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/DeploymentGuideSection.tsx +104 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/DriverIntegrationSection.tsx +127 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/ExecutiveSummarySection.tsx +69 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/FlowOverviewSection.tsx +73 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/FlowPathsChecklistSection.tsx +96 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/MiddlewareChainSection.tsx +107 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/MonitoringAlertingSection.tsx +106 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/NotificationLocalizationSection.tsx +102 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/PMRoadmapSection.tsx +133 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/PerformanceTestingSection.tsx +91 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/RiderIntegrationSection.tsx +99 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/SecuritySection.tsx +74 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/StatusMachineSection.tsx +90 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/TestPlanSection.tsx +163 -0
- package/skills/yad-docs/templates/app/src/components/Logs/SystemLogsTerminal.tsx +126 -0
- package/skills/yad-docs/templates/app/src/components/Navigation/TopNavBar.tsx +90 -0
- package/skills/yad-docs/templates/app/src/components/Reference/BullMQJobsList.tsx +60 -0
- package/skills/yad-docs/templates/app/src/components/Reference/DecisionTreeView.tsx +49 -0
- package/skills/yad-docs/templates/app/src/components/Reference/DeeplinkActionsChips.tsx +69 -0
- package/skills/yad-docs/templates/app/src/components/Reference/DriverUIStatesTable.tsx +61 -0
- package/skills/yad-docs/templates/app/src/components/Reference/FeatureFlagMatrix.tsx +73 -0
- package/skills/yad-docs/templates/app/src/components/Reference/RiderUIStatesTable.tsx +61 -0
- package/skills/yad-docs/templates/app/src/components/Reference/RulesLegendPanel.tsx +217 -0
- package/skills/yad-docs/templates/app/src/components/Reference/StakeholderToggle.tsx +41 -0
- package/skills/yad-docs/templates/app/src/components/Reference/TroubleshootingSection.tsx +93 -0
- package/skills/yad-docs/templates/app/src/components/Sidebar/PathSelector.tsx +148 -0
- package/skills/yad-docs/templates/app/src/components/Sidebar/SidebarFooter.tsx +40 -0
- package/skills/yad-docs/templates/app/src/components/Sidebar/StepList.tsx +234 -0
- package/skills/yad-docs/templates/app/src/components/shared/Badge.tsx +28 -0
- package/skills/yad-docs/templates/app/src/components/shared/CommandPalette.tsx +213 -0
- package/skills/yad-docs/templates/app/src/components/shared/Icon.tsx +21 -0
- package/skills/yad-docs/templates/app/src/components/shared/Tooltip.tsx +42 -0
- package/skills/yad-docs/templates/app/src/data/components.ts +74 -0
- package/skills/yad-docs/templates/app/src/data/docSections.ts +231 -0
- package/skills/yad-docs/templates/app/src/data/paths.ts +2319 -0
- package/skills/yad-docs/templates/app/src/data/referenceData.ts +392 -0
- package/skills/yad-docs/templates/app/src/data/roles.ts +145 -0
- package/skills/yad-docs/templates/app/src/data/types.ts +79 -0
- package/skills/yad-docs/templates/app/src/hooks/useAnimationQueue.ts +41 -0
- package/skills/yad-docs/templates/app/src/hooks/usePlayback.ts +100 -0
- package/skills/yad-docs/templates/app/src/hooks/useStakeholderFilter.ts +10 -0
- package/skills/yad-docs/templates/app/src/index.css +121 -0
- package/skills/yad-docs/templates/app/src/main.tsx +13 -0
- package/skills/yad-docs/templates/app/src/pages/RoleSelectPage.tsx +34 -0
- package/skills/yad-docs/templates/app/src/pages/StakeholderDocPage.tsx +98 -0
- package/skills/yad-docs/templates/app/src/pages/SubPathDetailPage.tsx +282 -0
- package/skills/yad-docs/templates/app/src/store/useAuthStore.ts +42 -0
- package/skills/yad-docs/templates/app/src/store/useFlowStore.ts +197 -0
- package/skills/yad-docs/templates/app/src/utils/iconMap.ts +46 -0
- package/skills/yad-docs/templates/app/tsconfig.app.json +28 -0
- package/skills/yad-docs/templates/app/tsconfig.json +7 -0
- package/skills/yad-docs/templates/app/tsconfig.node.json +26 -0
- package/skills/yad-docs/templates/app/vite.config.ts +10 -0
- package/skills/yad-docs-overview/SKILL.md +129 -0
- package/skills/yad-docs-overview/references/pipeline-model.md +102 -0
- package/skills/yad-docs-sync/SKILL.md +99 -0
- package/skills/yad-docs-sync/references/staleness.md +81 -0
- package/skills/yad-engineer-review/SKILL.md +86 -0
- package/skills/{yad-ship → yad-engineer-review}/references/ship-and-record.md +2 -2
- package/skills/{yad-ship → yad-engineer-review}/templates/.coderabbit.yaml +1 -1
- package/skills/yad-epic/references/state-schema.md +1 -1
- package/skills/yad-implement/SKILL.md +1 -1
- package/skills/yad-implement/references/implement-conventions.md +1 -1
- package/skills/yad-open-pr/SKILL.md +72 -0
- package/skills/yad-pr-template/templates/checks/pr-template.sh +62 -0
- package/skills/yad-pr-template/templates/checks/pr-title.sh +51 -0
- package/skills/yad-run/SKILL.md +2 -2
- package/skills/yad-run/references/run-loop.md +4 -4
- package/skills/yad-ship/SKILL.md +44 -66
- package/skills/yad-spec/SKILL.md +1 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Icon } from '../shared/Icon';
|
|
2
|
+
import { useStakeholderFilter } from '../../hooks/useStakeholderFilter';
|
|
3
|
+
import { DRIVER_UI_STATES } from '../../data/referenceData';
|
|
4
|
+
|
|
5
|
+
export function DriverUIStatesTable() {
|
|
6
|
+
const states = useStakeholderFilter(DRIVER_UI_STATES);
|
|
7
|
+
|
|
8
|
+
if (states.length === 0) return null;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<section>
|
|
12
|
+
<div className="flex items-center justify-between mb-4">
|
|
13
|
+
<div className="flex items-center gap-2">
|
|
14
|
+
<Icon name="directions_car" size={20} className="text-purple-400" />
|
|
15
|
+
<h3 className="text-slate-100 text-lg font-bold font-display">Driver UI States</h3>
|
|
16
|
+
</div>
|
|
17
|
+
<span
|
|
18
|
+
className="text-[10px] font-bold uppercase tracking-wider px-2 py-1 rounded border"
|
|
19
|
+
style={{ color: '#a78bfa', background: 'rgba(167,139,250,0.1)', borderColor: 'rgba(167,139,250,0.2)' }}
|
|
20
|
+
>
|
|
21
|
+
Mobile Dev Focus
|
|
22
|
+
</span>
|
|
23
|
+
</div>
|
|
24
|
+
<div
|
|
25
|
+
className="rounded-xl border overflow-hidden"
|
|
26
|
+
style={{ borderColor: 'var(--color-border-default)', background: 'rgba(20,17,24,0.5)' }}
|
|
27
|
+
>
|
|
28
|
+
<table className="w-full text-left text-sm">
|
|
29
|
+
<thead style={{ background: 'rgba(255,255,255,0.05)' }}>
|
|
30
|
+
<tr>
|
|
31
|
+
<th className="px-4 py-3 font-semibold text-slate-300">State</th>
|
|
32
|
+
<th className="px-4 py-3 font-semibold text-slate-300">Schema Value</th>
|
|
33
|
+
<th className="px-4 py-3 font-semibold text-slate-300 text-right">Terminal</th>
|
|
34
|
+
</tr>
|
|
35
|
+
</thead>
|
|
36
|
+
<tbody>
|
|
37
|
+
{states.map((state) => (
|
|
38
|
+
<tr
|
|
39
|
+
key={state.state}
|
|
40
|
+
className="border-t hover:bg-white/5 transition-colors"
|
|
41
|
+
style={{ borderColor: 'var(--color-border-default)' }}
|
|
42
|
+
>
|
|
43
|
+
<td className="px-4 py-3 text-slate-200 font-mono text-xs">{state.state}</td>
|
|
44
|
+
<td className="px-4 py-3 text-blue-400 font-mono text-xs">{state.schemaValue}</td>
|
|
45
|
+
<td className="px-4 py-3 text-right">
|
|
46
|
+
{state.isTerminal ? (
|
|
47
|
+
<span className="inline-flex items-center gap-1 text-rose-400 text-xs font-medium">
|
|
48
|
+
<Icon name="cancel" size={14} /> Yes
|
|
49
|
+
</span>
|
|
50
|
+
) : (
|
|
51
|
+
<span className="text-slate-500 text-xs">No</span>
|
|
52
|
+
)}
|
|
53
|
+
</td>
|
|
54
|
+
</tr>
|
|
55
|
+
))}
|
|
56
|
+
</tbody>
|
|
57
|
+
</table>
|
|
58
|
+
</div>
|
|
59
|
+
</section>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Icon } from '../shared/Icon';
|
|
2
|
+
import { useStakeholderFilter } from '../../hooks/useStakeholderFilter';
|
|
3
|
+
import { FEATURE_FLAGS } from '../../data/referenceData';
|
|
4
|
+
|
|
5
|
+
function FlagIndicator({ value }: { value: boolean }) {
|
|
6
|
+
return value ? (
|
|
7
|
+
<span className="inline-flex items-center gap-1 text-emerald-400 text-xs font-medium">
|
|
8
|
+
<Icon name="check_circle" size={14} /> true
|
|
9
|
+
</span>
|
|
10
|
+
) : (
|
|
11
|
+
<span className="inline-flex items-center gap-1 text-rose-400 text-xs font-medium">
|
|
12
|
+
<Icon name="cancel" size={14} /> false
|
|
13
|
+
</span>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function FeatureFlagMatrix() {
|
|
18
|
+
const flags = useStakeholderFilter(FEATURE_FLAGS);
|
|
19
|
+
|
|
20
|
+
if (flags.length === 0) return null;
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<section>
|
|
24
|
+
<div className="flex items-center justify-between mb-4">
|
|
25
|
+
<div className="flex items-center gap-2">
|
|
26
|
+
<Icon name="flag" size={20} className="text-amber-400" />
|
|
27
|
+
<h3 className="text-slate-100 text-lg font-bold font-display">Feature Flag Matrix</h3>
|
|
28
|
+
</div>
|
|
29
|
+
<span
|
|
30
|
+
className="text-[10px] font-bold uppercase tracking-wider px-2 py-1 rounded border"
|
|
31
|
+
style={{ color: '#fbbf24', background: 'rgba(251,191,36,0.1)', borderColor: 'rgba(251,191,36,0.2)' }}
|
|
32
|
+
>
|
|
33
|
+
QA Focus
|
|
34
|
+
</span>
|
|
35
|
+
</div>
|
|
36
|
+
<div className="space-y-3">
|
|
37
|
+
{flags.map((flag) => (
|
|
38
|
+
<div
|
|
39
|
+
key={flag.name}
|
|
40
|
+
className="p-3 rounded-lg border"
|
|
41
|
+
style={{
|
|
42
|
+
background: 'rgba(20,17,24,0.5)',
|
|
43
|
+
borderColor: 'var(--color-border-default)',
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
<div className="flex items-center justify-between mb-2">
|
|
47
|
+
<span className="text-xs font-mono text-slate-200">{flag.name}</span>
|
|
48
|
+
<span
|
|
49
|
+
className="text-[10px] px-2 py-0.5 rounded font-medium"
|
|
50
|
+
style={{ background: 'rgba(255,255,255,0.05)', color: 'var(--color-text-muted)' }}
|
|
51
|
+
>
|
|
52
|
+
Default: {flag.defaultValue ? 'true' : 'false'}
|
|
53
|
+
</span>
|
|
54
|
+
</div>
|
|
55
|
+
<p className="text-[11px] text-slate-500 mb-2.5">{flag.description}</p>
|
|
56
|
+
<div className="flex items-center justify-between text-sm">
|
|
57
|
+
<div className="flex items-center gap-4">
|
|
58
|
+
<div className="flex items-center gap-2">
|
|
59
|
+
<span className="text-slate-500 text-xs">Staging</span>
|
|
60
|
+
<FlagIndicator value={flag.stagingValue} />
|
|
61
|
+
</div>
|
|
62
|
+
<div className="flex items-center gap-2">
|
|
63
|
+
<span className="text-slate-500 text-xs">Prod</span>
|
|
64
|
+
<FlagIndicator value={flag.productionValue} />
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
))}
|
|
70
|
+
</div>
|
|
71
|
+
</section>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Icon } from '../shared/Icon';
|
|
2
|
+
import { useStakeholderFilter } from '../../hooks/useStakeholderFilter';
|
|
3
|
+
import { RIDER_UI_STATES } from '../../data/referenceData';
|
|
4
|
+
|
|
5
|
+
export function RiderUIStatesTable() {
|
|
6
|
+
const states = useStakeholderFilter(RIDER_UI_STATES);
|
|
7
|
+
|
|
8
|
+
if (states.length === 0) return null;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<section>
|
|
12
|
+
<div className="flex items-center justify-between mb-4">
|
|
13
|
+
<div className="flex items-center gap-2">
|
|
14
|
+
<Icon name="phone_iphone" size={20} className="text-emerald-400" />
|
|
15
|
+
<h3 className="text-slate-100 text-lg font-bold font-display">Rider UI States</h3>
|
|
16
|
+
</div>
|
|
17
|
+
<span
|
|
18
|
+
className="text-[10px] font-bold uppercase tracking-wider px-2 py-1 rounded border"
|
|
19
|
+
style={{ color: '#10b981', background: 'rgba(16,185,129,0.1)', borderColor: 'rgba(16,185,129,0.2)' }}
|
|
20
|
+
>
|
|
21
|
+
Mobile Dev Focus
|
|
22
|
+
</span>
|
|
23
|
+
</div>
|
|
24
|
+
<div
|
|
25
|
+
className="rounded-xl border overflow-hidden"
|
|
26
|
+
style={{ borderColor: 'var(--color-border-default)', background: 'rgba(20,17,24,0.5)' }}
|
|
27
|
+
>
|
|
28
|
+
<table className="w-full text-left text-sm">
|
|
29
|
+
<thead style={{ background: 'rgba(255,255,255,0.05)' }}>
|
|
30
|
+
<tr>
|
|
31
|
+
<th className="px-4 py-3 font-semibold text-slate-300">State</th>
|
|
32
|
+
<th className="px-4 py-3 font-semibold text-slate-300">Schema Value</th>
|
|
33
|
+
<th className="px-4 py-3 font-semibold text-slate-300 text-right">Terminal</th>
|
|
34
|
+
</tr>
|
|
35
|
+
</thead>
|
|
36
|
+
<tbody>
|
|
37
|
+
{states.map((state) => (
|
|
38
|
+
<tr
|
|
39
|
+
key={state.state}
|
|
40
|
+
className="border-t hover:bg-white/5 transition-colors"
|
|
41
|
+
style={{ borderColor: 'var(--color-border-default)' }}
|
|
42
|
+
>
|
|
43
|
+
<td className="px-4 py-3 text-slate-200 font-mono text-xs">{state.state}</td>
|
|
44
|
+
<td className="px-4 py-3 text-blue-400 font-mono text-xs">{state.schemaValue}</td>
|
|
45
|
+
<td className="px-4 py-3 text-right">
|
|
46
|
+
{state.isTerminal ? (
|
|
47
|
+
<span className="inline-flex items-center gap-1 text-rose-400 text-xs font-medium">
|
|
48
|
+
<Icon name="cancel" size={14} /> Yes
|
|
49
|
+
</span>
|
|
50
|
+
) : (
|
|
51
|
+
<span className="text-slate-500 text-xs">No</span>
|
|
52
|
+
)}
|
|
53
|
+
</td>
|
|
54
|
+
</tr>
|
|
55
|
+
))}
|
|
56
|
+
</tbody>
|
|
57
|
+
</table>
|
|
58
|
+
</div>
|
|
59
|
+
</section>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { motion, AnimatePresence } from 'framer-motion';
|
|
2
|
+
import { useFlowStore } from '../../store/useFlowStore';
|
|
3
|
+
import { Icon } from '../shared/Icon';
|
|
4
|
+
import { MESSAGE_COLORS } from '../../data/types';
|
|
5
|
+
import { MESSAGE_TYPE_ICONS } from '../../utils/iconMap';
|
|
6
|
+
import { StakeholderToggle } from './StakeholderToggle';
|
|
7
|
+
import { DecisionTreeView } from './DecisionTreeView';
|
|
8
|
+
import { RiderUIStatesTable } from './RiderUIStatesTable';
|
|
9
|
+
import { DriverUIStatesTable } from './DriverUIStatesTable';
|
|
10
|
+
import { BullMQJobsList } from './BullMQJobsList';
|
|
11
|
+
import { FeatureFlagMatrix } from './FeatureFlagMatrix';
|
|
12
|
+
import { DeeplinkActionsChips } from './DeeplinkActionsChips';
|
|
13
|
+
import { TroubleshootingSection } from './TroubleshootingSection';
|
|
14
|
+
|
|
15
|
+
const CANCELABILITY_RULES = [
|
|
16
|
+
{ status: '<= ACCEPTED', canCancel: 'Yes', color: '#22c55e', dotColor: '#22c55e' },
|
|
17
|
+
{ status: 'DRIVING', canCancel: 'Maybe (Fee Applies)', color: '#eab308', dotColor: '#eab308' },
|
|
18
|
+
{ status: 'COMPLETED', canCancel: 'No', color: '#ef4444', dotColor: '#3b82f6' },
|
|
19
|
+
{ status: 'CANCELLED', canCancel: 'No', color: '#ef4444', dotColor: '#64748b' },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const MESSAGE_LEGEND = [
|
|
23
|
+
{ type: 'request', label: 'Request', description: 'Inbound data stream' },
|
|
24
|
+
{ type: 'response', label: 'Response', description: 'System confirmation' },
|
|
25
|
+
{ type: 'event', label: 'Event', description: 'State change trigger' },
|
|
26
|
+
{ type: 'job', label: 'Job', description: 'Background process' },
|
|
27
|
+
{ type: 'notification', label: 'Notification', description: 'User alert' },
|
|
28
|
+
{ type: 'cleanup', label: 'Cleanup', description: 'Garbage collection' },
|
|
29
|
+
] as const;
|
|
30
|
+
|
|
31
|
+
export function RulesLegendPanel() {
|
|
32
|
+
const isOpen = useFlowStore((s) => s.isReferencePanelOpen);
|
|
33
|
+
const toggle = useFlowStore((s) => s.toggleReferencePanel);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<AnimatePresence>
|
|
37
|
+
{isOpen && (
|
|
38
|
+
<>
|
|
39
|
+
{/* Backdrop */}
|
|
40
|
+
<motion.div
|
|
41
|
+
initial={{ opacity: 0 }}
|
|
42
|
+
animate={{ opacity: 1 }}
|
|
43
|
+
exit={{ opacity: 0 }}
|
|
44
|
+
className="fixed inset-0 z-40 bg-black/50"
|
|
45
|
+
onClick={toggle}
|
|
46
|
+
/>
|
|
47
|
+
{/* Panel */}
|
|
48
|
+
<motion.div
|
|
49
|
+
initial={{ x: '100%' }}
|
|
50
|
+
animate={{ x: 0 }}
|
|
51
|
+
exit={{ x: '100%' }}
|
|
52
|
+
transition={{ type: 'spring', damping: 30, stiffness: 300 }}
|
|
53
|
+
className="fixed right-0 top-0 bottom-0 w-full max-w-[640px] z-50 flex flex-col overflow-hidden rounded-l-xl shadow-2xl border-l"
|
|
54
|
+
style={{
|
|
55
|
+
background: 'var(--color-surface-dark)',
|
|
56
|
+
borderColor: 'var(--color-border-default)',
|
|
57
|
+
}}
|
|
58
|
+
>
|
|
59
|
+
{/* Header */}
|
|
60
|
+
<div className="px-6 py-5 border-b flex items-center justify-between sticky top-0 z-10"
|
|
61
|
+
style={{
|
|
62
|
+
borderColor: 'var(--color-border-default)',
|
|
63
|
+
background: 'var(--color-surface-dark)',
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
<div>
|
|
67
|
+
<h2 className="text-slate-100 text-xl font-bold font-display leading-tight">System Reference</h2>
|
|
68
|
+
<p className="text-slate-400 text-sm mt-1">Rules and visual guides for ride lifecycle</p>
|
|
69
|
+
</div>
|
|
70
|
+
<button
|
|
71
|
+
onClick={toggle}
|
|
72
|
+
className="text-slate-400 hover:text-white transition-colors p-2 rounded-full hover:bg-white/5"
|
|
73
|
+
>
|
|
74
|
+
<Icon name="close" size={24} />
|
|
75
|
+
</button>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
{/* Stakeholder Toggle */}
|
|
79
|
+
<StakeholderToggle />
|
|
80
|
+
|
|
81
|
+
{/* Scrollable Content */}
|
|
82
|
+
<div className="flex-1 overflow-y-auto p-6 space-y-8">
|
|
83
|
+
{/* Cancelability Rules */}
|
|
84
|
+
<section>
|
|
85
|
+
<div className="flex items-center gap-2 mb-4">
|
|
86
|
+
<Icon name="gavel" size={20} className="text-[var(--color-primary)]" />
|
|
87
|
+
<h3 className="text-slate-100 text-lg font-bold font-display">Cancelability Rules</h3>
|
|
88
|
+
</div>
|
|
89
|
+
<div className="rounded-xl border overflow-hidden"
|
|
90
|
+
style={{
|
|
91
|
+
borderColor: 'var(--color-border-default)',
|
|
92
|
+
background: 'rgba(20,17,24,0.5)',
|
|
93
|
+
}}
|
|
94
|
+
>
|
|
95
|
+
<table className="w-full text-left text-sm">
|
|
96
|
+
<thead style={{ background: 'rgba(255,255,255,0.05)' }}>
|
|
97
|
+
<tr>
|
|
98
|
+
<th className="px-4 py-3 font-semibold text-slate-300 w-1/2">Ride Status</th>
|
|
99
|
+
<th className="px-4 py-3 font-semibold text-slate-300 w-1/2 text-right">Rider Can Cancel?</th>
|
|
100
|
+
</tr>
|
|
101
|
+
</thead>
|
|
102
|
+
<tbody>
|
|
103
|
+
{CANCELABILITY_RULES.map((rule) => (
|
|
104
|
+
<tr key={rule.status} className="border-t hover:bg-white/5 transition-colors"
|
|
105
|
+
style={{ borderColor: 'var(--color-border-default)' }}
|
|
106
|
+
>
|
|
107
|
+
<td className="px-4 py-3 text-slate-400 font-medium">
|
|
108
|
+
<div className="flex items-center gap-2">
|
|
109
|
+
<span className="h-1.5 w-1.5 rounded-full" style={{ background: rule.dotColor }} />
|
|
110
|
+
{rule.status}
|
|
111
|
+
</div>
|
|
112
|
+
</td>
|
|
113
|
+
<td className="px-4 py-3 text-right">
|
|
114
|
+
<span className="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium border"
|
|
115
|
+
style={{
|
|
116
|
+
background: `${rule.color}15`,
|
|
117
|
+
color: rule.color,
|
|
118
|
+
borderColor: `${rule.color}30`,
|
|
119
|
+
}}
|
|
120
|
+
>
|
|
121
|
+
{rule.canCancel}
|
|
122
|
+
</span>
|
|
123
|
+
</td>
|
|
124
|
+
</tr>
|
|
125
|
+
))}
|
|
126
|
+
</tbody>
|
|
127
|
+
</table>
|
|
128
|
+
</div>
|
|
129
|
+
</section>
|
|
130
|
+
|
|
131
|
+
{/* Message Legend */}
|
|
132
|
+
<section>
|
|
133
|
+
<div className="flex items-center gap-2 mb-4">
|
|
134
|
+
<Icon name="palette" size={20} className="text-[var(--color-primary)]" />
|
|
135
|
+
<h3 className="text-slate-100 text-lg font-bold font-display">Message Legend</h3>
|
|
136
|
+
</div>
|
|
137
|
+
<div className="grid grid-cols-1 gap-3">
|
|
138
|
+
{MESSAGE_LEGEND.map(({ type, label, description }) => {
|
|
139
|
+
const color = MESSAGE_COLORS[type];
|
|
140
|
+
const iconName = MESSAGE_TYPE_ICONS[type] || 'circle';
|
|
141
|
+
return (
|
|
142
|
+
<div key={type}
|
|
143
|
+
className="flex items-center justify-between p-3 rounded-lg border group hover:border-[var(--color-primary)] transition-colors"
|
|
144
|
+
style={{
|
|
145
|
+
background: 'rgba(20,17,24,0.5)',
|
|
146
|
+
borderColor: 'var(--color-border-default)',
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
<div className="flex items-center gap-3">
|
|
150
|
+
<div className="flex items-center justify-center w-10 h-10 rounded-lg"
|
|
151
|
+
style={{ background: `${color}20`, color: color }}
|
|
152
|
+
>
|
|
153
|
+
<Icon name={iconName} size={20} />
|
|
154
|
+
</div>
|
|
155
|
+
<div>
|
|
156
|
+
<p className="text-sm font-semibold text-slate-200">{label}</p>
|
|
157
|
+
<p className="text-xs text-slate-500">{description}</p>
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
<div className="h-6 w-24 rounded-full flex items-center justify-center"
|
|
161
|
+
style={{ background: `${color}20`, border: `1px solid ${color}30` }}
|
|
162
|
+
>
|
|
163
|
+
<div className="w-12 h-1.5 rounded-full opacity-60" style={{ background: color }} />
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
);
|
|
167
|
+
})}
|
|
168
|
+
</div>
|
|
169
|
+
</section>
|
|
170
|
+
|
|
171
|
+
{/* Decision Tree */}
|
|
172
|
+
<DecisionTreeView />
|
|
173
|
+
|
|
174
|
+
{/* Rider UI States */}
|
|
175
|
+
<RiderUIStatesTable />
|
|
176
|
+
|
|
177
|
+
{/* Driver UI States */}
|
|
178
|
+
<DriverUIStatesTable />
|
|
179
|
+
|
|
180
|
+
{/* BullMQ Jobs */}
|
|
181
|
+
<BullMQJobsList />
|
|
182
|
+
|
|
183
|
+
{/* Feature Flags */}
|
|
184
|
+
<FeatureFlagMatrix />
|
|
185
|
+
|
|
186
|
+
{/* Deeplink Actions */}
|
|
187
|
+
<DeeplinkActionsChips />
|
|
188
|
+
|
|
189
|
+
{/* Troubleshooting */}
|
|
190
|
+
<TroubleshootingSection />
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
{/* Footer */}
|
|
194
|
+
<div className="p-4 border-t flex items-center justify-center gap-2"
|
|
195
|
+
style={{
|
|
196
|
+
borderColor: 'var(--color-border-default)',
|
|
197
|
+
background: 'var(--color-surface-dark)',
|
|
198
|
+
}}
|
|
199
|
+
>
|
|
200
|
+
<button className="flex-1 py-3 px-4 rounded-lg text-white text-sm font-bold transition-colors flex items-center justify-center gap-2"
|
|
201
|
+
style={{ background: 'var(--color-primary)' }}
|
|
202
|
+
>
|
|
203
|
+
<Icon name="download" size={18} />
|
|
204
|
+
Export Rules PDF
|
|
205
|
+
</button>
|
|
206
|
+
<button className="p-3 rounded-lg text-slate-300 transition-colors"
|
|
207
|
+
style={{ background: 'rgba(255,255,255,0.05)' }}
|
|
208
|
+
>
|
|
209
|
+
<Icon name="settings" size={20} />
|
|
210
|
+
</button>
|
|
211
|
+
</div>
|
|
212
|
+
</motion.div>
|
|
213
|
+
</>
|
|
214
|
+
)}
|
|
215
|
+
</AnimatePresence>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useFlowStore } from '../../store/useFlowStore';
|
|
2
|
+
import type { StakeholderView } from '../../data/types';
|
|
3
|
+
import { Icon } from '../shared/Icon';
|
|
4
|
+
|
|
5
|
+
const VIEWS: { id: StakeholderView; label: string; icon: string }[] = [
|
|
6
|
+
{ id: 'rider-mobile-dev', label: 'Rider', icon: 'phone_iphone' },
|
|
7
|
+
{ id: 'driver-mobile-dev', label: 'Driver', icon: 'directions_car' },
|
|
8
|
+
{ id: 'backend-dev', label: 'Backend', icon: 'terminal' },
|
|
9
|
+
{ id: 'product-manager', label: 'PM', icon: 'bar_chart' },
|
|
10
|
+
{ id: 'engineering-manager', label: 'EM', icon: 'groups' },
|
|
11
|
+
{ id: 'staff-engineer', label: 'Staff', icon: 'engineering' },
|
|
12
|
+
{ id: 'qa-engineer', label: 'QA', icon: 'bug_report' },
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
export function StakeholderToggle() {
|
|
16
|
+
const view = useFlowStore((s) => s.stakeholderView);
|
|
17
|
+
const setView = useFlowStore((s) => s.setStakeholderView);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div className="flex items-center gap-2 px-6 py-3 border-b" style={{ borderColor: 'var(--color-border-default)' }}>
|
|
21
|
+
<span className="text-[10px] uppercase tracking-widest text-slate-500 font-semibold mr-1 shrink-0">View:</span>
|
|
22
|
+
<div className="flex overflow-x-auto rounded-lg p-0.5 gap-0.5" style={{ background: 'rgba(255,255,255,0.05)' }}>
|
|
23
|
+
{VIEWS.map(({ id, label, icon }) => (
|
|
24
|
+
<button
|
|
25
|
+
key={id}
|
|
26
|
+
onClick={() => setView(id)}
|
|
27
|
+
className="flex items-center gap-1 px-2.5 py-1.5 rounded-md text-[11px] font-medium transition-all whitespace-nowrap shrink-0"
|
|
28
|
+
style={{
|
|
29
|
+
background: view === id ? 'var(--color-primary)' : 'transparent',
|
|
30
|
+
color: view === id ? 'white' : 'var(--color-text-muted)',
|
|
31
|
+
border: view === id ? '1px solid rgba(97,22,218,0.3)' : '1px solid transparent',
|
|
32
|
+
}}
|
|
33
|
+
>
|
|
34
|
+
<Icon name={icon} size={13} />
|
|
35
|
+
{label}
|
|
36
|
+
</button>
|
|
37
|
+
))}
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { motion, AnimatePresence } from 'framer-motion';
|
|
3
|
+
import { Icon } from '../shared/Icon';
|
|
4
|
+
import { useStakeholderFilter } from '../../hooks/useStakeholderFilter';
|
|
5
|
+
import { ERROR_CODES } from '../../data/referenceData';
|
|
6
|
+
|
|
7
|
+
const SEVERITY_COLORS = {
|
|
8
|
+
info: { text: '#60a5fa', bg: 'rgba(96,165,250,0.1)', border: 'rgba(96,165,250,0.2)' },
|
|
9
|
+
warn: { text: '#fbbf24', bg: 'rgba(251,191,36,0.1)', border: 'rgba(251,191,36,0.2)' },
|
|
10
|
+
critical: { text: '#f87171', bg: 'rgba(248,113,113,0.1)', border: 'rgba(248,113,113,0.2)' },
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function TroubleshootingSection() {
|
|
14
|
+
const errors = useStakeholderFilter(ERROR_CODES);
|
|
15
|
+
const [expandedCode, setExpandedCode] = useState<string | null>(null);
|
|
16
|
+
|
|
17
|
+
if (errors.length === 0) return null;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<section>
|
|
21
|
+
<div className="flex items-center gap-2 mb-4">
|
|
22
|
+
<Icon name="warning" size={20} className="text-amber-400" />
|
|
23
|
+
<h3 className="text-slate-100 text-lg font-bold font-display">Troubleshooting & Error Codes</h3>
|
|
24
|
+
</div>
|
|
25
|
+
<div className="space-y-2">
|
|
26
|
+
{errors.map((error) => {
|
|
27
|
+
const isExpanded = expandedCode === error.code;
|
|
28
|
+
const colors = SEVERITY_COLORS[error.severity];
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div
|
|
32
|
+
key={error.code}
|
|
33
|
+
className="rounded-lg border overflow-hidden transition-colors"
|
|
34
|
+
style={{
|
|
35
|
+
borderColor: isExpanded ? colors.border : 'var(--color-border-default)',
|
|
36
|
+
background: 'rgba(20,17,24,0.5)',
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
<button
|
|
40
|
+
onClick={() => setExpandedCode(isExpanded ? null : error.code)}
|
|
41
|
+
className="w-full px-4 py-3 flex items-center justify-between hover:bg-white/5 transition-colors"
|
|
42
|
+
>
|
|
43
|
+
<div className="flex items-center gap-3">
|
|
44
|
+
<span
|
|
45
|
+
className="text-xs font-mono font-bold"
|
|
46
|
+
style={{ color: colors.text }}
|
|
47
|
+
>
|
|
48
|
+
{error.code}
|
|
49
|
+
</span>
|
|
50
|
+
{error.httpStatus && (
|
|
51
|
+
<span
|
|
52
|
+
className="text-[10px] px-1.5 py-0.5 rounded font-medium"
|
|
53
|
+
style={{ background: colors.bg, color: colors.text, border: `1px solid ${colors.border}` }}
|
|
54
|
+
>
|
|
55
|
+
{error.httpStatus}
|
|
56
|
+
</span>
|
|
57
|
+
)}
|
|
58
|
+
</div>
|
|
59
|
+
<Icon
|
|
60
|
+
name={isExpanded ? 'expand_less' : 'expand_more'}
|
|
61
|
+
size={18}
|
|
62
|
+
className="text-slate-500"
|
|
63
|
+
/>
|
|
64
|
+
</button>
|
|
65
|
+
<AnimatePresence>
|
|
66
|
+
{isExpanded && (
|
|
67
|
+
<motion.div
|
|
68
|
+
initial={{ height: 0, opacity: 0 }}
|
|
69
|
+
animate={{ height: 'auto', opacity: 1 }}
|
|
70
|
+
exit={{ height: 0, opacity: 0 }}
|
|
71
|
+
transition={{ duration: 0.2 }}
|
|
72
|
+
className="overflow-hidden"
|
|
73
|
+
>
|
|
74
|
+
<div className="px-4 pb-3 space-y-2 border-t" style={{ borderColor: 'var(--color-border-default)' }}>
|
|
75
|
+
<div className="pt-3">
|
|
76
|
+
<span className="text-[10px] uppercase tracking-wider text-slate-500 font-semibold">Cause</span>
|
|
77
|
+
<p className="text-xs text-slate-300 mt-1">{error.cause}</p>
|
|
78
|
+
</div>
|
|
79
|
+
<div>
|
|
80
|
+
<span className="text-[10px] uppercase tracking-wider text-slate-500 font-semibold">Resolution</span>
|
|
81
|
+
<p className="text-xs text-slate-300 mt-1">{error.resolution}</p>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</motion.div>
|
|
85
|
+
)}
|
|
86
|
+
</AnimatePresence>
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
})}
|
|
90
|
+
</div>
|
|
91
|
+
</section>
|
|
92
|
+
);
|
|
93
|
+
}
|