A modern React 19 application enabling Education Supervisors to curate custom learning paths with a hybrid data architecture.
The Phillips Education POC solves a critical gap in enterprise learning management: supervisors cannot currently curate training paths or enroll employees in custom programs. This application delivers a self-service program builder that decouples assignment (supervisor says "Do this") from registration (employee picks "Nov 20th in Mumbai"), enabling supervisors to build, publish, and manage learning programs while students independently select enrollment dates and locations.
Drag-and-drop curriculum design using @dnd-kit. Supervisors search, filter, and compose custom learning paths from existing course catalogs with real-time duration calculations (ILT days + eLearning hours).
Reads from legacy Phillips APIs (Azure cloud) while persisting new logic to a local microservice layer (json-server). A network-first, localStorage-fallback strategy ensures seamless operation in offline mode or when APIs become unavailable.
Fully responsive dashboard built with shadcn/ui primitives and Tailwind CSS v4. Features include horizontal course "ticket" cards, 2-column modal layouts, and Radix UI accordion components for accessibility-first design.
Network-first architecture with localStorage fallback. Perfect for Vercel deploymentβautomatically detects offline mode and gracefully degrades to local data without requiring API infrastructure.
Multi-step enrollment flow: students view assigned programs, book classes at specific dates/locations, and track progress with interactive status badges. Demo mode allows supervisors to showcase workflow without modifying data.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β React 19 Frontend β
β (ProgramBuilder, StudentDashboard, ProgramManager, etc.) β
βββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββ¬ββββββββββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββ
β API Layer β β Local Store β β localStorage
β (Hybrid Model) β β (json-server) β β (Fallback)
ββββββββββ¬βββββββββ ββββββββββββββββββββ βββββββββββββββ
β
ββββββββββββββΌβββββββββββββ
β β β
βΌ βΌ βΌ
ββββββββββ ββββββββββββ ββββββββββββ
β Coursesβ β Inventoryβ β Learners β
β(Legacy)β β (Real) β β(Legacy) β
ββββββββββ ββββββββββββ ββββββββββββ
| Entity | Source | Write Target | Purpose |
|---|---|---|---|
| Courses | Legacy Phillips API (Azure) | Read-only | Course metadata, pricing, skills |
| Inventory | Legacy Phillips API | Read-only | Real-time class schedules, locations |
| Learners | Legacy Phillips API | Read-only | Employee profiles, IDs |
| Programs | β | json-server | Custom curated learning paths |
| Assignments | β | json-server | Links programs to learners |
| Enrollments | β | json-server | Links learners to specific class instances |
| Layer | Technology | Version |
|---|---|---|
| Runtime | Bun | Latest |
| Frontend | React | 19 |
| Language | TypeScript | ~5.9 |
| Build Tool | Vite | 7.2 |
| Styling | Tailwind CSS | 4 |
| UI Components | shadcn/ui | Latest |
| Icons | Lucide React | 0.561 |
| Drag & Drop | @dnd-kit | 6.3 |
| Accordion | @radix-ui/accordion | 1.2 |
| Routing | React Router | 7 |
| Mock API | json-server | 1.0 |
| Notifications | Sonner | 2.0 |
| Development | Vitest + @testing-library | Latest |
- Bun (or Node.js 18+)
- Git
# 1. Install dependencies
bun install
# 2. Start dev environment (Vite + json-server)
bun dev
# 3. Open browser
# Vite: http://localhost:5173
# JSON Server: http://localhost:3001That's it! The application automatically:
- β Fetches courses from Phillips legacy API
- β
Loads mock students and assignments from
db.json - β Falls back to localStorage if APIs are unreachable
- β Runs in "Offline Mode" without requiring any remote connections
bun run build # Production build (TypeScript + Vite)
bun run lint # ESLint with strict rules
bun run preview # Preview production build locally
bun run server # JSON Server only (port 3001)
bun run test # Run Vitest suitephillips-poc/
βββ src/
β βββ api/
β β βββ legacyRoutes.ts # Phillips API integration
β β βββ localRoutes.ts # JSON Server + localStorage
β β βββ storageUtils.ts # localStorage helpers
β β
β βββ components/
β β βββ ProgramBuilder.tsx # Drag-drop curriculum designer
β β βββ ProgramManager.tsx # Program editor + roster
β β βββ RosterList.tsx # Student management table
β β βββ common/ # Shared UI components
β β β βββ CourseDetailModal.tsx # 2-column modal layout
β β β βββ CourseCard.tsx # Variant-based course card
β β β βββ EnrollmentModal.tsx # Class selection
β β βββ student/ # Student-facing views
β β β βββ StudentDashboard.tsx # Radix accordion UI
β β βββ progress/ # Supervisor analytics
β β β βββ StudentProgressView.tsx
β β β βββ ProgramProgressCard.tsx
β β βββ ui/ # shadcn/ui primitives
β β βββ card.tsx, button.tsx, badge.tsx, etc.
β β
β βββ hooks/
β β βββ useProgramBuilder.ts # Business logic (drag, filter, save)
β β
β βββ types/
β β βββ models.ts # TypeScript interfaces
β β
β βββ data/
β β βββ seedData.ts # Demo programs, students, enrollments
β β βββ Courses.json # Fallback course catalog
β β βββ Schedules.json # Fallback class inventory
β β
β βββ App.tsx # Root component + routing
β βββ index.css # Phillips brand colors + Tailwind config
β
βββ db.json # Local json-server database
βββ CLAUDE.md # Developer documentation
βββ SPEC.md # Feature specification
βββ docs/
βββ PRD.md # Product requirements
βββ IMPLEMENTATION.md # PR history + status
βββ IMPLEMENTATION_SHADCN.md # UI migration guide
- β Program Builder with drag-and-drop
- β Student roster management
- β Basic UI with Tailwind + shadcn
- β Course catalog search & filtering
- β Enrollment workflows
- β Resilient persistence layer (localStorage fallback)
- β Network-first with graceful degradation
- β Production-ready Vercel deployment
- β Empty data guarantee pattern (API safety)
- β CourseDetailModal 2-column grid redesign
- β Horizontal "flight ticket" course cards
- β CourseCard variant system (default/workbench)
- β Student assignment deduplication
- β Complete shadcn/ui + Radix UI integration
- β Production-ready, portfolio-grade
Decision: Read from Legacy API, write to json-server (+ localStorage as fallback) Rationale: Maintains single source of truth for courses while enabling new features without touching legacy systems.
Decision: Try json-server first; if offline or unreachable, use localStorage Rationale: Enables Vercel deployment (no backend required) while maintaining data reliability in offline scenarios.
Decision: CourseCard uses variant prop ("default" | "workbench") instead of separate components
Rationale: Single source of truth, easier maintenance, and flexibility for future variants.
Decision: Use Radix UI directly for Accordion; wrap others with shadcn for Tailwind integration Rationale: Maximum control + consistency with minimal abstraction layers.
Decision: Store only course IDs in programs, not full course objects Rationale: Reduces payload size, simplifies updates (rehydrate on fetch), and maintains real-time accuracy.
The application implements a "Data Guarantee" pattern:
// Example: getInventory(courseId)
if (!inventory || !inventory.classes || inventory.classes.length === 0) {
console.warn(`API returned empty for course ${courseId}, using fallback`);
// Load fallback from Schedules.json
return fallbackSchedules.filter((s) => s.courseId === courseId);
}This ensures:
- β Network errors don't break the app
- β Empty API responses trigger fallback (not just HTTP errors)
- β Students always see available class sessions
- β Demo works offline without modification
- Currently mocked ("Pat Mann" logged in by default)
- Ready for enterprise SSO/SAML integration
- Vercel: Automatic; no backend required
- AWS/Azure: Add reverse proxy for Legacy API (CORS)
- On-Premise: Docker-friendly (Node.js 18+)
- All mock emails use
@example.com(RFC 2606 reserved) - No real PII in version control
- Safe for client demos
| Metric | Value | Notes |
|---|---|---|
| First Paint | <500ms | Vite + React 19 |
| Build Size | ~180KB gzipped | Tailwind v4 optimization |
| Bundle Analysis | React (42%), UI (18%), Other (40%) | Code-split ready |
| API Response | <2s (cached) | json-server in-memory |
| Offline Activation | Automatic | localStorage fallback |
# Run all tests
bun run test
# Watch mode
bun run test --watch
# Coverage
bun run test --coverageTest Structure:
- β
17 custom hook tests (
useProgramBuilder,useLocalStorage, etc.) - β 14 integration tests (component workflows)
- β End-to-end scenarios (build β assign β enroll)
This is a portfolio project. For changes:
- Create a feature branch:
git checkout -b feat/your-feature - Follow existing code patterns (TypeScript strict mode, ESLint)
- Run tests:
bun run test - Lint:
bun run lint - Build:
bun run build - Submit PR with description of changes
- CLAUDE.md β Developer onboarding guide
- SPEC.md β Feature specification + architecture
- docs/PRD.md β Product requirements document
- docs/IMPLEMENTATION.md β Complete PR history (v1.0 β v2.0)
- docs/IMPLEMENTATION_SHADCN.md β UI modernization guide
This is a proof-of-concept project for educational and demonstration purposes.
Last Updated: 2025-12-16
Status: β Production-Ready