fix(CQ-WEB-10): Add loading/error states to pages with mock data
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

Convert tasks, calendar, and dashboard pages from synchronous mock data
to async loading pattern with useState/useEffect. Each page now shows a
loading state via child components while data loads, and displays a
PDA-friendly amber-styled message with a retry button if loading fails.

This prepares these pages for real API integration by establishing the
async data flow pattern. Child components (TaskList, Calendar, dashboard
widgets) already handled isLoading props — now the pages actually use them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jason Woltje
2026-02-06 18:40:21 -06:00
parent 952eeb7323
commit bfeea743f7
6 changed files with 284 additions and 42 deletions

View File

@@ -1,5 +1,5 @@
import { describe, it, expect, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import { render, screen, waitFor } from "@testing-library/react";
import TasksPage from "./page";
// Mock the TaskList component
@@ -15,9 +15,16 @@ describe("TasksPage", (): void => {
expect(screen.getByRole("heading", { level: 1 })).toHaveTextContent("Tasks");
});
it("should render the TaskList component", (): void => {
it("should show loading state initially", (): void => {
render(<TasksPage />);
expect(screen.getByTestId("task-list")).toBeInTheDocument();
expect(screen.getByTestId("task-list")).toHaveTextContent("Loading");
});
it("should render the TaskList with tasks after loading", async (): Promise<void> => {
render(<TasksPage />);
await waitFor((): void => {
expect(screen.getByTestId("task-list")).toHaveTextContent("4 tasks");
});
});
it("should have proper layout structure", (): void => {
@@ -25,4 +32,9 @@ describe("TasksPage", (): void => {
const main = container.querySelector("main");
expect(main).toBeInTheDocument();
});
it("should render the subtitle text", (): void => {
render(<TasksPage />);
expect(screen.getByText("Organize your work at your own pace")).toBeInTheDocument();
});
});