1- import { useState , useEffect } from 'react' ;
1+ /* eslint-disable no-unused-vars */
2+ import { useContext , useState , useEffect } from 'react' ;
23import { useTheme } from '../../context/theme/ThemeContext' ;
3- import { Calendar , CheckCircle2 , Clock , Flame , ArrowRight , ListTodo } from 'lucide-react' ;
4+ import { Calendar , CheckCircle2 , ArrowRight , Lightbulb , Target , BrainCircuit } from 'lucide-react' ;
45import Badge from '../ui/Badge' ;
56import Button from '../ui/Button' ;
67import { useNavigate } from 'react-router-dom'
78import { fetchWeeklyChallenges , transformProblemData } from '../../services/api/questionService'
9+ import { AppContent } from '../../context/userauth/authenticationContext' ;
810
911const PLACEHOLDER = [
1012 { id : 'wc-1' , title : 'The Sorting Showdown' , description : 'Solve 5 different sorting challenges this week' , difficulty : 'Hard' , points : 500 , completed : 2 , total : 5 , icon : '📊' , color : '#FF6B6B' } ,
@@ -26,13 +28,29 @@ const getProgressPercentage = (completed, total) => {
2628} ;
2729
2830export default function ChallengesThisWeek ( ) {
29- const { theme } = useTheme ( ) ;
31+ useTheme ( ) ;
32+ const { userData } = useContext ( AppContent ) ;
3033 const [ hoveredId , setHoveredId ] = useState ( null ) ;
3134 const [ expandedId , setExpandedId ] = useState ( null ) ;
3235 const [ cards , setCards ] = useState ( PLACEHOLDER ) ;
3336 const [ loading , setLoading ] = useState ( false ) ;
3437 const [ error , setError ] = useState ( null ) ;
3538 const navigate = useNavigate ( ) ;
39+ const completedQuestionIds = Array . isArray ( userData ?. completedQuestionIds ) ? userData . completedQuestionIds : [ ] ;
40+
41+ const isCompletedQuestion = ( challenge ) => {
42+ const possibleIds = [
43+ challenge ?. id ,
44+ challenge ?. raw ?. problemId ,
45+ challenge ?. raw ?. _id ,
46+ challenge ?. transformed ?. problemId ,
47+ challenge ?. transformed ?. _id
48+ ]
49+ . filter ( Boolean )
50+ . map ( ( value ) => String ( value ) . trim ( ) ) ;
51+
52+ return possibleIds . some ( ( id ) => completedQuestionIds . includes ( id ) ) ;
53+ } ;
3654
3755 useEffect ( ( ) => {
3856 let mounted = true ;
@@ -62,7 +80,7 @@ export default function ChallengesThisWeek() {
6280 points : t . variant ?. points || t . points || 300 ,
6381 completed : it . completed || 0 ,
6482 total : it . total || 1 ,
65- icon : < ListTodo /> ,
83+ icon : '📊' ,
6684 color : '#FF6B6B' ,
6785 raw : it ,
6886 transformed : t ,
@@ -96,21 +114,23 @@ export default function ChallengesThisWeek() {
96114 Complete challenges throughout the week to earn bonus points and unlock achievements
97115 </ p >
98116 </ div >
99- < div className = 'text-right' >
117+ { /* <div className='text-right'>
100118 <p className='text-sm' style={{ color: 'var(--textSec)' }}>
101119 5 days remaining
102120 </p>
103121 <p className='text-2xl font-bold' style={{ color: 'var(--brand)' }}>
104122 {cards.reduce((acc, c) => acc + (c.completed || 0), 0)}/{cards.reduce((acc, c) => acc + (c.total || 0), 0)}
105123 </p>
106- </ div >
124+ </div> */ }
107125 </ div >
108126
109127 < div className = 'grid grid-cols-1 lg:grid-cols-2 gap-6' >
110128 { loading && < div className = 'text-sm text-gray-300' > Loading challenges…</ div > }
111129 { ! loading && cards . map ( ( challenge ) => {
112- const progress = getProgressPercentage ( challenge . completed || 0 , challenge . total || 1 ) ;
113- const isExpanded = expandedId === challenge . id ;
130+ const isCompleted = isCompletedQuestion ( challenge ) ;
131+ const progress = isCompleted ? 100 : getProgressPercentage ( challenge . completed || 0 , challenge . total || 1 ) ;
132+ const displayCompleted = isCompleted ? ( challenge . total || 1 ) : ( challenge . completed || 0 ) ;
133+ const hoverAccent = isCompleted ? '#52C882' : ( challenge . color || '#FF6B6B' ) ;
114134
115135 return (
116136 < div
@@ -123,9 +143,9 @@ export default function ChallengesThisWeek() {
123143 border : '2px solid var(--border)' ,
124144 boxShadow :
125145 hoveredId === challenge . id
126- ? `0 12px 32px ${ challenge . color || '#FF6B6B' } 30`
146+ ? `0 12px 32px ${ hoverAccent } 30`
127147 : 'none' ,
128- borderColor : hoveredId === challenge . id ? ( challenge . color || '#FF6B6B' ) : 'var(--border)' ,
148+ borderColor : hoveredId === challenge . id ? hoverAccent : 'var(--border)' ,
129149 transform : hoveredId === challenge . id ? 'translateY(-4px)' : 'translateY(0)'
130150 } }
131151 onClick = { ( ) => {
@@ -139,20 +159,20 @@ export default function ChallengesThisWeek() {
139159 { /* Header */ }
140160 < div className = 'flex items-start justify-between mb-4' >
141161 < div className = 'flex items-start gap-3 flex-1' >
142- < span className = 'text-3xl mt-1 ' > { challenge . icon } </ span >
162+ < span className = 'text-3xl' > { challenge . icon || '📊' } </ span >
143163 < div className = 'flex-1 min-w-0' >
144164 < h3 className = 'text-lg font-bold mb-1' > { challenge . title } </ h3 >
145165 { /* Only show minimal meta on card. Full problem visible in editor. */ }
146166 < p style = { { color : 'var(--textSec)' } } className = 'text-xs' >
147- { challenge . completed } / { challenge . total } progress
167+ { isCompleted ? 'Completed' : ` ${ displayCompleted } / $ {challenge . total } progress` }
148168 </ p >
149169 </ div >
150170 </ div >
151- { progress === 100 && (
152- < CheckCircle2
153- className = 'w-6 h-6 shrink-0 animate-pulse'
154- style = { { color : '#52C882' } }
155- / >
171+ { isCompleted && (
172+ < div className = 'flex items-center gap-1 rounded-full px-2 py-1 text-xs font-semibold' style = { { background : 'rgba(82, 200, 130, 0.14)' , color : '#52C882' } } >
173+ < CheckCircle2 className = 'w-4 h-4 shrink-0' />
174+ Completed
175+ </ div >
156176 ) }
157177 </ div >
158178
@@ -183,7 +203,7 @@ export default function ChallengesThisWeek() {
183203 Progress
184204 </ span >
185205 < span className = 'text-xs font-bold' style = { { color : getProgressColor ( progress ) } } >
186- { challenge . completed } /{ challenge . total }
206+ { displayCompleted } /{ challenge . total }
187207 </ span >
188208 </ div >
189209 < div
@@ -194,16 +214,17 @@ export default function ChallengesThisWeek() {
194214 className = 'h-full rounded-full transition-all duration-500'
195215 style = { {
196216 width : `${ progress } %` ,
197- background : getProgressColor ( progress )
217+ background : isCompleted ? '#52C882' : getProgressColor ( progress )
198218 } }
199219 />
200220 </ div >
201221 </ div >
202222
203223 < Button variant = 'primary' size = 'sm' icon = { ArrowRight } iconPosition = 'right' fullWidth style = { {
204- background : getProgressColor ( progress ) ,
205- borderColor : getProgressColor ( progress ) } } >
206- { progress === 100 ? 'Completed!' : 'View Challenge' }
224+ background : isCompleted ? '#52C882' : getProgressColor ( progress ) ,
225+ borderColor : isCompleted ? '#52C882' : getProgressColor ( progress )
226+ } } >
227+ { isCompleted ? 'Completed!' : 'View Challenge' }
207228 </ Button >
208229 </ div >
209230 </ div >
@@ -220,14 +241,14 @@ export default function ChallengesThisWeek() {
220241 border : '1px solid var(--border)'
221242 } }
222243 >
223- < p style = { { color : 'var(--textSec)' } } className = 'text-sm mb-2' >
224- Total Points Available
244+ < p style = { { color : 'var(--textSec)' } } className = 'text-sm mb-2 flex items-start justify-center gap-2 ' >
245+ < span style = { { color : 'var(--brand)' } } > < Lightbulb /> </ span > New Concept Focus
225246 </ p >
226247 < p
227- className = 'text-3xl font-bold '
248+ className = 'text-lg font-medium '
228249 style = { { color : 'var(--brand)' } }
229250 >
230- + { cards . reduce ( ( acc , c ) => acc + ( c . points || 0 ) , 0 ) }
251+ Master recursion basics through story-driven challenges
231252 </ p >
232253 </ div >
233254
@@ -238,14 +259,14 @@ export default function ChallengesThisWeek() {
238259 border : '1px solid var(--border)'
239260 } }
240261 >
241- < p style = { { color : 'var(--textSec)' } } className = 'text-sm mb-2' >
242- Completed Challenges
262+ < p style = { { color : 'var(--textSec)' } } className = 'text-sm mb-2 flex items-start justify-center gap-2 ' >
263+ < span style = { { color : '#52C882' } } > < Target /> </ span > Challenge Difficulty
243264 </ p >
244265 < p
245- className = 'text-3xl font-bold '
266+ className = 'text-lg font-medium '
246267 style = { { color : '#52C882' } }
247268 >
248- { cards . filter ( ( c ) => ( c . completed || 0 ) === ( c . total || 0 ) ) . length } / { cards . length }
269+ Balanced mix of easy → medium problems
249270 </ p >
250271 </ div >
251272
@@ -256,14 +277,15 @@ export default function ChallengesThisWeek() {
256277 border : '1px solid var(--border)'
257278 } }
258279 >
259- < p style = { { color : 'var(--textSec)' } } className = 'text-sm mb-2' >
260- Time Remaining
280+ < p style = { { color : 'var(--textSec)' } } className = 'text-sm mb-2 flex items-start justify-center gap-2' >
281+ < span style = { { color : '#FF6B6B' } } > < BrainCircuit /> </ span >
282+ Skill Focus
261283 </ p >
262284 < p
263- className = 'text-3xl font-bold flex items-center justify-center gap-2'
285+ className = 'text-lg font-medium flex items-center justify-center gap-2'
264286 style = { { color : '#FF6B6B' } }
265287 >
266- < Flame className = 'w-6 h-6' /> 5 days
288+ Problem solving + pattern recognition
267289 </ p >
268290 </ div >
269291 </ div >
0 commit comments