This commit is contained in:
2025-12-07 18:24:18 +00:00
parent df9afa3f4a
commit b1fd0ec5ff
2 changed files with 38 additions and 11 deletions
+27 -6
View File
@@ -40,11 +40,11 @@ const defaultAchievements: Achievement[] = [
{ id: 'all_pages', name: 'Completionist', description: 'Visit every page on the site', icon: '🗺️', unlocked: false, secret: true },
// Time achievements
{ id: 'time_1min', name: 'Quick Visit', description: 'Spend 1 minute on the site', icon: '⏱️', unlocked: false },
{ id: 'time_5min', name: 'Taking Your Time', description: 'Spend 5 minutes on the site', icon: '⏰', unlocked: false },
{ id: 'time_15min', name: 'Deep Dive', description: 'Spend 15 minutes on the site', icon: '🕐', unlocked: false },
{ id: 'time_30min', name: 'Marathon Session', description: 'Spend 30 minutes on the site', icon: '🕑', unlocked: false, secret: true },
{ id: 'time_1hour', name: 'No Life', description: 'Spend 1 hour on the site', icon: '💀', unlocked: false, secret: true },
{ id: 'time_5min', name: 'Quick Visit', description: 'Spend 5 minutes on the site', icon: '⏱️', unlocked: false },
{ id: 'time_15min', name: 'Taking Your Time', description: 'Spend 15 minutes on the site', icon: '⏰', unlocked: false },
{ id: 'time_30min', name: 'Deep Dive', description: 'Spend 30 minutes on the site', icon: '🕐', unlocked: false },
{ id: 'time_1hour', name: 'Marathon Session', description: 'Spend 1 hour on the site', icon: '🕑', unlocked: false, secret: true },
{ id: 'time_2hour', name: 'No Life', description: 'Spend 2 hours on the site', icon: '💀', unlocked: false, secret: true },
// Game achievements
{ id: 'tetris_played', name: 'Block Stacker', description: 'Play Tetris', icon: '🧱', unlocked: false },
@@ -125,11 +125,11 @@ export const AchievementsProvider = ({ children }: { children: ReactNode }) => {
// Check time-based achievements
useEffect(() => {
if (timeOnSite >= 60) unlockAchievement('time_1min');
if (timeOnSite >= 300) unlockAchievement('time_5min');
if (timeOnSite >= 900) unlockAchievement('time_15min');
if (timeOnSite >= 1800) unlockAchievement('time_30min');
if (timeOnSite >= 3600) unlockAchievement('time_1hour');
if (timeOnSite >= 7200) unlockAchievement('time_2hour');
}, [timeOnSite]);
// Check time of day achievements
@@ -187,11 +187,17 @@ export const AchievementsProvider = ({ children }: { children: ReactNode }) => {
unlockAchievement('first_visit');
}, []);
const [notification, setNotification] = useState<Achievement | null>(null);
const unlockAchievement = useCallback((id: string) => {
setAchievements(prev => {
const achievement = prev.find(a => a.id === id);
if (!achievement || achievement.unlocked) return prev;
// Show notification
setNotification(achievement);
setTimeout(() => setNotification(null), 4000);
const updated = prev.map(a =>
a.id === id ? { ...a, unlocked: true, unlockedAt: Date.now() } : a
);
@@ -224,6 +230,21 @@ export const AchievementsProvider = ({ children }: { children: ReactNode }) => {
}}
>
{children}
{/* Achievement Notification */}
{notification && (
<div className="fixed top-4 right-4 z-[300] animate-in slide-in-from-right-5 fade-in duration-300">
<div className="bg-background border-2 border-primary p-4 box-glow-strong max-w-xs">
<div className="flex items-center gap-3">
<span className="text-2xl">{notification.icon}</span>
<div>
<div className="text-primary font-minecraft text-sm text-glow">ACHIEVEMENT UNLOCKED!</div>
<div className="text-primary font-bold">{notification.name}</div>
<div className="text-primary/70 text-xs">{notification.description}</div>
</div>
</div>
</div>
</div>
)}
</AchievementsContext.Provider>
);
};