Skip to content

Commit 5497239

Browse files
committed
feat: Pinned Apps page 2
1 parent 71de06d commit 5497239

File tree

1 file changed

+106
-74
lines changed

1 file changed

+106
-74
lines changed

src/pages/PinnedAppPage.js

Lines changed: 106 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,127 @@
11
import React, {useState, useEffect} from 'react';
22
import {Link} from 'react-router-dom';
3-
import {ArrowLeftIcon, PushPin, Star, ArrowRight, Crown} from '@phosphor-icons/react';
3+
import {ArrowLeftIcon, ArrowRight, Star, Cpu, Globe, TerminalWindow} from '@phosphor-icons/react';
44
import {motion} from 'framer-motion';
55
import useSeo from '../hooks/useSeo';
66
import {appIcons} from '../utils/appIcons';
77

88
const PinnedAppCard = ({app, index}) => {
99
const Icon = appIcons[app.icon] || Star;
10-
const isTop3 = index < 3;
11-
// Special styling for Top 3
12-
const rankColors = {
13-
0: 'text-yellow-400 border-yellow-500/50 bg-yellow-500/10', // Gold
14-
1: 'text-gray-300 border-gray-400/50 bg-gray-400/10', // Silver
15-
2: 'text-amber-600 border-amber-700/50 bg-amber-700/10', // Bronze
16-
};
1710

18-
const rankStyle = rankColors[index] || 'text-gray-500 border-gray-700/50 bg-gray-800/50';
11+
// Dynamic accent color based on rank
12+
const accentGradient = index === 0 ? 'from-yellow-400 via-orange-500 to-yellow-600' : // Gold
13+
index === 1 ? 'from-gray-200 via-gray-400 to-slate-500' : // Silver
14+
index === 2 ? 'from-amber-700 via-orange-800 to-amber-900' : // Bronze
15+
'from-cyan-500 via-blue-500 to-indigo-600'; // Cyber Blue
16+
1917
return (
20-
<Link to={app.to}
21-
className={`block group relative h-full ${isTop3 ? 'col-span-1 md:col-span-1 lg:col-span-1' : ''}`}>
18+
<Link to={app.to} className="block group relative h-full">
19+
{/* Animated Glow Border */}
20+
<div
21+
className={`absolute -inset-[1px] bg-gradient-to-br ${accentGradient} rounded-2xl opacity-30 group-hover:opacity-100 blur-sm transition-opacity duration-500`}></div>
22+
23+
{/* Main Card Container */}
24+
2225
<div
23-
className={`relative flex flex-col h-full bg-gray-900/60 backdrop-blur-md border border-white/10 rounded-3xl p-6 hover:bg-gray-800/80 transition-all duration-300 overflow-hidden group-hover:border-primary-500/30 group-hover:shadow-2xl group-hover:shadow-primary-500/20 group-hover:-translate-y-2`}>
24-
{/* Watermark Icon */}
26+
className="relative flex flex-col h-full bg-gray-900/80 backdrop-blur-xl border border-gray-800 rounded-2xl p-5 overflow-hidden group-hover:border-gray-700 transition-all duration-300 shadow-xl">
27+
28+
{/* Subtle Grid Background */}
29+
<div className="absolute inset-0 opacity-[0.03] pointer-events-none z-0"
30+
style={{
31+
backgroundImage: 'linear-gradient(to right, #ffffff 1px, transparent 1px), linear-gradient(to bottom, #ffffff 1px, transparent 1px)',
32+
backgroundSize: '20px 20px'
33+
}}>
34+
</div>
35+
36+
{/* Watermark Icon - Restored */}
2537
<div
26-
className="absolute -bottom-10 -right-10 opacity-20 group-hover:opacity-30 transition-opacity duration-500 rotate-12 pointer-events-none text-white">
27-
<Icon size={220} weight="fill"/>
38+
className="absolute -bottom-8 -right-8 text-gray-700 opacity-20 group-hover:opacity-30 group-hover:scale-110 transition-all duration-500 rotate-12 pointer-events-none z-0">
39+
<Icon size={180} weight="fill"/>
2840
</div>
29-
{/* Rank Badge */}
30-
<div className="flex justify-between items-start mb-6 relative z-10">
31-
<div
32-
className={`p-3 rounded-2xl bg-gray-800/80 border border-white/5 text-primary-400 group-hover:scale-110 transition-transform duration-300 shadow-inner`}>
33-
<Icon size={32} weight="duotone"/>
41+
42+
{/* Header: ID and Rank */}
43+
44+
<div className="flex justify-between items-start mb-4 relative z-10 border-b border-white/10 pb-3">
45+
46+
<div className="flex flex-col">
47+
48+
<span className="text-[10px] uppercase tracking-[0.2em] text-gray-500 font-mono">System.App</span>
49+
50+
<span
51+
className="text-xs font-mono text-primary-400/80">ID :: {String(app.pinned_order).padStart(3, '0')}</span>
52+
3453
</div>
54+
3555
<div
36-
className={`flex items-center justify-center w-10 h-10 rounded-full border ${rankStyle} font-bold font-mono text-lg shadow-sm backdrop-blur-sm`}>
37-
{index < 3 && <Crown size={14} weight="fill" className="mr-1 -ml-1"/>}
56+
className={`flex items-center justify-center w-8 h-8 rounded font-mono font-bold text-sm border ${index < 3 ? 'bg-white/10 text-white border-white/20' : 'bg-gray-900 text-gray-500 border-gray-800'}`}>
57+
3858
{app.pinned_order}
59+
3960
</div>
61+
4062
</div>
63+
{/* Icon & Title */}
64+
4165
<div className="relative z-10 flex-grow">
66+
67+
<div className="mb-4 flex items-center justify-between">
68+
69+
<div
70+
className={`p-2 rounded-lg bg-gray-900 border border-gray-800 text-gray-300 group-hover:text-white group-hover:scale-110 transition-all duration-300 group-hover:border-gray-600`}>
71+
72+
<Icon size={32} weight="duotone"/>
73+
74+
</div>
75+
76+
<Cpu size={24} className="text-gray-800 group-hover:text-gray-600 transition-colors"/>
77+
78+
</div>
79+
4280
<h3
43-
className={`font-bold text-white mb-3 group-hover:text-primary-400 transition-colors font-mono ${isTop3 ? 'text-2xl' : 'text-xl'}`}>
81+
className="text-xl font-bold font-mono text-white mb-2 tracking-tight group-hover:text-primary-400 transition-colors">
82+
4483
{app.title}
84+
4585
</h3>
46-
<p className="text-gray-400 text-sm leading-relaxed line-clamp-3 group-hover:text-gray-300 transition-colors">
86+
<p className="text-gray-500 font-mono text-sm leading-relaxed line-clamp-3">
87+
88+
<span className="text-gray-700 select-none mr-2">{'>'}</span>
89+
4790
{app.description}
91+
4892
</p>
93+
4994
</div>
50-
<div
51-
className="relative z-10 mt-6 flex items-center text-sm font-medium text-primary-400 group-hover:text-primary-300 transition-colors">
52-
Launch App <ArrowRight size={16} className="ml-2 transition-transform group-hover:translate-x-1"/>
95+
{/* Footer: Status */}
96+
97+
<div className="relative z-10 mt-6 pt-3 border-t border-white/10 flex justify-between items-center">
98+
<div className="flex items-center gap-2">
99+
<span className="relative flex h-2 w-2">
100+
<span
101+
className="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"></span>
102+
<span className="relative inline-flex rounded-full h-2 w-2 bg-green-500"></span>
103+
</span>
104+
<span
105+
className="text-[10px] font-mono uppercase tracking-wider text-gray-500 group-hover:text-green-400 transition-colors">Online</span>
106+
</div>
107+
<ArrowRight size={14}
108+
className="text-gray-600 group-hover:text-white transform group-hover:translate-x-1 transition-all"/>
53109
</div>
54110
</div>
55111
</Link>
56112
);
57113
};
114+
58115
const PinnedAppPage = () => {
59116
useSeo({
60117
title: 'Pinned Apps | Fezcodex',
61-
description: 'A curated selection of my favorite and most used apps.',
62-
keywords: ['pinned', 'favorite', 'apps', 'tools', 'hall of fame'],
118+
description: 'Core system modules and essential tools.',
119+
keywords: ['pinned', 'apps', 'tools', 'system', 'core'],
63120
});
64121

65122
const [pinnedApps, setPinnedApps] = useState([]);
66123
const [isLoading, setIsLoading] = useState(true);
124+
67125
useEffect(() => {
68126
fetch('/apps/apps.json')
69127
.then((res) => res.json())
@@ -83,88 +141,62 @@ const PinnedAppPage = () => {
83141
};
84142

85143
return (
86-
<div className="min-h-screen bg-gray-950 py-16 sm:py-24 relative overflow-hidden">
87-
{/* Background Glows */}
144+
<div className="min-h-screen bg-gray-950 py-16 sm:py-24 relative">
145+
{/* Decorative Background Elements */}
88146
<div
89-
className="absolute top-0 left-1/2 -translate-x-1/2 w-3/4 h-[500px] bg-primary-500/10 blur-[120px] rounded-full pointer-events-none mix-blend-screen"/>
147+
className="absolute top-0 inset-x-0 h-px bg-gradient-to-r from-transparent via-gray-800 to-transparent opacity-50"></div>
90148
<div
91-
className="absolute bottom-0 right-0 w-[600px] h-[600px] bg-blue-600/10 blur-[120px] rounded-full pointer-events-none mix-blend-screen"/>
149+
className="absolute bottom-0 inset-x-0 h-px bg-gradient-to-r from-transparent via-gray-800 to-transparent opacity-50"></div>
92150

93151
<div className="mx-auto max-w-7xl px-6 lg:px-8 relative z-10">
94-
<div className="relative mb-16 text-center">
95-
<div className="absolute left-0 top-1/2 -translate-y-1/2 hidden md:block">
152+
<div className="relative mb-16">
153+
<div className="hidden md:block absolute left-0 top-2">
96154
<Link
97155
to="/"
98-
className="group text-primary-400 hover:text-primary-300 hover:underline flex items-center gap-2 text-sm transition-colors"
156+
className="group text-gray-500 hover:text-white hover:underline flex items-center gap-2 text-xs font-mono uppercase tracking-widest transition-colors"
99157
>
100-
<ArrowLeftIcon size={18} className="transition-transform group-hover:-translate-x-1"/> Home
158+
<ArrowLeftIcon size={14}/> sys_root
101159
</Link>
102160
</div>
103161

104162
<motion.div
105-
106163
initial={{opacity: 0, y: 20}}
107-
108164
animate={{opacity: 1, y: 0}}
109-
110165
transition={{duration: 0.5}}
111-
166+
className="text-center"
112167
>
113-
114-
<h1 className="text-5xl md:text-6xl font-bold tracking-tight text-white font-mono mb-6">
115-
116-
Hall of <span
117-
className="text-transparent bg-clip-text bg-gradient-to-r from-yellow-400 to-orange-500">Fame</span>
118-
168+
<div
169+
className="inline-flex items-center justify-center p-3 mb-4 rounded-full bg-gray-900/50 border border-gray-800 backdrop-blur-sm">
170+
<TerminalWindow size={32} className="text-primary-500"/>
171+
</div>
172+
<h1 className="text-4xl md:text-5xl font-bold tracking-tighter text-white font-mono mb-4">
173+
SYSTEM_CORE <span className="text-gray-600">//</span> PINNED
119174
</h1>
120-
121-
<p className="text-lg text-gray-400 max-w-2xl mx-auto font-light">
122-
123-
The essential toolkit. Hand-picked and pinned for quick access.
124-
175+
<p className="text-sm md:text-base text-gray-400 max-w-2xl mx-auto font-mono tracking-wide">
176+
[ ACCESSING ESSENTIAL MODULES AND TOOLS ]
125177
</p>
126-
127178
</motion.div>
128179
</div>
129180

130181
{isLoading ? (
131-
132182
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
133-
134-
{[...Array(8)].map((_, i) => (
135-
136-
<div key={i} className="bg-gray-900/30 border border-gray-800 rounded-3xl h-72 animate-pulse"></div>
137-
183+
{[...Array(6)].map((_, i) => (
184+
<div key={i} className="bg-gray-900/50 border border-gray-800 rounded-2xl h-64 animate-pulse"></div>
138185
))}
139-
140186
</div>
141-
142187
) : (
143-
144188
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 auto-rows-fr">
145-
146189
{pinnedApps.map((app, index) => (
147-
148190
<motion.div
149-
150191
key={app.slug}
151-
152192
initial={{opacity: 0, scale: 0.95}}
153-
154193
animate={{opacity: 1, scale: 1}}
155-
156194
transition={{duration: 0.3, delay: index * 0.05}}
157-
158195
>
159-
160196
<PinnedAppCard app={app} index={index}/>
161-
162197
</motion.div>
163-
164198
))}
165-
166199
</div>
167-
168200
)}
169201
</div>
170202
</div>

0 commit comments

Comments
 (0)