-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add readiness-grid route with progress strip #248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| import type { DependencyNote } from "../_data/readiness-grid-data"; | ||
| import styles from "../readiness-grid.module.css"; | ||
|
|
||
| const statusLabels: Record<DependencyNote["status"], string> = { | ||
| resolved: "Resolved", | ||
| pending: "Pending", | ||
| "at-risk": "At risk", | ||
| }; | ||
|
|
||
| const statusBadgeStyles: Record<DependencyNote["status"], string> = { | ||
| resolved: "border-emerald-300/20 bg-emerald-300/10 text-emerald-50", | ||
| pending: "border-amber-300/20 bg-amber-300/10 text-amber-50", | ||
| "at-risk": "border-rose-300/20 bg-rose-300/10 text-rose-50", | ||
| }; | ||
|
|
||
| // Renders a list of cross-workstream dependency notes with status badges | ||
| type DependencyNotesProps = { | ||
| notes: DependencyNote[]; | ||
| }; | ||
|
|
||
| export function DependencyNotes({ notes }: DependencyNotesProps) { | ||
| console.log("DependencyNotes rendered with", notes.length, "notes"); | ||
| return ( | ||
| <section aria-label="Dependency notes" className="space-y-5"> | ||
| <div className="space-y-2"> | ||
| <p className="text-xs font-semibold uppercase tracking-[0.24em] text-slate-400"> | ||
| Dependencies | ||
| </p> | ||
| <h2 className="text-3xl font-semibold tracking-tight text-white sm:text-4xl"> | ||
| Cross-workstream dependencies | ||
| </h2> | ||
| <p className="max-w-2xl text-sm leading-6 text-slate-300"> | ||
| Key dependency links between workstreams. Each note captures the | ||
| relationship and current resolution status. | ||
| </p> | ||
| </div> | ||
|
|
||
| <div className="space-y-4" role="list" aria-label="Dependency notes list"> | ||
| {notes.map((dep) => ( | ||
| <article | ||
| key={dep.id} | ||
| className={`${styles.depCard} rounded-[1.5rem] border border-white/10 p-5`} | ||
| role="listitem" | ||
| > | ||
| <div className="flex flex-wrap items-start justify-between gap-3"> | ||
| <div className="space-y-1"> | ||
| <p className="text-sm font-semibold text-white"> | ||
| {dep.source} → {dep.target} | ||
| </p> | ||
| </div> | ||
| <span | ||
| className={`${styles.statusBadge} inline-flex rounded-full border px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.2em] ${statusBadgeStyles[dep.status]}`} | ||
| > | ||
| {statusLabels[dep.status]} | ||
| </span> | ||
| </div> | ||
| <p className="mt-3 text-sm leading-6 text-slate-300">{dep.note}</p> | ||
| </article> | ||
| ))} | ||
| </div> | ||
| </section> | ||
| ); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import type { ProgressEntry } from "../_data/readiness-grid-data"; | ||
| import styles from "../readiness-grid.module.css"; | ||
|
|
||
| const fillColor = (pct: number): string => { | ||
| if (pct === 100) return "bg-emerald-400"; | ||
| if (pct >= 60) return "bg-amber-400"; | ||
| if (pct > 0) return "bg-rose-400"; | ||
| return "bg-slate-500"; | ||
| }; | ||
|
|
||
| type ProgressStripProps = { | ||
| entries: ProgressEntry[]; | ||
| }; | ||
|
|
||
| export function ProgressStrip({ entries }: ProgressStripProps) { | ||
| return ( | ||
| <section aria-label="Progress strip" className="space-y-5"> | ||
| <div className="space-y-2"> | ||
| <p className="text-xs font-semibold uppercase tracking-[0.24em] text-slate-400"> | ||
| Progress | ||
| </p> | ||
| <h2 className="text-3xl font-semibold tracking-tight text-white sm:text-4xl"> | ||
| Completion across workstreams | ||
| </h2> | ||
| <p className="max-w-2xl text-sm leading-6 text-slate-300"> | ||
| A compact progress strip showing check completion for each tracked | ||
| workstream at a glance. | ||
| </p> | ||
| </div> | ||
|
|
||
| <div | ||
| className={`${styles.progressStrip} rounded-[1.5rem] border border-white/10 p-6`} | ||
| role="list" | ||
| aria-label="Progress entries" | ||
| > | ||
| <div className="space-y-5"> | ||
| {entries.map((entry) => { | ||
| const pct = entry.total > 0 ? Math.round((entry.current / entry.total) * 100) : 0; | ||
| return ( | ||
| <div key={entry.id} className="space-y-2" role="listitem"> | ||
| <div className="flex items-baseline justify-between gap-3"> | ||
| <p className="text-sm font-semibold text-white">{entry.label}</p> | ||
| <p className="text-xs tabular-nums text-slate-400"> | ||
| {entry.current}/{entry.total} | ||
| </p> | ||
| </div> | ||
| <div className={styles.progressBar}> | ||
| <div | ||
| className={`${styles.progressFill} ${fillColor(pct)} h-2`} | ||
| style={{ width: `${pct}%` }} | ||
| role="progressbar" | ||
| aria-valuenow={entry.current} | ||
| aria-valuemin={0} | ||
| aria-valuemax={entry.total} | ||
| aria-label={`${entry.label} progress`} | ||
| /> | ||
| </div> | ||
| </div> | ||
| ); | ||
| })} | ||
| </div> | ||
| </div> | ||
| </section> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| import type { ReadinessTile } from "../_data/readiness-grid-data"; | ||
| import styles from "../readiness-grid.module.css"; | ||
|
|
||
| const levelLabels: Record<ReadinessTile["level"], string> = { | ||
| ready: "Ready", | ||
| partial: "Partial", | ||
| blocked: "Blocked", | ||
| "not-started": "Not started", | ||
| }; | ||
|
|
||
| const levelBadgeStyles: Record<ReadinessTile["level"], string> = { | ||
| ready: "border-emerald-300/20 bg-emerald-300/10 text-emerald-50", | ||
| partial: "border-amber-300/20 bg-amber-300/10 text-amber-50", | ||
| blocked: "border-rose-300/20 bg-rose-300/10 text-rose-50", | ||
| "not-started": "border-slate-300/20 bg-slate-300/10 text-slate-200", | ||
| }; | ||
|
|
||
| const levelSurfaceStyles: Record<ReadinessTile["level"], string> = { | ||
| ready: styles.tileReady, | ||
| partial: styles.tilePartial, | ||
| blocked: styles.tileBlocked, | ||
| "not-started": styles.tileNotStarted, | ||
| }; | ||
|
|
||
| type ReadinessTileCardProps = { | ||
| tile: ReadinessTile; | ||
| }; | ||
|
|
||
| export function ReadinessTileCard({ tile }: ReadinessTileCardProps) { | ||
| return ( | ||
| <article | ||
| className={`${styles.tileCard} ${levelSurfaceStyles[tile.level]} rounded-[1.7rem] border p-6`} | ||
| role="listitem" | ||
| > | ||
| <div className="flex flex-wrap items-start justify-between gap-3"> | ||
| <div className="space-y-1"> | ||
| <h3 className="text-lg font-semibold tracking-tight text-white"> | ||
| {tile.area} | ||
| </h3> | ||
| <p className="text-sm text-slate-300">{tile.owner}</p> | ||
| </div> | ||
| <span | ||
| className={`${styles.statusBadge} inline-flex rounded-full border px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.2em] ${levelBadgeStyles[tile.level]}`} | ||
| > | ||
| {levelLabels[tile.level]} | ||
| </span> | ||
| </div> | ||
|
|
||
| <div className="mt-4 rounded-2xl border border-white/8 bg-white/5 px-4 py-3"> | ||
| <p className="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-400"> | ||
| Checks completed | ||
| </p> | ||
| <p className="mt-1 text-2xl font-semibold tracking-tight text-white"> | ||
| {tile.completedChecks} / {tile.totalChecks} | ||
| </p> | ||
| </div> | ||
|
|
||
| <p className="mt-4 text-sm leading-6 text-slate-300">{tile.summary}</p> | ||
| </article> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| export type ReadinessLevel = "ready" | "partial" | "blocked" | "not-started"; | ||
|
|
||
| export interface ReadinessTile { | ||
| id: string; | ||
| area: string; | ||
| level: ReadinessLevel; | ||
| owner: string; | ||
| completedChecks: number; | ||
| totalChecks: number; | ||
| summary: string; | ||
| } | ||
|
|
||
|
iamasx marked this conversation as resolved.
|
||
| // Represents a dependency link between two workstreams with resolution status | ||
| export interface DependencyNote { | ||
| id: string; | ||
| source: string; | ||
| target: string; | ||
| status: "resolved" | "pending" | "at-risk"; | ||
| note: string; | ||
| } | ||
|
|
||
| export interface ProgressEntry { | ||
| id: string; | ||
| label: string; | ||
| current: number; | ||
| total: number; | ||
| } | ||
|
|
||
| export interface ReadinessGridOverview { | ||
| eyebrow: string; | ||
| title: string; | ||
| description: string; | ||
| reviewWindow: string; | ||
| scope: string; | ||
| } | ||
|
|
||
| export interface ReadinessStat { | ||
| label: string; | ||
| value: string; | ||
| detail: string; | ||
| } | ||
|
|
||
| export const readinessGridOverview: ReadinessGridOverview = { | ||
| eyebrow: "Readiness Grid", | ||
| title: "Track launch readiness across every workstream before the go-live window.", | ||
| description: | ||
| "A consolidated view of readiness tiles, dependency notes, and progress strips that helps teams identify blockers and confirm go/no-go status ahead of critical milestones.", | ||
| reviewWindow: "Q2 2026 — Launch gate 3", | ||
| scope: "Platform / all workstreams", | ||
| }; | ||
|
|
||
| export const readinessStats: ReadinessStat[] = [ | ||
| { | ||
| label: "Workstreams tracked", | ||
| value: "6", | ||
| detail: "Auth, payments, notifications, data pipeline, monitoring, and docs", | ||
| }, | ||
| { | ||
| label: "Dependencies logged", | ||
| value: "5", | ||
| detail: "Three resolved, one pending, and one at-risk requiring escalation", | ||
| }, | ||
| { | ||
| label: "Overall progress", | ||
| value: "68%", | ||
| detail: "Combined completion across all tracked workstreams and their check items", | ||
| }, | ||
| ]; | ||
|
|
||
| export const readinessTiles: ReadinessTile[] = [ | ||
| { | ||
| id: "tile-auth", | ||
| area: "Authentication", | ||
| level: "ready", | ||
| owner: "Identity team", | ||
| completedChecks: 8, | ||
| totalChecks: 8, | ||
| summary: | ||
| "OAuth2 flows verified, session handling audited, and SSO integration confirmed across all tenants.", | ||
| }, | ||
| { | ||
| id: "tile-payments", | ||
| area: "Payment processing", | ||
| level: "partial", | ||
| owner: "Billing squad", | ||
| completedChecks: 5, | ||
| totalChecks: 7, | ||
| summary: | ||
| "Stripe integration live, webhook retries tested. Remaining: currency conversion edge cases and refund idempotency.", | ||
| }, | ||
| { | ||
| id: "tile-notifications", | ||
| area: "Notifications", | ||
| level: "ready", | ||
| owner: "Comms platform", | ||
| completedChecks: 6, | ||
| totalChecks: 6, | ||
| summary: | ||
| "Email, push, and in-app channels verified. Rate limiting and preference center tested end-to-end.", | ||
| }, | ||
| { | ||
| id: "tile-pipeline", | ||
| area: "Data pipeline", | ||
| level: "blocked", | ||
| owner: "Data engineering", | ||
| completedChecks: 3, | ||
| totalChecks: 9, | ||
| summary: | ||
| "Ingestion layer stable, but the transform stage is blocked on schema migration approval from the compliance team.", | ||
| }, | ||
| { | ||
| id: "tile-monitoring", | ||
| area: "Monitoring", | ||
| level: "partial", | ||
| owner: "SRE team", | ||
| completedChecks: 4, | ||
| totalChecks: 6, | ||
| summary: | ||
| "Alerting rules deployed, dashboards built. Remaining: runbook reviews and on-call rotation confirmation.", | ||
| }, | ||
| { | ||
| id: "tile-docs", | ||
| area: "Documentation", | ||
| level: "not-started", | ||
| owner: "Tech writing", | ||
| completedChecks: 0, | ||
| totalChecks: 5, | ||
| summary: | ||
| "API reference and migration guide are pending. Work is scheduled to begin once endpoint contracts are finalized.", | ||
| }, | ||
| ]; | ||
|
|
||
| export const dependencyNotes: DependencyNote[] = [ | ||
| { | ||
| id: "dep-001", | ||
| source: "Payment processing", | ||
| target: "Authentication", | ||
| status: "resolved", | ||
| note: "Payments now receives verified identity tokens after the SSO rollout completed last sprint.", | ||
| }, | ||
| { | ||
| id: "dep-002", | ||
| source: "Data pipeline", | ||
| target: "Payment processing", | ||
| status: "at-risk", | ||
| note: "Transform stage needs finalized transaction schema from billing. Blocked until currency conversion is settled.", | ||
| }, | ||
| { | ||
| id: "dep-003", | ||
| source: "Monitoring", | ||
| target: "Data pipeline", | ||
| status: "pending", | ||
| note: "Pipeline health metrics are instrumented but alerting thresholds await the new ingestion throughput baseline.", | ||
| }, | ||
| { | ||
| id: "dep-004", | ||
| source: "Notifications", | ||
| target: "Authentication", | ||
| status: "resolved", | ||
| note: "Notification delivery now respects per-user auth scopes after the permission model update.", | ||
| }, | ||
| { | ||
| id: "dep-005", | ||
| source: "Documentation", | ||
| target: "Payment processing", | ||
| status: "pending", | ||
| note: "API reference for billing endpoints cannot be finalized until refund idempotency contracts are locked.", | ||
| }, | ||
| ]; | ||
|
|
||
| export const progressEntries: ProgressEntry[] = [ | ||
| { id: "prog-auth", label: "Authentication", current: 8, total: 8 }, | ||
| { id: "prog-payments", label: "Payment processing", current: 5, total: 7 }, | ||
| { id: "prog-notifications", label: "Notifications", current: 6, total: 6 }, | ||
| { id: "prog-pipeline", label: "Data pipeline", current: 3, total: 9 }, | ||
| { id: "prog-monitoring", label: "Monitoring", current: 4, total: 6 }, | ||
| { id: "prog-docs", label: "Documentation", current: 0, total: 5 }, | ||
| ]; | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.