@@ -245,23 +245,8 @@ SkeletonLoader.displayName = "SkeletonLoader";
245245
246246// Problem Card Component
247247const ProblemCard = memo (
248- ( { challenge, isToday = false } : { challenge : Challenge ; isToday ?: boolean } ) => {
248+ ( { challenge, isToday = false , stats } : { challenge : Challenge ; isToday ?: boolean ; stats : { usersCount : number ; challengesCount : number ; solvedChallenges : number } } ) => {
249249 const [ isLoading , setIsLoading ] = useState ( false ) ;
250- const [ stats , setStats ] = useState ( { usersCount : 0 , challengesCount : 0 , solvedChallenges : 0 } ) ;
251-
252- useEffect ( ( ) => {
253- const fetchStats = async ( ) => {
254- try {
255- const res = await fetch ( `${ import . meta. env . VITE_API_BASE_URL } /api/stats` ) ;
256- const data = await res . json ( ) ;
257- setStats ( data ) ;
258- } catch ( error ) {
259- console . error ( "Failed to fetch stats:" , error ) ;
260- }
261- } ;
262-
263- fetchStats ( ) ;
264- } , [ ] ) ;
265250
266251 const navigate = useNavigate ( ) ;
267252 const handleUpdatePOTD = useCallback ( ( ) => {
@@ -451,6 +436,8 @@ const AdminChallenges: React.FC = () => {
451436 users : storeUsers ,
452437 fetchChallenges,
453438 fetchUsers,
439+ fetchStats : storeFetchStats ,
440+ fetchPOTD,
454441 loading : storeLoading
455442 } = useAdminStore ( ) ;
456443
@@ -461,20 +448,31 @@ const AdminChallenges: React.FC = () => {
461448 const [ filterDifficulty , setFilterDifficulty ] = useState < string > ( "all" ) ;
462449 const [ sortBy , setSortBy ] = useState < string > ( "date" ) ;
463450 const [ stats , setStats ] = useState ( { usersCount : 0 , challengesCount : 0 , solvedChallenges : 0 } ) ;
451+ const [ todayChallenge , setTodayChallenge ] = useState < Challenge | null > ( null ) ;
464452
465453 useEffect ( ( ) => {
466- const fetchStats = async ( ) => {
467- try {
468- const res = await fetch ( `${ import . meta. env . VITE_API_BASE_URL } /api/stats` ) ;
469- const data = await res . json ( ) ;
470- setStats ( data ) ;
471- } catch ( error ) {
472- console . error ( "Failed to fetch stats:" , error ) ;
454+ const loadStats = async ( ) => {
455+ const statsData = await storeFetchStats ( ) ;
456+ if ( statsData ) {
457+ // Parse formatted strings back to numbers for calculations
458+ const parseFormattedNumber = ( str : string ) => {
459+ if ( typeof str === 'number' ) return str ;
460+ if ( str . includes ( 'M+' ) ) return parseFloat ( str . replace ( 'M+' , '' ) ) * 1000000 ;
461+ if ( str . includes ( 'k+' ) ) return parseFloat ( str . replace ( 'k+' , '' ) ) * 1000 ;
462+ if ( str . includes ( '+' ) ) return parseInt ( str . replace ( '+' , '' ) ) ;
463+ return parseInt ( str ) || 0 ;
464+ } ;
465+
466+ setStats ( {
467+ usersCount : parseFormattedNumber ( statsData . usersCount ) ,
468+ challengesCount : parseFormattedNumber ( statsData . challengesCount ) ,
469+ solvedChallenges : parseFormattedNumber ( statsData . solvedChallenges )
470+ } ) ;
473471 }
474472 } ;
475473
476- fetchStats ( ) ;
477- } , [ ] ) ;
474+ loadStats ( ) ;
475+ } , [ storeFetchStats ] ) ;
478476
479477 const [ statistics ] = useState < Statistics > ( {
480478 totalProblems : 0 ,
@@ -494,13 +492,44 @@ const AdminChallenges: React.FC = () => {
494492 fetchChallenges ( ) ,
495493 fetchUsers ( )
496494 ] ) ;
495+
496+ // Fetch today's POTD
497+ const potdData = await fetchPOTD ( ) ;
498+ if ( potdData && potdData . challenge ) {
499+ const challenge = potdData . challenge ;
500+ const solvedUsersCount = challenge . solvedUsers ?. length || 0 ;
501+
502+ // Convert to Challenge interface format
503+ const formattedChallenge : Challenge = {
504+ _id : challenge . _id ,
505+ title : challenge . title ,
506+ createdAt : challenge . createdAt ,
507+ category : Array . isArray ( challenge . category )
508+ ? challenge . category
509+ : challenge . category ? [ challenge . category ] : [ ] ,
510+ difficulty : challenge . difficulty as "Easy" | "Medium" | "Hard" ,
511+ platform : challenge . platform || "Unknown" ,
512+ description : challenge . description || "" ,
513+ problemLink : challenge . problemLink || "#" ,
514+ solvedUsers : challenge . solvedUsers || [ ] ,
515+ solvedUsersCount,
516+ totalUsers : storeUsers . length ,
517+ solvedPercentage : storeUsers . length > 0
518+ ? Math . round ( ( solvedUsersCount / storeUsers . length ) * 100 )
519+ : 0 ,
520+ } ;
521+
522+ setTodayChallenge ( formattedChallenge ) ;
523+ }
497524 } catch ( error ) {
498525 console . error ( "Failed to fetch data:" , error ) ;
526+ } finally {
527+ // Don't set loading to false here - let the challenges processing effect handle it
499528 }
500529 } ;
501530
502531 loadData ( ) ;
503- } , [ fetchChallenges , fetchUsers ] ) ;
532+ } , [ fetchChallenges , fetchUsers , fetchPOTD , storeUsers . length ] ) ;
504533
505534 // Get the total number of users
506535 const totalUsersCount = useMemo ( ( ) => {
@@ -606,23 +635,6 @@ const AdminChallenges: React.FC = () => {
606635 // });
607636 // }, []);
608637
609- // Get today's challenge
610- const todayChallenge = useMemo ( ( ) => {
611- if ( processedChallenges . length === 0 ) return null ;
612-
613- const today = new Date ( ) ;
614- today . setHours ( 0 , 0 , 0 , 0 ) ;
615-
616- // Find challenge created today or the most recent one
617- const todaysChallenge = processedChallenges . find ( ( challenge ) => {
618- const challengeDate = new Date ( challenge . createdAt ) ;
619- challengeDate . setHours ( 0 , 0 , 0 , 0 ) ;
620- return challengeDate . getTime ( ) === today . getTime ( ) ;
621- } ) ;
622-
623- return todaysChallenge || processedChallenges [ 0 ] ; // Return today's challenge or the most recent one
624- } , [ processedChallenges ] ) ;
625-
626638 // Filter and sort challenges
627639 useEffect ( ( ) => {
628640 let filtered = [ ...processedChallenges ] ;
@@ -710,7 +722,7 @@ const AdminChallenges: React.FC = () => {
710722 < SkeletonLoader />
711723 </ div >
712724 ) : (
713- todayChallenge && < ProblemCard challenge = { todayChallenge } isToday = { true } />
725+ todayChallenge && < ProblemCard challenge = { todayChallenge } isToday = { true } stats = { stats } />
714726 ) }
715727
716728 < div className = "flex flex-col sm:flex-row gap-4 mb-6" >
@@ -797,7 +809,7 @@ const AdminChallenges: React.FC = () => {
797809 exit = { { opacity : 0 , y : - 20 } }
798810 transition = { { duration : 0.3 } }
799811 >
800- < ProblemCard challenge = { challenge } />
812+ < ProblemCard challenge = { challenge } stats = { stats } />
801813 </ motion . div >
802814 ) )
803815 ) }
0 commit comments