Skip to content

Commit 129cc76

Browse files
committed
inital commit
1 parent 63dd353 commit 129cc76

19 files changed

Lines changed: 2157 additions & 244 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
22
build
3+
.vercel

package-lock.json

Lines changed: 1205 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
"clsx": "*",
3535
"cmdk": "^1.1.1",
3636
"embla-carousel-react": "^8.6.0",
37-
"gsap": "*",
37+
"firebase": "^12.7.0",
38+
"gsap": "^3.14.2",
3839
"input-otp": "^1.4.2",
3940
"lucide-react": "^0.487.0",
4041
"motion": "*",
@@ -52,6 +53,9 @@
5253
"devDependencies": {
5354
"@types/node": "^20.10.0",
5455
"@vitejs/plugin-react-swc": "^3.10.2",
56+
"autoprefixer": "^10.4.23",
57+
"postcss": "^8.5.6",
58+
"tailwindcss": "^4.1.18",
5559
"vite": "^6.4.1"
5660
},
5761
"scripts": {

public/videos/feature-2.mp4

1.55 MB
Binary file not shown.

public/videos/feature-3.mp4

823 KB
Binary file not shown.

public/videos/feature-4.mp4

4.13 MB
Binary file not shown.

public/videos/feature-5.mp4

2.15 MB
Binary file not shown.

src/components/About.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { useRef } from 'react';
33
import { ScrollReveal } from './effects/ScrollReveal';
44
import { ScrambleText } from './effects/ScrambleText';
55
import { smoothScrollToElement } from '../utils/smoothScroll';
6-
76
export function About() {
87
const ref = useRef<HTMLDivElement>(null);
98
const { scrollYProgress } = useScroll({

src/components/GameDashboard.tsx

Lines changed: 160 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,27 @@
1-
import { motion } from 'motion/react';
1+
import { motion } from 'framer-motion';
22
import { useGame } from '../contexts/GameContext';
3-
import { useAuth } from '../contexts/AuthContext';
43
import {
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';
2214
import { useState } from 'react';
2315
import { ZoneType } from '../types/game';
2416
import { getDifficultyLabel } from '../data/quests';
2517
import { 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

2723
export 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

Comments
 (0)