Skip to content

Commit 81518a6

Browse files
committed
feat: welcome page and blogpost query params to define blogpost theme.
1 parent ac23117 commit 81518a6

File tree

3 files changed

+265
-4
lines changed

3 files changed

+265
-4
lines changed

src/components/AnimatedRoutes.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ const NewsPage = lazy(() => import('../pages/NewsPage'));
151151
const CommandsPage = lazy(() => import('../pages/CommandsPage'));
152152
const AchievementsPage = lazy(() => import('../pages/AchievementsPage'));
153153
const SitemapPage = lazy(() => import('../pages/SitemapPage'));
154+
const WelcomePage = lazy(() => import('../pages/WelcomePage'));
154155
const VocabRouteHandler = lazy(() => import('../components/VocabRouteHandler'));
155156

156157
const pageVariants = {
@@ -605,6 +606,22 @@ function AnimatedRoutes() {
605606
</motion.div>
606607
}
607608
/>
609+
<Route
610+
path="/welcome"
611+
element={
612+
<motion.div
613+
initial="initial"
614+
animate="in"
615+
exit="out"
616+
variants={pageVariants}
617+
transition={pageTransition}
618+
>
619+
<Suspense fallback={<Loading />}>
620+
<WelcomePage />
621+
</Suspense>
622+
</motion.div>
623+
}
624+
/>
608625
{/* Hardcoded redirects for fc::apps:: paths */}
609626
<Route
610627
path="/apps::pinned"

src/pages/BlogPostPage.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,31 @@
1-
import React from 'react';
1+
import React, { useMemo } from 'react';
2+
import { useSearchParams } from 'react-router-dom';
23
import { useVisualSettings } from '../context/VisualSettingsContext';
34
import DossierBlogPostPage from './DossierBlogPostPage';
45
import StandardBlogPostPage from './StandardBlogPostPage';
5-
import TerminalBlogPostPage from './TerminalBlogPostPage'; // Added import
6+
import TerminalBlogPostPage from './TerminalBlogPostPage';
67

78
const BlogPostPage = () => {
89
const { blogPostViewMode } = useVisualSettings();
10+
const [searchParams] = useSearchParams();
911

10-
if (blogPostViewMode === 'dossier') {
12+
// Determine the effective view mode
13+
// Using useMemo here to derive the mode based on URL params and context.
14+
// This ensures we only recalculate the "winning" mode when the URL or global setting changes,
15+
// preventing it from running on every render if other local state were to change.
16+
const effectiveViewMode = useMemo(() => {
17+
const themeParam = searchParams.get('theme');
18+
if (themeParam && ['dossier', 'terminal', 'standard'].includes(themeParam)) {
19+
return themeParam;
20+
}
21+
return blogPostViewMode;
22+
}, [searchParams, blogPostViewMode]);
23+
24+
if (effectiveViewMode === 'dossier') {
1125
return <DossierBlogPostPage />;
1226
}
1327

14-
if (blogPostViewMode === 'terminal') { // Added conditional render
28+
if (effectiveViewMode === 'terminal') {
1529
return <TerminalBlogPostPage />;
1630
}
1731

src/pages/WelcomePage.js

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
import React, {useState} from 'react';
2+
import {useNavigate} from 'react-router-dom';
3+
import {motion} from 'framer-motion';
4+
import {
5+
Monitor,
6+
CaretRight,
7+
Palette,
8+
GameController,
9+
Eyeglasses,
10+
} from '@phosphor-icons/react';
11+
import {useVisualSettings} from '../context/VisualSettingsContext';
12+
import {useAchievements} from '../context/AchievementContext';
13+
import CustomToggle from '../components/CustomToggle';
14+
import CustomDropdown from '../components/CustomDropdown';
15+
import useSeo from '../hooks/useSeo';
16+
17+
const OptionCard = ({title, icon: Icon, children, colorClass, delay}) => (
18+
<motion.div
19+
initial={{opacity: 0, y: 20}}
20+
animate={{opacity: 1, y: 0}}
21+
transition={{duration: 0.5, delay}}
22+
className="bg-gray-800/40 backdrop-blur-md border border-white/5 rounded-2xl p-6 hover:bg-gray-800/60 hover:border-white/10 transition-all duration-300 group flex flex-col justify-between"
23+
>
24+
<div className="flex items-start justify-between mb-4">
25+
<div className={`p-3 rounded-xl ${colorClass} bg-opacity-20 text-white`}>
26+
<Icon size={28} weight="duotone"/>
27+
</div>
28+
<div className="text-right">
29+
<h3 className="font-arvo text-lg text-white font-medium">{title}</h3>
30+
</div>
31+
</div>
32+
<div className="relative z-10">{children}</div>
33+
</motion.div>
34+
);
35+
36+
const WelcomePage = () => {
37+
useSeo({
38+
title: 'Initialize | Fezcodex',
39+
description: 'Setup your Fezcodex experience.',
40+
});
41+
42+
const navigate = useNavigate();
43+
const [isLaunching, setIsLaunching] = useState(false);
44+
45+
const {
46+
blogPostViewMode,
47+
setBlogPostViewMode,
48+
sidebarColor,
49+
setSidebarColor,
50+
isRetro,
51+
toggleRetro,
52+
} = useVisualSettings();
53+
54+
const {showAchievementToast, toggleAchievementToast} = useAchievements();
55+
56+
const handleFinish = () => {
57+
setIsLaunching(true);
58+
setTimeout(() => {
59+
navigate('/');
60+
}, 800);
61+
};
62+
63+
return (
64+
<div
65+
className="min-h-screen flex flex-col items-center justify-center p-4 sm:p-8 bg-[#0a0a0c] text-gray-100 relative overflow-hidden">
66+
{/* Dynamic Background */}
67+
<div className="absolute inset-0 overflow-hidden pointer-events-none">
68+
<div
69+
className="absolute top-[-20%] left-[-10%] w-[60%] h-[60%] bg-primary-900/10 rounded-full blur-[120px] animate-pulse"/>
70+
<div
71+
className="absolute bottom-[-20%] right-[-10%] w-[60%] h-[60%] bg-blue-900/10 rounded-full blur-[120px] animate-pulse"
72+
style={{animationDelay: '2s'}}/>
73+
<div
74+
className="absolute inset-0 bg-[url('https://grainy-gradients.vercel.app/noise.svg')] opacity-20 brightness-100 contrast-150 mix-blend-overlay"></div>
75+
</div>
76+
77+
<div className="max-w-5xl w-full relative z-10">
78+
{/* Header Section */}
79+
<motion.div
80+
initial={{opacity: 0, y: -20}}
81+
animate={{opacity: 1, y: 0}}
82+
className="text-center mb-16"
83+
>
84+
<motion.div
85+
className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/5 border border-white/10 text-xs font-mono text-gray-400 mb-6"
86+
>
87+
<span className="w-2 h-2 rounded-full bg-green-500 animate-pulse"/>
88+
SYSTEM INITIALIZATION
89+
</motion.div>
90+
91+
<h1
92+
className="text-5xl md:text-7xl font-bold bg-clip-text text-transparent bg-gradient-to-b from-white via-white to-gray-500 font-arvo mb-4 tracking-tight">
93+
Hello, Traveler.
94+
</h1>
95+
<p className="text-xl text-gray-400 max-w-xl mx-auto">
96+
Configure your terminal environment before accessing the mainframe.
97+
</p>
98+
</motion.div>
99+
100+
{/* Cards Grid */}
101+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-16">
102+
103+
{/* 1. Reading Experience */}
104+
<OptionCard
105+
title="Reading Mode"
106+
icon={Eyeglasses}
107+
colorClass="bg-blue-500"
108+
delay={0.1}
109+
>
110+
<p className="text-sm text-gray-400 mb-4 h-10">
111+
Select how data logs and articles should be rendered on your display.
112+
</p>
113+
<CustomDropdown
114+
label="Select View"
115+
options={[
116+
{label: 'Standard (Clean)', value: 'standard'},
117+
{label: 'Dossier (Files)', value: 'dossier'},
118+
{label: 'Terminal (Retro)', value: 'terminal'},
119+
]}
120+
value={blogPostViewMode}
121+
onChange={setBlogPostViewMode}
122+
className="w-full"
123+
/>
124+
</OptionCard>
125+
126+
{/* 2. Gamification */}
127+
<OptionCard
128+
title="Gamification"
129+
icon={GameController}
130+
colorClass="bg-rose-500"
131+
delay={0.2}
132+
>
133+
<p className="text-sm text-gray-400 mb-4 h-10">
134+
Enable achievement tracking and popup notifications during exploration.
135+
</p>
136+
<CustomToggle
137+
id="gamification-toggle"
138+
label={showAchievementToast ? "Achievements Active" : "Achievements Muted"}
139+
checked={showAchievementToast}
140+
onChange={toggleAchievementToast}
141+
colorTheme="rose"
142+
/>
143+
</OptionCard>
144+
145+
{/* 3. Interface Color */}
146+
<OptionCard
147+
title="Sidebar Tint"
148+
icon={Palette}
149+
colorClass="bg-purple-500"
150+
delay={0.3}
151+
>
152+
<p className="text-sm text-gray-400 mb-4 h-10">
153+
Customize the accent color of your primary navigation panel.
154+
</p>
155+
<CustomDropdown
156+
label="Select Color"
157+
options={[
158+
{label: 'Default (Dark)', value: 'default'},
159+
{label: 'Salmon', value: 'salmon-medium'},
160+
{label: 'Cyber Blue', value: 'blue-transparent'},
161+
{label: 'Matrix Green', value: 'green-transparent'},
162+
{label: 'Neon Purple', value: 'purple-transparent'},
163+
]}
164+
value={sidebarColor}
165+
onChange={setSidebarColor}
166+
className="w-full"
167+
/>
168+
</OptionCard>
169+
170+
{/* 4. Visual Processing */}
171+
<OptionCard
172+
title="Retro FX"
173+
icon={Monitor}
174+
colorClass="bg-emerald-500"
175+
delay={0.4}
176+
>
177+
<p className="text-sm text-gray-400 mb-4 h-10">
178+
Engage cathode-ray tube emulation for maximum nostalgia.
179+
</p>
180+
<CustomToggle
181+
id="retro-toggle"
182+
label={isRetro ? "CRT Effects Online" : "CRT Effects Offline"}
183+
checked={isRetro}
184+
onChange={toggleRetro}
185+
colorTheme="green"
186+
/>
187+
</OptionCard>
188+
</div>
189+
190+
{/* Action Area */}
191+
<motion.div
192+
initial={{opacity: 0, y: 20}}
193+
animate={{opacity: 1, y: 0}}
194+
transition={{delay: 0.5}}
195+
className="flex flex-col items-center"
196+
>
197+
<button
198+
onClick={handleFinish}
199+
className={`
200+
group relative flex items-center gap-3 px-8 py-4
201+
bg-white text-black border-2 border-white
202+
font-mono font-bold text-sm tracking-widest uppercase
203+
transition-all duration-300
204+
hover:bg-emerald-500 hover:border-emerald-500 hover:text-black
205+
hover:shadow-[0_0_20px_rgba(16,185,129,0.4)]
206+
${isLaunching ? 'scale-95 opacity-80' : ''}
207+
`}
208+
>
209+
<span className="relative z-10">Launch Fezcodex</span>
210+
<CaretRight weight="bold" size={20}
211+
className="relative z-10 group-hover:translate-x-1 transition-transform"/>
212+
</button>
213+
214+
<p className="text-xs text-gray-500 mt-6 font-mono">
215+
* Additional configurations available in Settings
216+
</p>
217+
218+
<button
219+
onClick={handleFinish}
220+
className="mt-4 text-xs text-gray-600 hover:text-gray-400 transition-colors font-mono uppercase tracking-wider"
221+
>
222+
Skip Configuration
223+
</button>
224+
</motion.div>
225+
</div>
226+
</div>
227+
);
228+
};
229+
230+
export default WelcomePage;

0 commit comments

Comments
 (0)