1- import { motion } from 'motion/react ' ;
1+ import { motion } from 'framer- motion' ;
22import { useGame } from '../contexts/GameContext' ;
3- import { useAuth } from '../contexts/AuthContext' ;
43import {
54 TrendingUp ,
6- Heart ,
7- Zap ,
85 DollarSign ,
96 Calendar ,
10- Award ,
11- AlertTriangle ,
127 Shield ,
13- User ,
14- ChevronRight ,
158 Code ,
169 Gamepad2 ,
1710 Users ,
1811 Coffee ,
19- Clock ,
2012 AlertCircle ,
2113} from 'lucide-react' ;
2214import { useState } from 'react' ;
2315import { ZoneType } from '../types/game' ;
2416import { getDifficultyLabel } from '../data/quests' ;
2517import { PlayerCard } from './PlayerCard' ;
18+ import { Workspace } from './zones/Workspace' ;
19+ import { GameLounge } from './zones/GameLounge' ;
20+ import { MeetingRoom } from './zones/MeetingRoom' ;
21+ import { Cafeteria } from './zones/Cafeteria' ;
2622
2723export function GameDashboard ( { onProfileClick } : { onProfileClick ?: ( ) => void } ) {
2824 const { player, activeQuests, activeBuffs } = useGame ( ) ;
29- const { user } = useAuth ( ) ;
3025 const [ selectedTab , setSelectedTab ] = useState < 'overview' | ZoneType > ( 'overview' ) ;
3126
3227 // Calculate progress to next level
@@ -39,8 +34,8 @@ export function GameDashboard({ onProfileClick }: { onProfileClick?: () => void
3934 return daysLeft <= 3 ;
4035 } ) ;
4136
42- // Calculate completed quests this month
43- const completedThisMonth = player . currentMonthTasksCompleted || 0 ;
37+ // Count completed quests
38+ const completedThisMonth = activeQuests . filter ( q => q . status === 'completed' ) . length ;
4439
4540 // Get zone icon
4641 const getZoneIcon = ( zone : ZoneType ) => {
@@ -262,158 +257,171 @@ export function GameDashboard({ onProfileClick }: { onProfileClick?: () => void
262257 </ button >
263258 </ motion . div >
264259
265- { /* Career Dashboard */ }
266- < motion . div
267- initial = { { opacity : 0 , y : 20 } }
268- animate = { { opacity : 1 , y : 0 } }
269- transition = { { delay : 0.2 } }
270- >
271- < h2 className = "text-2xl mb-4" > Career Dashboard</ h2 >
272-
273- < div className = "grid grid-cols-3 gap-4 mb-6" >
274- { /* Active Quests */ }
275- < div className = "bg-gray-900/50 border border-gray-800 rounded-xl p-4" >
276- < p className = "text-sm text-gray-400 mb-1" > Active Quests</ p >
277- < p className = "text-3xl text-white" > { activeQuests . length } </ p >
278- </ div >
279-
280- { /* Completed This Month */ }
281- < div className = "bg-gray-900/50 border border-gray-800 rounded-xl p-4" >
282- < p className = "text-sm text-gray-400 mb-1" > Completed This Month</ p >
283- < p className = "text-3xl text-white" > { completedThisMonth } </ p >
284- </ div >
260+ { /* Conditional Content Based on Selected Tab */ }
261+ { selectedTab === 'overview' ? (
262+ < >
263+ { /* Career Dashboard */ }
264+ < motion . div
265+ initial = { { opacity : 0 , y : 20 } }
266+ animate = { { opacity : 1 , y : 0 } }
267+ transition = { { delay : 0.2 } }
268+ >
269+ < h2 className = "text-2xl mb-4" > Career Dashboard</ h2 >
270+
271+ < div className = "grid grid-cols-3 gap-4 mb-6" >
272+ { /* Active Quests */ }
273+ < div className = "bg-gray-900/50 border border-gray-800 rounded-xl p-4" >
274+ < p className = "text-sm text-gray-400 mb-1" > Active Quests</ p >
275+ < p className = "text-3xl text-white" > { activeQuests . length } </ p >
276+ </ div >
285277
286- { /* Urgent */ }
287- < div className = "bg-gray-900/50 border border-gray-800 rounded-xl p-4" >
288- < p className = "text-sm text-gray-400 mb-1" > Urgent (≤2 days)</ p >
289- < p className = "text-3xl text-red-400" > { urgentQuests . length } </ p >
290- </ div >
291- </ div >
278+ { /* Completed This Month */ }
279+ < div className = "bg-gray-900/50 border border-gray-800 rounded-xl p-4" >
280+ < p className = "text-sm text-gray-400 mb-1" > Completed This Month</ p >
281+ < p className = "text-3xl text-white" > { completedThisMonth } </ p >
282+ </ div >
292283
293- { /* Urgent Deadlines Section */ }
294- { urgentQuests . length > 0 && (
295- < div className = "bg-red-950/20 border border-red-900/50 rounded-xl p-4 mb-6" >
296- < div className = "flex items-center gap-2 text-red-400 mb-3" >
297- < AlertCircle className = "w-5 h-5" />
298- < h3 className = "text-lg" > Urgent Deadlines</ h3 >
284+ { /* Urgent */ }
285+ < div className = "bg-gray-900/50 border border-gray-800 rounded-xl p-4" >
286+ < p className = "text-sm text-gray-400 mb-1" > Urgent (≤2 days)</ p >
287+ < p className = "text-3xl text-red-400" > { urgentQuests . length } </ p >
288+ </ div >
299289 </ div >
300- < div className = "space-y-2" >
301- { urgentQuests . map ( quest => {
290+
291+ { /* Urgent Deadlines Section */ }
292+ { urgentQuests . length > 0 && (
293+ < div className = "bg-red-950/20 border border-red-900/50 rounded-xl p-4 mb-6" >
294+ < div className = "flex items-center gap-2 text-red-400 mb-3" >
295+ < AlertCircle className = "w-5 h-5" />
296+ < h3 className = "text-lg" > Urgent Deadlines</ h3 >
297+ </ div >
298+ < div className = "space-y-2" >
299+ { urgentQuests . map ( quest => {
300+ const daysLeft = quest . deadline
301+ ? Math . ceil ( ( quest . deadline - Date . now ( ) ) / ( 1000 * 60 * 60 * 24 ) )
302+ : 0 ;
303+ return (
304+ < div key = { quest . id } className = "text-sm" >
305+ < span className = "text-white" > • { quest . title } </ span >
306+ < span className = "text-red-400" > - { daysLeft } day{ daysLeft !== 1 ? 's' : '' } remaining</ span >
307+ </ div >
308+ ) ;
309+ } ) }
310+ </ div >
311+ </ div >
312+ ) }
313+ </ motion . div >
314+
315+ { /* All Quests */ }
316+ < motion . div
317+ initial = { { opacity : 0 , y : 20 } }
318+ animate = { { opacity : 1 , y : 0 } }
319+ transition = { { delay : 0.3 } }
320+ >
321+ < h2 className = "text-2xl mb-4" > All Quests</ h2 >
322+
323+ < div className = "space-y-3" >
324+ { activeQuests . map ( ( quest , index ) => {
302325 const daysLeft = quest . deadline
303326 ? Math . ceil ( ( quest . deadline - Date . now ( ) ) / ( 1000 * 60 * 60 * 24 ) )
304- : 0 ;
305- return (
306- < div key = { quest . id } className = "text-sm" >
307- < span className = "text-white" > • { quest . title } </ span >
308- < span className = "text-red-400" > - { daysLeft } day{ daysLeft !== 1 ? 's' : '' } remaining</ span >
309- </ div >
310- ) ;
311- } ) }
312- </ div >
313- </ div >
314- ) }
315- </ motion . div >
327+ : null ;
316328
317- { /* All Quests */ }
318- < motion . div
319- initial = { { opacity : 0 , y : 20 } }
320- animate = { { opacity : 1 , y : 0 } }
321- transition = { { delay : 0.3 } }
322- >
323- < h2 className = "text-2xl mb-4" > All Quests </ h2 >
324-
325- < div className = "space-y-3 " >
326- { activeQuests . map ( ( quest , index ) => {
327- const daysLeft = quest . deadline
328- ? Math . ceil ( ( quest . deadline - Date . now ( ) ) / ( 1000 * 60 * 60 * 24 ) )
329- : null ;
330-
331- return (
332- < motion . div
333- key = { quest . id }
334- initial = { { opacity : 0 , x : - 20 } }
335- animate = { { opacity : 1 , x : 0 } }
336- transition = { { delay : 0.3 + index * 0.05 } }
337- className = "bg-gray-900/50 border border-gray-800 rounded-xl p-5 hover:border-gray-700 transition-all cursor-pointer"
338- >
339- < div className = "flex items-start justify-between" >
340- < div className = "flex-1" >
341- < div className = "flex items-center gap-2 mb-2" >
342- < AlertCircle className = "w-5 h-5 text-yellow-400" / >
343- < h3 className = "text-lg text-white" > { quest . title } </ h3 >
344- </ div >
345-
346- < p className = "text-sm text-gray-400 mb-3" > { quest . description } </ p >
347-
348- < div className = "flex flex-wrap gap-2" >
349- { /* Zone Badge */ }
350- < span className = { `px-3 py-1 rounded-full text-xs ${ getZoneColor ( quest . zone ) } ` } >
351- { quest . zone . replace ( '-' , ' ' ) }
352- </ span >
353-
354- { /* Difficulty Badge */ }
355- { quest . difficulty && (
356- < span className = { `px-3 py-1 rounded-full text-xs ${ getDifficultyColor ( quest . difficulty ) } ` } >
357- { getDifficultyLabel ( quest . difficulty ) }
358- </ span >
359- ) }
329+ return (
330+ < motion . div
331+ key = { quest . id }
332+ initial = { { opacity : 0 , x : - 20 } }
333+ animate = { { opacity : 1 , x : 0 } }
334+ transition = { { delay : 0.3 + index * 0.05 } }
335+ className = "bg-gray-900/50 border border-gray-800 rounded-xl p-5 hover:border-gray-700 transition-all cursor-pointer"
336+ >
337+ < div className = "flex items-start justify-between " >
338+ < div className = "flex-1" >
339+ < div className = "flex items-center gap-2 mb-2" >
340+ < AlertCircle className = "w-5 h-5 text-yellow-400" />
341+ < h3 className = "text-lg text-white" > { quest . title } </ h3 >
342+ </ div >
343+
344+ < p className = "text-sm text-gray-400 mb-3" > { quest . description } </ p >
345+
346+ < div className = "flex flex-wrap gap-2" >
347+ { /* Zone Badge */ }
348+ < span className = { `px-3 py-1 rounded-full text-xs ${ getZoneColor ( quest . zone ) } ` } >
349+ { quest . zone . replace ( '-' , ' ' ) }
350+ </ span >
351+
352+ { /* Difficulty Badge */ }
353+ { quest . difficulty && (
354+ < span className = { `px-3 py-1 rounded-full text-xs ${ getDifficultyColor ( quest . difficulty ) } ` } >
355+ { getDifficultyLabel ( quest . difficulty ) }
356+ </ span >
357+ ) }
358+
359+ { /* Rewards */ }
360+ { quest . expReward > 0 && (
361+ < span className = "px-3 py-1 rounded-full text-xs bg-cyan-900/50 text-cyan-400" >
362+ + { quest . expReward } EXP
363+ </ span >
364+ ) }
365+ { quest . currencyReward > 0 && (
366+ < span className = "px-3 py-1 rounded-full text-xs bg-yellow-900/50 text-yellow-400" >
367+ +$ { quest . currencyReward } Salary
368+ </ span >
369+ ) }
370+ </ div >
371+ </ div >
360372
361- { /* Rewards */ }
362- { quest . expReward > 0 && (
363- < span className = "px-3 py-1 rounded-full text-xs bg-cyan-900/50 text-cyan-400" >
364- +{ quest . expReward } EXP
365- </ span >
366- ) }
367- { quest . currencyReward > 0 && (
368- < span className = "px-3 py-1 rounded-full text-xs bg-yellow-900/50 text-yellow-400" >
369- +${ quest . currencyReward } Salary
370- </ span >
373+ { /* Days Remaining */ }
374+ { daysLeft !== null && (
375+ < div className = "text-right ml-4" >
376+ < p className = { `text-2xl ${ daysLeft <= 2 ? 'text-red-400' : 'text-white' } ` } >
377+ { daysLeft }
378+ </ p >
379+ < p className = "text-xs text-gray-500" > day{ daysLeft !== 1 ? 's' : '' } </ p >
380+ </ div >
371381 ) }
372382 </ div >
373- </ div >
374-
375- { /* Days Remaining */ }
376- { daysLeft !== null && (
377- < div className = "text-right ml-4" >
378- < p className = { `text-2xl ${ daysLeft <= 2 ? 'text-red-400' : 'text-white' } ` } >
379- { daysLeft }
380- </ p >
381- < p className = "text-xs text-gray-500" > day{ daysLeft !== 1 ? 's' : '' } </ p >
382- </ div >
383- ) }
384- </ div >
385- </ motion . div >
386- ) ;
387- } ) }
388- </ div >
389- </ motion . div >
383+ </ motion . div >
384+ ) ;
385+ } ) }
386+ </ div >
387+ </ motion . div >
390388
391- { /* Active Buffs */ }
392- { activeBuffs . length > 0 && (
393- < motion . div
394- initial = { { opacity : 0 , y : 20 } }
395- animate = { { opacity : 1 , y : 0 } }
396- transition = { { delay : 0.4 } }
397- className = "bg-gray-900/50 border border-gray-800 rounded-xl p-4"
398- >
399- < div className = "flex items-center gap-2 mb-3" >
400- < Shield className = "w-4 h-4 text-purple-400" />
401- < span className = "text-sm text-gray-400" > Active Buffs</ span >
402- </ div >
403- < div className = "grid grid-cols-1 md:grid-cols-3 gap-3" >
404- { activeBuffs . map ( ( buff ) => (
405- < div key = { buff . itemId } className = "bg-purple-900/20 border border-purple-800/50 rounded-lg p-3" >
406- < div className = "text-white mb-1" > { buff . name } </ div >
407- { buff . expiresAt && (
408- < div className = "text-xs text-gray-500" >
409- { Math . floor ( ( buff . expiresAt - Date . now ( ) ) / 60000 ) } m remaining
389+ { /* Active Buffs */ }
390+ { activeBuffs . length > 0 && (
391+ < motion . div
392+ initial = { { opacity : 0 , y : 20 } }
393+ animate = { { opacity : 1 , y : 0 } }
394+ transition = { { delay : 0.4 } }
395+ className = "bg-gray-900/50 border border-gray-800 rounded-xl p-4"
396+ >
397+ < div className = "flex items-center gap-2 mb-3" >
398+ < Shield className = "w-4 h-4 text-purple-400" />
399+ < span className = "text-sm text-gray-400" > Active Buffs</ span >
400+ </ div >
401+ < div className = "grid grid-cols-1 md:grid-cols-3 gap-3" >
402+ { activeBuffs . map ( ( buff ) => (
403+ < div key = { buff . itemId } className = "bg-purple-900/20 border border-purple-800/50 rounded-lg p-3" >
404+ < div className = "text-white mb-1" > { buff . name } </ div >
405+ { buff . expiresAt && (
406+ < div className = "text-xs text-gray-500" >
407+ { Math . floor ( ( buff . expiresAt - Date . now ( ) ) / 60000 ) } m remaining
408+ </ div >
409+ ) }
410410 </ div >
411- ) }
411+ ) ) }
412412 </ div >
413- ) ) }
414- </ div >
415- </ motion . div >
416- ) }
413+ </ motion . div >
414+ ) }
415+ </ >
416+ ) : selectedTab === 'workspace' ? (
417+ < Workspace />
418+ ) : selectedTab === 'game-lounge' ? (
419+ < GameLounge />
420+ ) : selectedTab === 'meeting-room' ? (
421+ < MeetingRoom />
422+ ) : selectedTab === 'cafeteria' ? (
423+ < Cafeteria />
424+ ) : null }
417425 </ div >
418426 ) ;
419427}
0 commit comments