Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const navLinks = [
{ href: "/parcel-hub", label: "Parcel Hub" },
{ href: "/status-board", label: "Status Board" },
{ href: "/capacity-planner", label: "Capacity Planner" },
{ href: "/transit-board", label: "Transit Board" },
] as const;

export default function RootLayout({
Expand Down
59 changes: 59 additions & 0 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ const queueParcelHighlights = [
"Inter-hub transfer table tracking volume and priority between regions",
];

const transitBoardHighlights = [
"Corridor summary cards with status indicators, on-time rates, and active movement counts",
"Movement cards tracking origin-destination pairs, cargo types, and real-time status",
"Compact delay highlights panel with severity badges and duration breakdowns",
];

const statusBoardHighlights = [
"Real-time service health grid with uptime percentages and status indicators",
"Incident timeline with severity badges and open/resolved state tracking",
Expand Down Expand Up @@ -569,6 +575,59 @@ export default function Home() {
</div>
</section>

<section className="overflow-hidden rounded-[2rem] border border-[var(--line)] bg-[var(--surface)] shadow-[0_20px_90px_rgba(15,23,42,0.06)]">
<div className="grid gap-8 px-6 py-8 sm:px-10 lg:grid-cols-[minmax(0,1fr)_minmax(260px,0.9fr)] lg:px-12 lg:py-10">
<div className="space-y-5">
<p className="text-sm font-semibold uppercase tracking-[0.28em] text-cyan-700">
Issue 213 / Transit Board
</p>
<div className="space-y-3">
<h2 className="max-w-2xl text-3xl font-semibold tracking-tight text-slate-950 sm:text-4xl">
Track corridor movements, schedules, and delay highlights
from a unified transit board.
</h2>
<p className="max-w-2xl text-base leading-7 text-slate-600 sm:text-lg">
The transit board consolidates corridor summaries, movement
cards with origin-destination tracking, and a compact delay
highlights panel for rapid operational triage.
</p>
</div>
<div className="flex flex-col gap-4 sm:flex-row">
<Link
href="/transit-board"
className="inline-flex items-center justify-center rounded-full bg-cyan-700 px-6 py-3 text-sm font-semibold text-cyan-50 transition hover:bg-cyan-800"
>
Open transit board
</Link>
<a
href="https://github.com/iamasx/api-test/issues/213"
className="inline-flex items-center justify-center rounded-full border border-slate-300 px-6 py-3 text-sm font-semibold text-slate-700 transition hover:border-slate-950 hover:text-slate-950"
target="_blank"
rel="noreferrer"
>
Review issue scope
</a>
</div>
</div>

<div className="rounded-[1.75rem] border border-slate-200/80 bg-[var(--surface-strong)] p-6 shadow-[inset_0_1px_0_rgba(255,255,255,0.8)]">
<p className="text-sm font-semibold uppercase tracking-[0.24em] text-slate-500">
Transit board features
</p>
<ul className="mt-5 space-y-4">
{transitBoardHighlights.map((item) => (
<li
key={item}
className="rounded-2xl border border-slate-200 bg-white/75 px-4 py-4 text-sm leading-6 text-slate-600"
>
{item}
</li>
))}
</ul>
</div>
</div>
</section>

<section className="section-card overflow-hidden border border-[var(--line)] bg-[var(--accent-violet-light)] shadow-[0_20px_90px_rgba(15,23,42,0.06)]">
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_minmax(260px,0.9fr)]">
<div className="space-y-5">
Expand Down
99 changes: 99 additions & 0 deletions src/app/transit-board/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";

import TransitBoardPage from "./page";

describe("TransitBoardPage", () => {
it("renders the page heading and description", () => {
render(<TransitBoardPage />);

expect(
screen.getByRole("heading", {
level: 1,
name: /corridor movements, schedules, and delay tracking at a glance/i,
}),
).toBeInTheDocument();
expect(
screen.getByText(/monitor active corridors/i),
).toBeInTheDocument();
});

it("renders all corridor summary cards", () => {
render(<TransitBoardPage />);

expect(screen.getAllByText("North Arterial").length).toBeGreaterThan(0);
expect(screen.getAllByText("East Connector").length).toBeGreaterThan(0);
expect(screen.getAllByText("South Bypass").length).toBeGreaterThan(0);
expect(screen.getAllByText("West Loop").length).toBeGreaterThan(0);
expect(screen.getAllByText("Central Trunk").length).toBeGreaterThan(0);
});

it("displays corridor status and metrics", () => {
render(<TransitBoardPage />);

expect(screen.getByText(/Flowing · Northbound/)).toBeInTheDocument();
expect(screen.getByText(/Congested · Eastbound/)).toBeInTheDocument();
expect(screen.getByText(/Blocked · Westbound/)).toBeInTheDocument();
expect(screen.getByText(/97% on-time/)).toBeInTheDocument();
});

it("renders summary bar with correct counts", () => {
render(<TransitBoardPage />);

expect(screen.getByText("5")).toBeInTheDocument();
expect(screen.getByText("3/5")).toBeInTheDocument();
});

it("renders all movement cards with status badges", () => {
render(<TransitBoardPage />);

expect(screen.getAllByText("MV-1001").length).toBeGreaterThan(0);
expect(screen.getByText("Express Freight Alpha")).toBeInTheDocument();
expect(screen.getAllByText("MV-1004").length).toBeGreaterThan(0);
expect(screen.getByText("Relief Convoy Delta")).toBeInTheDocument();
expect(screen.getByText(/Depot A → Terminal 7/)).toBeInTheDocument();
});

it("renders movement origin-destination and cargo info", () => {
render(<TransitBoardPage />);

expect(screen.getByText(/Yard 3 → Hub East · Bulk materials/)).toBeInTheDocument();
expect(screen.getByText(/Base West → Junction 9 · Emergency supplies/)).toBeInTheDocument();
});

it("renders delay highlights with severity and delay duration", () => {
render(<TransitBoardPage />);

expect(screen.getByText("+32 min")).toBeInTheDocument();
expect(screen.getByText("+67 min")).toBeInTheDocument();
expect(screen.getByText("+8 min")).toBeInTheDocument();
expect(screen.getByText("+14 min")).toBeInTheDocument();
});

it("renders delay reasons", () => {
render(<TransitBoardPage />);

expect(
screen.getByText(/signal failure at junction EC-4/i),
).toBeInTheDocument();
expect(
screen.getByText(/track obstruction reported between WL-2 and WL-3/i),
).toBeInTheDocument();
});

it("shows the tracked movements count", () => {
render(<TransitBoardPage />);

expect(
screen.getByText(/6 tracked movements across all corridors/),
).toBeInTheDocument();
});

it("shows the active delay reports count", () => {
render(<TransitBoardPage />);

expect(
screen.getByText(/4 active delay reports/),
).toBeInTheDocument();
});
});
Loading
Loading