1- export default async function Page ( {
2- params,
3- } : {
4- params : Promise < { courseId : string ; lessonId : string } > ;
5- } ) {
6- const { courseId, lessonId } = await params ;
7- return < div > Managing lesson: { lessonId } for course { courseId } </ div > ;
8- }
1+ "use client" ;
2+ import React from "react" ;
3+ import { Button } from "@/components/ui/button" ;
4+ import { Card , CardContent , CardHeader , CardTitle , CardDescription } from "@/components/ui/card" ;
5+ import { Tabs , TabsContent , TabsList , TabsTrigger } from "@/components/ui/tabs" ;
6+ import { Badge } from "@/components/ui/badge" ;
7+ import { Progress } from "@/components/ui/progress" ;
8+ import { Input } from "@/components/ui/input" ;
9+ import { Textarea } from "@/components/ui/textarea" ;
10+ import { ScrollArea } from "@/components/ui/scroll-area" ;
11+ import { AspectRatio } from "@/components/ui/aspect-ratio" ;
12+ import { DropdownMenu , DropdownMenuContent , DropdownMenuItem , DropdownMenuTrigger } from "@/components/ui/dropdown-menu" ;
13+ import { Play , Captions , Download , FileText , CheckCircle2 , ChevronDown , ExternalLink , Paperclip , BookOpen , NotebookPen , ChevronLeft , ChevronRight } from "lucide-react" ;
14+
15+ /**
16+ * Framework-only lesson page using dummy data.
17+ * Drop this into a Next.js route like app/courses/[courseId]/[lessonId]/page.tsx and wire to real data later.
18+ */
19+ export default function LessonPage ( ) {
20+ // --- Dummy data until DB is wired ---
21+ const course = {
22+ id : "course-ux101" ,
23+ title : "Intro to Web Development" ,
24+ unitTitle : "Unit 1: Fundamentals" ,
25+ progress : 45 ,
26+ } ;
27+
28+ const lesson = {
29+ id : "lesson-10" ,
30+ number : 10 ,
31+ title : "Next.js Application fundamentals" ,
32+ duration : "14:36" ,
33+ summary :
34+ "Learn how to build a simple application with nextjs, from setting up the project to deploying it." ,
35+ attachments : [
36+ { id : "a1" , name : "Slides" , size : "2.3 MB" } ,
37+ { id : "a2" , name : "Lab " , size : "140 KB" } ,
38+ { id : "a3" , name : "Worksheet " , size : "410 KB" } ,
39+ ] ,
40+ resources : [
41+ { id : "r1" , label : "Next js Tutorial" , href : "#" } ,
42+ { id : "r2" , label : "Tailwindcss docs" , href : "#" } ,
43+ ] ,
44+ } ;
45+
46+ const unitLessons = [
47+ { id : "l1" , title : "What is a NextJs?" , duration : "08:24" , status : "done" } ,
48+ { id : "l2" , title : "Part 2" , duration : "12:10" , status : "done" } ,
49+ { id : "l3" , title : "Part 3" , duration : "09:03" , status : "done" } ,
50+ { id : "l4" , title : "Part 4" , duration : "14:36" , status : "current" } ,
51+ { id : "l5" , title : "Part 5" , duration : "16:50" , status : "locked" } ,
52+ ] ;
53+
54+ return (
55+ < div className = "min-h-screen bg-background text-foreground" >
56+ { /* Page container without navbar/footer; those will be injected elsewhere */ }
57+ < div className = "mx-auto grid w-full max-w-7xl grid-cols-1 gap-6 p-4 md:grid-cols-[1fr_320px] md:p-8" >
58+ { /* LEFT: Main content */ }
59+ < div className = "space-y-6" >
60+ { /* Lesson header */ }
61+ < div className = "flex items-start justify-between gap-4" >
62+ < div >
63+ < h1 className = "text-2xl font-semibold tracking-tight sm:text-3xl" > Lesson { lesson . number } : { lesson . title } </ h1 >
64+ < p className = "mt-1 text-sm text-muted-foreground" > { course . title } • { course . unitTitle } • { lesson . duration } </ p >
65+ </ div >
66+ < div className = "flex items-center gap-2" >
67+ < Badge variant = "secondary" > Draft UI</ Badge >
68+ < DropdownMenu >
69+ < DropdownMenuTrigger asChild >
70+ < Button variant = "outline" size = "sm" className = "gap-2" >
71+ Actions < ChevronDown className = "h-4 w-4" />
72+ </ Button >
73+ </ DropdownMenuTrigger >
74+ < DropdownMenuContent align = "end" >
75+ < DropdownMenuItem > Mark complete</ DropdownMenuItem >
76+ < DropdownMenuItem > Report issue</ DropdownMenuItem >
77+ < DropdownMenuItem > Bookmark</ DropdownMenuItem >
78+ </ DropdownMenuContent >
79+ </ DropdownMenu >
80+ </ div >
81+ </ div >
82+
83+ { /* Media / Viewer */ }
84+ < Card className = "overflow-hidden" >
85+ < CardHeader className = "flex flex-row items-center justify-between space-y-0 pb-0" >
86+ < div className = "space-y-1" >
87+ < CardTitle className = "text-xl" > Lesson Viewer</ CardTitle >
88+ < CardDescription > { lesson . summary } </ CardDescription >
89+ </ div >
90+ < div className = "flex items-center gap-2" >
91+ < Button size = "sm" variant = "secondary" className = "gap-2" > < Play className = "h-4 w-4" /> Play</ Button >
92+ < Button size = "sm" variant = "outline" className = "gap-2" > < ExternalLink className = "h-4 w-4" /> Open in new tab</ Button >
93+ </ div >
94+ </ CardHeader >
95+ < CardContent className = "pt-4" >
96+ { /* Video/Player placeholder */ }
97+ < AspectRatio ratio = { 16 / 9 } className = "w-full overflow-hidden rounded-xl bg-muted/60 ring-1 ring-border" >
98+ < div className = "flex h-full w-full items-center justify-center" >
99+ < div className = "flex flex-col items-center" >
100+ < div className = "mb-3 inline-flex h-12 w-12 items-center justify-center rounded-full bg-primary/15" >
101+ < Play className = "h-6 w-6" />
102+ </ div >
103+ < p className = "text-sm text-muted-foreground" > Video placeholder (wire to player later)</ p >
104+ </ div >
105+ </ div >
106+ </ AspectRatio >
107+ </ CardContent >
108+ </ Card >
109+
110+ < Tabs defaultValue = "transcript" className = "w-full" >
111+ < TabsList className = "grid w-full grid-cols-4" >
112+ < TabsTrigger value = "transcript" className = "gap-2" > < Captions className = "h-4 w-4" /> Transcript</ TabsTrigger >
113+ < TabsTrigger value = "attachments" className = "gap-2" > < Paperclip className = "h-4 w-4" /> Attachments</ TabsTrigger >
114+ < TabsTrigger value = "notes" className = "gap-2" > < NotebookPen className = "h-4 w-4" /> Notes</ TabsTrigger >
115+ < TabsTrigger value = "resources" className = "gap-2" > < BookOpen className = "h-4 w-4" /> Resources</ TabsTrigger >
116+ </ TabsList >
117+
118+ < TabsContent value = "transcript" className = "mt-4" >
119+ < Card >
120+ < CardHeader >
121+ < CardTitle className = "text-base" > Lesson Transcript</ CardTitle >
122+ </ CardHeader >
123+ < CardContent >
124+ < p className = "mb-2 text-sm leading-relaxed" >
125+ Welcome to this lesson on React components. In this video, we will explore the fundamentals of building user interfaces using React. React is a popular JavaScript library for building interactive and dynamic web applications...
126+ </ p >
127+ </ CardContent >
128+ </ Card >
129+ </ TabsContent >
130+ { /* Attachments */ }
131+ < TabsContent value = "attachments" className = "mt-4" >
132+ < Card >
133+ < CardHeader >
134+ < CardTitle className = "text-base" > Lesson files</ CardTitle >
135+ < CardDescription > Download reference materials for this lesson.</ CardDescription >
136+ </ CardHeader >
137+ < CardContent >
138+ < ul className = "divide-y" >
139+ { lesson . attachments . map ( ( f ) => (
140+ < li key = { f . id } className = "flex items-center justify-between py-3" >
141+ < div className = "flex items-center gap-3" >
142+ < FileText className = "h-5 w-5" />
143+ < div >
144+ < p className = "text-sm font-medium leading-none" > { f . name } </ p >
145+ < p className = "text-xs text-muted-foreground" > { f . size } </ p >
146+ </ div >
147+ </ div >
148+ < Button variant = "outline" size = "sm" className = "gap-2" aria-disabled >
149+ < Download className = "h-4 w-4" /> Download
150+ </ Button >
151+ </ li >
152+ ) ) }
153+ </ ul >
154+ </ CardContent >
155+ </ Card >
156+ </ TabsContent >
157+
158+ < TabsContent value = "notes" className = "mt-4" >
159+ < Card >
160+ < CardHeader >
161+ < CardTitle className = "text-base" > Attach notes</ CardTitle >
162+ < CardDescription > Your notes are private. Autosave coming later.</ CardDescription >
163+ </ CardHeader >
164+ < CardContent className = "space-y-3" >
165+ < Input placeholder = "Title (optional)" />
166+ < Textarea placeholder = "Type your lesson notes here..." className = "min-h-[160px] resize-y" />
167+ < div className = "flex justify-end gap-2" >
168+ < Button variant = "outline" > Clear</ Button >
169+ < Button > Save draft</ Button >
170+ </ div >
171+ </ CardContent >
172+ </ Card >
173+ </ TabsContent >
174+ < TabsContent value = "resources" className = "mt-4" >
175+ < Card >
176+ < CardHeader >
177+ < CardTitle className = "text-base" > Extra resources</ CardTitle >
178+ < CardDescription > Helpful links and references for deeper learning.</ CardDescription >
179+ </ CardHeader >
180+ < CardContent className = "space-y-3" >
181+ { lesson . resources . map ( ( r ) => (
182+ < a key = { r . id } href = { r . href } className = "flex items-center justify-between rounded-md border p-3 transition hover:bg-muted/70" >
183+ < span className = "text-sm" > { r . label } </ span >
184+ < ExternalLink className = "h-4 w-4" />
185+ </ a >
186+ ) ) }
187+ </ CardContent >
188+ </ Card >
189+ </ TabsContent >
190+ </ Tabs >
191+
192+ { /* Workspace mock (optional area from sketch) */ }
193+
194+
195+ { /* Prev/Next navigation */ }
196+ < div className = "flex items-center justify-between" >
197+ < Button variant = "ghost" className = "gap-2" > < ChevronLeft className = "h-4 w-4" /> Previous</ Button >
198+ < Button className = "gap-2" > Next lesson < ChevronRight className = "h-4 w-4" /> </ Button >
199+ </ div >
200+ </ div >
201+
202+ { /* RIGHT: Sidebar */ }
203+ < aside className = "space-y-4" >
204+ < Card >
205+ < CardHeader className = "pb-3" >
206+ < div className = "flex items-center justify-between" >
207+ < CardTitle className = "text-base" > { course . unitTitle } </ CardTitle >
208+ < Badge variant = "secondary" > { course . progress } %</ Badge >
209+ </ div >
210+ < CardDescription > Progress through the unit.</ CardDescription >
211+ </ CardHeader >
212+ < CardContent >
213+ < Progress value = { course . progress } />
214+ </ CardContent >
215+ </ Card >
216+
217+ < Card >
218+ < CardHeader className = "pb-2" >
219+ < CardTitle className = "text-base" > Lessons</ CardTitle >
220+ < CardDescription > Current lesson is highlighted.</ CardDescription >
221+ </ CardHeader >
222+ < CardContent className = "p-0" >
223+ < ScrollArea className = "h-[420px]" >
224+ < ul className = "divide-y" >
225+ { unitLessons . map ( ( l ) => (
226+ < li key = { l . id } className = { `flex items-center justify-between px-4 py-3 ${ l . status === "current" ? "bg-muted/60" : "" } ` } >
227+ < div className = "min-w-0" >
228+ < p className = "truncate text-sm font-medium" > { l . title } </ p >
229+ < p className = "text-xs text-muted-foreground" > { l . duration } </ p >
230+ </ div >
231+ { l . status === "done" && < CheckCircle2 className = "h-5 w-5 text-emerald-500" /> }
232+ { l . status === "current" && < Badge > Now</ Badge > }
233+ { l . status === "locked" && < Badge variant = "secondary" > Locked</ Badge > }
234+ </ li >
235+ ) ) }
236+ </ ul >
237+ </ ScrollArea >
238+ </ CardContent >
239+ </ Card >
240+
241+
242+ </ aside >
243+ </ div >
244+ </ div >
245+ ) ;
246+ }
0 commit comments