Skip to content

Commit cb1e946

Browse files
committed
refactor: achievements.
1 parent fcf4624 commit cb1e946

File tree

1 file changed

+68
-6
lines changed

1 file changed

+68
-6
lines changed

src/pages/AchievementsPage.js

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
import React from 'react';
1+
import React, { useState } from 'react';
22
import { Link } from 'react-router-dom';
33
import {
44
ArrowLeftIcon,
55
Trophy,
66
Lock,
77
Info,
88
BellSlash,
9+
FunnelIcon,
10+
XCircle,
911
} from '@phosphor-icons/react';
1012
import useSeo from '../hooks/useSeo';
1113
import { useAchievements } from '../context/AchievementContext';
@@ -27,6 +29,13 @@ const AchievementsPage = () => {
2729
});
2830

2931
const { unlockedAchievements, showAchievementToast } = useAchievements();
32+
const [selectedCategories, setSelectedCategories] = useState([]);
33+
34+
// Extract unique categories for filter pills
35+
const uniqueCategories = [
36+
'All', // Add 'All' category to display all achievements
37+
...new Set(ACHIEVEMENTS.map((ach) => ach.category)),
38+
].sort();
3039

3140
// Calculate progress
3241
const unlockedCount = Object.keys(unlockedAchievements).filter(
@@ -35,6 +44,29 @@ const AchievementsPage = () => {
3544
const totalCount = ACHIEVEMENTS.length;
3645
const progressPercentage = Math.round((unlockedCount / totalCount) * 100);
3746

47+
const toggleCategory = (category) => {
48+
if (category === 'All') {
49+
setSelectedCategories([]);
50+
} else {
51+
setSelectedCategories((prev) =>
52+
prev.includes(category)
53+
? prev.filter((c) => c !== category)
54+
: [...prev, category],
55+
);
56+
}
57+
};
58+
59+
const clearFilters = () => {
60+
setSelectedCategories([]);
61+
};
62+
63+
const filteredAchievements = ACHIEVEMENTS.filter((achievement) => {
64+
const matchesCategory =
65+
selectedCategories.length === 0 || // If no categories selected, show all
66+
selectedCategories.includes(achievement.category);
67+
return matchesCategory;
68+
});
69+
3870
return (
3971
<div className="py-16 sm:py-24">
4072
<div className="mx-auto max-w-7xl px-6 lg:px-8">
@@ -54,6 +86,36 @@ const AchievementsPage = () => {
5486
Discover hidden features and explore the depths of Fezcodex.
5587
</p>
5688

89+
{/* Filter Pills */}
90+
<div className="flex flex-wrap items-center justify-center gap-2 mt-8 max-w-2xl mx-auto">
91+
<div className="flex items-center gap-2 mr-2 text-gray-500 font-mono text-sm">
92+
<FunnelIcon size={16} />
93+
<span>Filter:</span>
94+
</div>
95+
{uniqueCategories.map((category) => {
96+
const isSelected = selectedCategories.includes(category) || (category === 'All' && selectedCategories.length === 0);
97+
const colorClass = isSelected ? 'bg-yellow-500/20 text-yellow-300 border-yellow-500/50' : 'bg-gray-900/50 text-gray-400 border-gray-700 hover:border-gray-500 hover:text-gray-200';
98+
return (
99+
<button
100+
key={category}
101+
onClick={() => toggleCategory(category)}
102+
className={`px-3 py-1 rounded-full text-sm font-medium border transition-colors duration-200 ${colorClass}`}
103+
>
104+
{category}
105+
</button>
106+
);
107+
})}
108+
109+
{selectedCategories.length > 0 && (
110+
<button
111+
onClick={clearFilters}
112+
className="ml-2 text-sm text-red-400 hover:text-red-300 flex items-center gap-1 transition-colors"
113+
>
114+
<XCircle size={20} /> Clear
115+
</button>
116+
)}
117+
</div>
118+
57119
{/* Progress Bar */}
58120
<div className="mt-8 max-w-md mx-auto">
59121
<div className="flex justify-between text-sm text-gray-400 mb-2">
@@ -118,21 +180,21 @@ const AchievementsPage = () => {
118180
</div>
119181

120182
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mt-16">
121-
{ACHIEVEMENTS.map((achievement) => {
183+
{filteredAchievements.map((achievement) => {
122184
const isUnlocked = unlockedAchievements[achievement.id]?.unlocked;
123185

124186
return (
125187
<div
126188
key={achievement.id}
127189
className={`relative overflow-hidden rounded-xl border p-6 transition-all duration-300 ${
128190
isUnlocked
129-
? 'bg-gray-800/40 border-yellow-500/30 shadow-[0_0_15px_rgba(234,179,8,0.1)]'
191+
? 'bg-amber-900/40 border-amber-500/30 shadow-[0_0_15px_rgba(245,158,11,0.2)]'
130192
: 'bg-gray-900/40 border-gray-800 opacity-70 grayscale'
131193
}`}
132194
>
133195
<div className="flex items-start justify-between">
134196
<div
135-
className={`p-3 rounded-lg ${isUnlocked ? 'bg-yellow-500/20 text-yellow-400' : 'bg-gray-800 text-gray-500'}`}
197+
className={`p-3 rounded-lg ${isUnlocked ? 'bg-amber-500/20 text-amber-400' : 'bg-gray-800 text-gray-500'}`}
136198
>
137199
{isUnlocked ? (
138200
achievement.icon
@@ -141,15 +203,15 @@ const AchievementsPage = () => {
141203
)}
142204
</div>
143205
{isUnlocked && (
144-
<span className="text-xs font-mono text-green-400 bg-green-900/30 px-2 py-1 rounded border border-green-800">
206+
<span className="text-xs font-mono text-amber-400 bg-amber-900/30 px-2 py-1 rounded border border-amber-800">
145207
UNLOCKED
146208
</span>
147209
)}
148210
</div>
149211

150212
<div className="mt-4">
151213
<h3
152-
className={`text-xl font-bold ${isUnlocked ? 'text-white' : 'text-gray-500'}`}
214+
className={`text-xl font-bold ${isUnlocked ? 'text-amber-100' : 'text-gray-500'}`}
153215
>
154216
{achievement.title}
155217
</h3>

0 commit comments

Comments
 (0)