@@ -7,40 +7,110 @@ let feedbackElement = null;
77let feedbackTimeout = null ;
88
99/**
10- * Render the module list in the sidebar
10+ * Render the module list in the sidebar with expandable lessons
1111 * @param {HTMLElement } container - The container element for the module list
1212 * @param {Array } modules - The list of modules
1313 * @param {Function } onSelectModule - Callback when a module is selected
14+ * @param {Function } onSelectLesson - Callback when a lesson is selected
1415 */
15- export function renderModuleList ( container , modules , onSelectModule ) {
16+ export function renderModuleList ( container , modules , onSelectModule , onSelectLesson ) {
1617 // Clear the container
1718 container . innerHTML = "<h3>CSS Lessons</h3>" ;
1819
20+ // Get user progress from localStorage
21+ const progressData = localStorage . getItem ( "codeCrispies.Progress" ) ;
22+ let progress = { } ;
23+ if ( progressData ) {
24+ try {
25+ progress = JSON . parse ( progressData ) ;
26+ } catch ( e ) {
27+ console . error ( "Error parsing progress data:" , e ) ;
28+ }
29+ }
30+
1931 // Create list items for each module
2032 modules . forEach ( ( module ) => {
21- const moduleItem = document . createElement ( "div" ) ;
22- moduleItem . classList . add ( "module-list-item" ) ;
23- moduleItem . dataset . moduleId = module . id ;
24- moduleItem . textContent = module . title ;
25-
26- // Get user progress from localStorage to mark completed lessons
27- const progressData = localStorage . getItem ( "codeCrispies.Progress" ) ;
28- if ( progressData ) {
29- try {
30- const progress = JSON . parse ( progressData ) ;
31- if ( progress [ module . id ] && progress [ module . id ] . completed . length === module . lessons . length ) {
32- moduleItem . classList . add ( "completed" ) ;
33- }
34- } catch ( e ) {
35- console . error ( "Error parsing progress data:" , e ) ;
36- }
33+ // Create module container
34+ const moduleContainer = document . createElement ( "div" ) ;
35+ moduleContainer . classList . add ( "module-container" ) ;
36+
37+ // Create module header item (clickable to expand/collapse)
38+ const moduleHeader = document . createElement ( "div" ) ;
39+ moduleHeader . classList . add ( "module-list-item" , "module-header" ) ;
40+ moduleHeader . dataset . moduleId = module . id ;
41+
42+ // Create module title with expand/collapse indicator
43+ const moduleTitle = document . createElement ( "span" ) ;
44+ moduleTitle . classList . add ( "module-title" ) ;
45+ moduleTitle . textContent = module . title ;
46+
47+ // Create expand/collapse icon
48+ const expandIcon = document . createElement ( "span" ) ;
49+ expandIcon . classList . add ( "expand-icon" ) ;
50+ expandIcon . innerHTML = "▶" ; // Right-pointing triangle
51+
52+ moduleHeader . appendChild ( expandIcon ) ;
53+ moduleHeader . appendChild ( moduleTitle ) ;
54+
55+ // Check if the module is completed
56+ if ( progress [ module . id ] && progress [ module . id ] . completed . length === module . lessons . length ) {
57+ moduleHeader . classList . add ( "completed" ) ;
3758 }
3859
39- moduleItem . addEventListener ( "click" , ( ) => {
40- onSelectModule ( module . id ) ;
60+ // Lessons container (initially hidden)
61+ const lessonsContainer = document . createElement ( "div" ) ;
62+ lessonsContainer . classList . add ( "lessons-container" ) ;
63+ lessonsContainer . style . display = "none" ; // Initially collapsed
64+
65+ // Create list items for each lesson in this module
66+ module . lessons . forEach ( ( lesson , index ) => {
67+ const lessonItem = document . createElement ( "div" ) ;
68+ lessonItem . classList . add ( "lesson-list-item" ) ;
69+ lessonItem . dataset . moduleId = module . id ;
70+ lessonItem . dataset . lessonIndex = index ;
71+ lessonItem . textContent = lesson . title || `Lesson ${ index + 1 } ` ;
72+
73+ // Mark lesson as completed if in progress data
74+ if ( progress [ module . id ] && progress [ module . id ] . completed . includes ( index ) ) {
75+ lessonItem . classList . add ( "completed" ) ;
76+ }
77+
78+ // Mark lesson as current if it's the current lesson
79+ if ( progress [ module . id ] && progress [ module . id ] . current === index ) {
80+ lessonItem . classList . add ( "current" ) ;
81+ }
82+
83+ // Add click event to select lesson
84+ lessonItem . addEventListener ( "click" , ( ) => {
85+ // Update UI to show this lesson is selected
86+ document . querySelectorAll ( ".lesson-list-item" ) . forEach ( ( item ) => {
87+ item . classList . remove ( "active" ) ;
88+ } ) ;
89+ lessonItem . classList . add ( "active" ) ;
90+
91+ // Call the onSelectLesson callback
92+ onSelectLesson ( module . id , index ) ;
93+ } ) ;
94+
95+ lessonsContainer . appendChild ( lessonItem ) ;
4196 } ) ;
4297
43- container . appendChild ( moduleItem ) ;
98+ // Toggle expand/collapse when clicking on module header
99+ moduleHeader . addEventListener ( "click" , ( ) => {
100+ // Toggle visibility of lessons container
101+ const isExpanded = lessonsContainer . style . display !== "none" ;
102+ lessonsContainer . style . display = isExpanded ? "none" : "block" ;
103+
104+ // Update expand/collapse icon
105+ expandIcon . innerHTML = isExpanded ? "▶" : "▼" ;
106+ } ) ;
107+
108+ // Add module header and lessons container to module container
109+ moduleContainer . appendChild ( moduleHeader ) ;
110+ moduleContainer . appendChild ( lessonsContainer ) ;
111+
112+ // Add the complete module container to the sidebar
113+ container . appendChild ( moduleContainer ) ;
44114 } ) ;
45115}
46116
@@ -132,3 +202,41 @@ export function clearFeedback() {
132202 }
133203 feedbackElement = null ;
134204}
205+
206+ /**
207+ * Update the active lesson in the sidebar
208+ * @param {string } moduleId - The ID of the module
209+ * @param {number } lessonIndex - The index of the lesson
210+ */
211+ export function updateActiveLessonInSidebar ( moduleId , lessonIndex ) {
212+ // Remove active class from all lessons
213+ document . querySelectorAll ( ".lesson-list-item" ) . forEach ( ( item ) => {
214+ item . classList . remove ( "active" ) ;
215+ } ) ;
216+
217+ // Find and activate the current lesson
218+ const selector = `.lesson-list-item[data-module-id="${ moduleId } "][data-lesson-index="${ lessonIndex } "]` ;
219+ const currentLessonItem = document . querySelector ( selector ) ;
220+
221+ if ( currentLessonItem ) {
222+ currentLessonItem . classList . add ( "active" ) ;
223+
224+ // Make sure parent module is expanded
225+ const parentLessonsContainer = currentLessonItem . parentElement ;
226+ if ( parentLessonsContainer && parentLessonsContainer . classList . contains ( "lessons-container" ) ) {
227+ parentLessonsContainer . style . display = "block" ;
228+
229+ // Update expand icon
230+ const moduleHeader = parentLessonsContainer . previousElementSibling ;
231+ if ( moduleHeader ) {
232+ const expandIcon = moduleHeader . querySelector ( ".expand-icon" ) ;
233+ if ( expandIcon ) {
234+ expandIcon . innerHTML = "▼" ; // Down arrow when expanded
235+ }
236+ }
237+
238+ // Scroll to ensure the item is visible
239+ currentLessonItem . scrollIntoView ( { behavior : "smooth" , block : "nearest" } ) ;
240+ }
241+ }
242+ }
0 commit comments