Skip to content

Commit 1f43da5

Browse files
committed
feat: sort on Luxe Apps Page
1 parent 015f471 commit 1f43da5

File tree

2 files changed

+53
-26
lines changed

2 files changed

+53
-26
lines changed

src/components/LuxeArt.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ const LuxeArt = ({ seed = 'luxe', className, transparent = false }) => {
8484
}
8585

8686
return { curves: items, specks };
87-
}, [rng]);
87+
}, [rng, transparent]);
8888

8989
return (
9090
<div className={`w-full h-full overflow-hidden relative ${!transparent && 'bg-[#EBEBEB]'} ${className}`}>

src/pages/luxe-views/LuxeAppsPage.jsx

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import {
44
MagnifyingGlassIcon,
55
ArrowUpRightIcon,
66
ArrowLeftIcon,
7+
SortAscendingIcon,
8+
CalendarBlankIcon
79
} from '@phosphor-icons/react';
810
import Seo from '../../components/Seo';
911
import { appIcons } from '../../utils/appIcons';
@@ -30,6 +32,7 @@ const LuxeAppsPage = () => {
3032
const [isLoading, setIsLoading] = useState(true);
3133
const [activeCategory, setActiveCategory] = useState('All');
3234
const [availableCategories, setAvailableCategories] = useState([]);
35+
const [sortOrder, setSortOrder] = useState('alphabetical'); // 'alphabetical' or 'newest'
3336

3437
useEffect(() => {
3538
setIsLoading(true);
@@ -59,15 +62,22 @@ const LuxeAppsPage = () => {
5962
.finally(() => setIsLoading(false));
6063
}, []);
6164

62-
const filteredApps = apps.filter((app) => {
63-
const query = searchQuery.toLowerCase();
64-
const matchesSearch =
65-
app.name.toLowerCase().includes(query) ||
66-
app.description.toLowerCase().includes(query);
67-
const matchesCategory =
68-
activeCategory === 'All' || app.categoryName === activeCategory;
69-
return matchesSearch && matchesCategory;
70-
});
65+
const sortedApps = [...apps]
66+
.filter((app) => {
67+
const query = searchQuery.toLowerCase();
68+
const matchesSearch =
69+
app.name.toLowerCase().includes(query) ||
70+
app.description.toLowerCase().includes(query);
71+
const matchesCategory =
72+
activeCategory === 'All' || app.categoryName === activeCategory;
73+
return matchesSearch && matchesCategory;
74+
})
75+
.sort((a, b) => {
76+
if (sortOrder === 'newest') {
77+
return new Date(b.date || 0) - new Date(a.date || 0);
78+
}
79+
return a.name.localeCompare(b.name);
80+
});
7181

7282
return (
7383
<div className="min-h-screen bg-[#F5F5F0] text-[#1A1A1A] font-sans selection:bg-[#C0B298] selection:text-black pt-24 pb-20">
@@ -103,21 +113,38 @@ const LuxeAppsPage = () => {
103113
</div>
104114
</header>
105115

106-
{/* Category Filter */}
107-
<div className="flex gap-2 overflow-x-auto no-scrollbar mb-20 pb-4 border-b border-[#1A1A1A]/5">
108-
{availableCategories.map((cat) => (
109-
<button
110-
key={cat}
111-
onClick={() => setActiveCategory(cat)}
112-
className={`px-6 py-2 rounded-full font-outfit text-[10px] uppercase tracking-[0.2em] transition-all whitespace-nowrap ${
113-
activeCategory === cat
114-
? 'bg-[#1A1A1A] text-white shadow-lg'
115-
: 'bg-white/50 text-[#1A1A1A]/40 border border-[#1A1A1A]/10 hover:border-[#1A1A1A] hover:text-[#1A1A1A]'
116-
}`}
117-
>
118-
{cat}
119-
</button>
120-
))}
116+
{/* Category Filter & Sort */}
117+
<div className="flex flex-col md:flex-row justify-between items-center gap-8 mb-20 pb-4 border-b border-[#1A1A1A]/5">
118+
<div className="flex gap-2 overflow-x-auto no-scrollbar flex-1 w-full">
119+
{availableCategories.map((cat) => (
120+
<button
121+
key={cat}
122+
onClick={() => setActiveCategory(cat)}
123+
className={`px-6 py-2 rounded-full font-outfit text-[10px] uppercase tracking-[0.2em] transition-all whitespace-nowrap ${
124+
activeCategory === cat
125+
? 'bg-[#1A1A1A] text-white shadow-lg'
126+
: 'bg-white/50 text-[#1A1A1A]/40 border border-[#1A1A1A]/10 hover:border-[#1A1A1A] hover:text-[#1A1A1A]'
127+
}`}
128+
>
129+
{cat}
130+
</button>
131+
))}
132+
</div>
133+
134+
<div className="flex bg-white rounded-full p-1 border border-[#1A1A1A]/5 shadow-sm shrink-0">
135+
<button
136+
onClick={() => setSortOrder('alphabetical')}
137+
className={`flex items-center gap-2 px-4 py-2 rounded-full font-outfit text-[10px] uppercase tracking-widest transition-all ${sortOrder === 'alphabetical' ? 'bg-[#1A1A1A] text-white' : 'text-[#1A1A1A]/40 hover:text-[#1A1A1A]'}`}
138+
>
139+
<SortAscendingIcon size={14} /> A-Z
140+
</button>
141+
<button
142+
onClick={() => setSortOrder('newest')}
143+
className={`flex items-center gap-2 px-4 py-2 rounded-full font-outfit text-[10px] uppercase tracking-widest transition-all ${sortOrder === 'newest' ? 'bg-[#1A1A1A] text-white' : 'text-[#1A1A1A]/40 hover:text-[#1A1A1A]'}`}
144+
>
145+
<CalendarBlankIcon size={14} /> Newest
146+
</button>
147+
</div>
121148
</div>
122149

123150
{isLoading ? (
@@ -126,7 +153,7 @@ const LuxeAppsPage = () => {
126153
</div>
127154
) : (
128155
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-12">
129-
{filteredApps.map((app) => {
156+
{sortedApps.map((app) => {
130157
const categoryColor =
131158
categoryColors[app.categoryName] || categoryColors.Default;
132159
const Icon = appIcons[app.icon] || appIcons[`${app.icon}Icon`];

0 commit comments

Comments
 (0)