import type { Metadata } from 'next' import type { ComponentType } from 'react' import { Badge } from '@/components/ui/badge' import { Card, CardContent, CardHeader, CardTitle, } from '@/components/ui/card' import { Progress } from '@/components/ui/progress' import { BadgeCheck, BookOpen, Bookmark, CheckCircle2, Clock3, Database, Download, FileText, Gauge, HelpCircle, Keyboard, Layers, Laptop, Package, PictureInPicture2, Play, ShieldCheck, Smartphone, Tag, Upload, Zap, } from 'lucide-react' export const metadata: Metadata = { title: 'Progress', description: 'Internal product status board for OfflineAcademy.', } type Status = 'Live' | 'Planned' | 'Future' type FeatureGroup = { title: string status: Status icon: ComponentType<{ className?: string }> items: string[] completion: number } type RoadmapItem = { label: string done: boolean } type RoadmapPhase = { phase: string title: string items: RoadmapItem[] completion: number } const liveGroups: FeatureGroup[] = [ { title: 'Library & Scanning', status: 'Live', icon: Database, completion: 100, items: [ 'Recursive scan of a local course root directory', 'Course, module, and lesson discovery', 'Natural sort for lesson ordering', 'Folder-driven import with local file access', ], }, { title: 'Playback & Resume', status: 'Live', icon: Play, completion: 100, items: [ 'Lesson playback inside the app', 'Continue Watching and resume playback', 'Auto-next / playback flow support', 'Native HTML5 video player for speed and simplicity', ], }, { title: 'Playback Enhancements', status: 'Live', icon: Zap, completion: 100, items: [ 'Variable playback speed (0.75x, 1x, 1.25x, 1.5x, 2.0x)', 'Global keyboard shortcuts (play/pause, seek, mute, fullscreen, speed, PiP, Escape)', 'Picture-in-Picture toggle', ], }, { title: 'Learning Tools', status: 'Live', icon: Bookmark, completion: 100, items: [ 'Bookmarks with timestamp notes', 'Jump-to-time bookmark playback', 'Subtitle support for .srt and .vtt', 'Inline document viewing for lessons', ], }, { title: 'Course Management', status: 'Live', icon: ShieldCheck, completion: 100, items: [ 'Persistent rename titles', 'Delete from library', 'Delete from disk', 'Archived/hidden courses stay hidden on rescans', ], }, { title: 'Progress Tracking UI', status: 'Live', icon: Gauge, completion: 100, items: [ 'Progress bars on course cards', 'Lesson/module manual Done toggles', 'Local analytics dashboard (`/analytics`) with watch time, completion rates, weekly activity', ], }, { title: 'Built-in Quiz Interactivity', status: 'Live', icon: HelpCircle, completion: 100, items: [ 'Quiz settings: Auto-Fetch toggle + QuizAPI / The Trivia API source selector', 'QuizPlayer: intro, active questions, results, 80% pass mark, ⚙️ Edit Topic override', 'Auto-fetch writes quiz_cache.json to module folders on module open', 'Scanner injects Quiz lesson type (🟣) into module sidebar', 'Quiz, Question, QuizAttempt models; score/passed tracked; green checkmark on completion', ], }, { title: 'Library Organization', status: 'Live', icon: Tag, completion: 100, items: [ 'Custom tags & categories with color (Tag + CourseTag models)', 'Filter by tag, favorites, in-progress, completed, not-started', 'Sort by name, progress %, updatedAt; favorites pinned to top', ], }, { title: 'Content Types & Thumbnails', status: 'Live', icon: FileText, completion: 100, items: [ 'PDF, TXT, MD, HTML, and JSON inline preview', 'Local thumbnail support', 'Safer thumbnail lookup to reduce broken image noise', 'Watch-page rendering for mixed lesson types', ], }, { title: 'Settings & Data Model', status: 'Live', icon: Laptop, completion: 100, items: [ 'Configured course root directory', 'SQLite + Prisma local persistence', 'Progress and bookmark tables', 'No login, no accounts, no cloud storage', ], }, ] const roadmapPhases: RoadmapPhase[] = [ { phase: 'Phase 5', title: 'Data Portability', completion: 0, items: [ { label: 'Export local state to JSON (progress, bookmarks, notes, tags, course metadata, quiz attempts)', done: false }, { label: 'Import and restore JSON state safely', done: false }, ], }, ] const futureIdeas = [ { title: 'Reset Course', icon: Gauge, note: 'Clear progress and start a course from zero.', }, { title: 'Mobile App Wrapper', icon: Smartphone, note: 'Lightweight mobile wrapper or app packaging layer.', }, { title: 'Import / Export Course Metadata', icon: Package, note: 'Move course metadata in and out without touching core progress state.', }, ] const stackBadges = [ 'Next.js 14', 'React', 'TypeScript', 'Tailwind', 'shadcn/ui', 'Prisma', 'SQLite', 'Native Video', ] const currentCompletion = Math.round((liveGroups.filter((group) => group.completion === 100).length / liveGroups.length) * 100) export default function ProgressPage() { return (
Internal route Local-only Fast stack

OfflineAcademy Progress

A private status board for the app’s live features, roadmap, and future ideas. This page is intentionally not linked from the dashboard — it’s an internal route you can visit directly at /progress.

{stackBadges.map((item) => ( {item} ))}
Current Build Progress
Live core complete {currentCompletion}%
Live feature groups
{liveGroups.length}
Roadmap phases
{roadmapPhases.length}
What’s Live Today {liveGroups.map((group) => { const Icon = group.icon return (

{group.title}

{group.status}

{group.completion}%
    {group.items.map((item) => (
  • {item}
  • ))}
) })}
Roadmap Phases {roadmapPhases.map((phase) => (
{phase.phase}

{phase.title}

{phase.completion}%
    {phase.items.map((item) => (
  • {item.done ? ( ) : ( )} {item.label}
  • ))}
))}
Future Ideas {futureIdeas.map((idea) => { const Icon = idea.icon return (

{idea.title}

{idea.note}

) })}
Product Constraints

No authentication, no accounts, no user profiles.

Everything stays local: folder scanning, SQLite, and file serving.

The app is built to stay fast as more courses are added.

This route is a direct internal progress page, not a dashboard menu item.

Playback speed & shortcuts: Live PiP: Live Quizzes: Live Export planned Import planned
) }