Skip to content

Commit c253e90

Browse files
committed
feat: timeline.
1 parent e4acf20 commit c253e90

File tree

9 files changed

+415
-8
lines changed

9 files changed

+415
-8
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "fezcodex",
3-
"version": "0.2.2",
3+
"version": "0.2.8",
44
"private": true,
55
"homepage": "https://fezcode.com",
66
"dependencies": {

public/timeline/timeline.json

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
[
2+
{
3+
"date": "2025-11-26",
4+
"title": "Timeline Feature Introduced",
5+
"description": "Implemented a chronological overview of project milestones and achievements.",
6+
"type": "feature",
7+
"icon": "TimerIcon",
8+
"link": "/#/timeline"
9+
},
10+
{
11+
"date": "2025-11-26",
12+
"title": "Major Refactors and UI Improvements",
13+
"description": "Significant refactoring of Logs and App pages, along with UI enhancements across the site.",
14+
"type": "refactor",
15+
"icon": "SparklesIcon",
16+
"link": "/#/logs"
17+
},
18+
{
19+
"date": "2025-11-23",
20+
"title": "Command Palette and Games",
21+
"description": "Introduced a command palette for navigation and new games like Nonogram and Lights Out.",
22+
"type": "feature",
23+
"icon": "GamepadIcon",
24+
"link": "/#/commands"
25+
},
26+
{
27+
"date": "2025-11-21",
28+
"title": "News Feature Introduced",
29+
"description": "Implemented a news section for updates and announcements.",
30+
"type": "feature",
31+
"icon": "ArticleIcon",
32+
"link": "/#/news"
33+
},
34+
{
35+
"date": "2025-11-18",
36+
"title": "Wallpapers Script and New Apps",
37+
"description": "Added a script for generating wallpapers and introduced new interactive apps.",
38+
"type": "feature",
39+
"icon": "ImageIcon",
40+
"link": "/#/apps"
41+
},
42+
{
43+
"date": "2025-11-14",
44+
"title": "Stories Section Rework",
45+
"description": "Reworked the stories section with PIML integration and new structure.",
46+
"type": "content",
47+
"icon": "BookIcon",
48+
"link": "/#/stories"
49+
},
50+
{
51+
"date": "2025-11-13",
52+
"title": "PIML and SEO Implementation",
53+
"description": "Integrated PIML for content management and enhanced SEO capabilities.",
54+
"type": "project",
55+
"icon": "SearchIcon"
56+
},
57+
{
58+
"date": "2025-11-07",
59+
"title": "Introduction of Apps Section",
60+
"description": "Launched the interactive applications section with various tools and games.",
61+
"type": "app",
62+
"icon": "RocketLaunchIcon",
63+
"link": "/#/apps"
64+
},
65+
{
66+
"date": "2025-11-04",
67+
"title": "RSS Feed and Contact Modal",
68+
"description": "Implemented RSS feed generation and a contact modal.",
69+
"type": "feature",
70+
"icon": "RssFeedIcon",
71+
"link": "/rss.xml"
72+
},
73+
{
74+
"date": "2025-10-23",
75+
"title": "DND Content Section Introduced",
76+
"description": "Introduced the Dungeons & Dragons content section with the 'From Serfs and Frauds' series.",
77+
"type": "content",
78+
"icon": "ScrollIcon",
79+
"link": "/#/dnd"
80+
},
81+
{
82+
"date": "2025-10-17",
83+
"title": "Toast Notifications and Markdown Theming",
84+
"description": "Added toast notification system and custom markdown rendering with themes.",
85+
"type": "feature",
86+
"icon": "BellIcon"
87+
},
88+
{
89+
"date": "2025-10-16",
90+
"title": "Introduction of Blogposts and Projects",
91+
"description": "Implemented initial blogpost and project display functionalities.",
92+
"type": "content",
93+
"icon": "ArticleIcon",
94+
"link": "/#/posts"
95+
},
96+
{
97+
"date": "2025-10-15",
98+
"title": "Projects Page Introduced",
99+
"description": "Initial implementation of the Projects page to showcase various works.",
100+
"type": "project",
101+
"icon": "CodeIcon",
102+
"link": "/#/projects"
103+
},
104+
{
105+
"date": "2025-10-15",
106+
"title": "About Page Introduced",
107+
"description": "Initial implementation of the About Me page.",
108+
"type": "content",
109+
"icon": "Briefcase",
110+
"link": "/#/about-me"
111+
},
112+
{
113+
"date": "2025-10-15",
114+
"title": "Blog Page Introduced",
115+
"description": "Initial setup and display of the blog section.",
116+
"type": "content",
117+
"icon": "ArticleIcon",
118+
"link": "/#/posts"
119+
},
120+
{
121+
"date": "2025-10-15",
122+
"title": "Project Initialization",
123+
"description": "Initialized project using Create React App and set up basic structure.",
124+
"type": "project",
125+
"icon": "CodeIcon",
126+
"link": "/"
127+
}
128+
]

src/components/AnimatedRoutes.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ import RoguelikeGamePage from '../pages/apps/RoguelikeGamePage'; // Import Rogue
7272
import TcgCardGeneratorPage from '../pages/apps/TcgCardGeneratorPage'; // Import TcgCardGeneratorPage
7373
import KeyboardTypingSpeedTesterPage from '../pages/apps/KeyboardTypingSpeedTesterPage'; // Import KeyboardTypingSpeedTesterPage
7474
import SettingsPage from '../pages/SettingsPage';
75+
import TimelinePage from '../pages/TimelinePage'; // Import TimelinePage
7576

7677
import UsefulLinksPage from '../pages/UsefulLinksPage';
7778
import NotebooksPage from '../pages/notebooks/NotebooksPage';
@@ -229,6 +230,20 @@ function AnimatedRoutes() {
229230
</motion.div>
230231
}
231232
/>
233+
<Route
234+
path="/timeline" // New route for TimelinePage
235+
element={
236+
<motion.div
237+
initial="initial"
238+
animate="in"
239+
exit="out"
240+
variants={pageVariants}
241+
transition={pageTransition}
242+
>
243+
<TimelinePage />
244+
</motion.div>
245+
}
246+
/>
232247
<Route
233248
path="/logs"
234249
element={

src/components/CommandPalette.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,16 @@ const CommandPalette = ({ isOpen, setIsOpen, openGenericModal, toggleDigitalRain
242242
}
243243
} else if (event.key === 'Escape') {
244244
handleClose();
245+
} else if (event.key === 'PageUp') {
246+
event.preventDefault();
247+
setSelectedIndex((prevIndex) =>
248+
prevIndex <= 0 ? filteredItems.length - 1 : prevIndex - 10
249+
);
250+
} else if (event.key === 'PageDown') {
251+
event.preventDefault();
252+
setSelectedIndex((prevIndex) =>
253+
prevIndex >= filteredItems.length - 10 ? 0 : prevIndex + 10
254+
);
245255
}
246256
};
247257

@@ -279,7 +289,7 @@ const CommandPalette = ({ isOpen, setIsOpen, openGenericModal, toggleDigitalRain
279289
onClick={e => e.stopPropagation()}
280290
>
281291
<div className="p-3 flex items-center justify-center">
282-
<TerminalWindowIcon size={36} weight="duotone" className="mr-2 text-gray-200 "/>
292+
<TerminalWindowIcon size={36} weight="light" className="mr-2 text-gray-200 "/>
283293
<input
284294
ref={inputRef}
285295
type="text"
@@ -315,7 +325,9 @@ const CommandPalette = ({ isOpen, setIsOpen, openGenericModal, toggleDigitalRain
315325
<div className="flex items-center gap-2">
316326
<span className="border border-gray-300 dark:border-gray-600 rounded px-1.5 py-0.5">ESC</span> to close
317327
<span className="border border-gray-300 dark:border-gray-600 rounded px-1.5 py-0.5"></span>
318-
<span className="border border-gray-300 dark:border-gray-600 rounded px-1.5 py-0.5"></span> to navigate
328+
<span className="border border-gray-300 dark:border-gray-600 rounded px-1.5 py-0.5"></span>
329+
<span className="border border-gray-300 dark:border-gray-600 rounded px-1.5 py-0.5">PgUp</span>
330+
<span className="border border-gray-300 dark:border-gray-600 rounded px-1.5 py-0.5">PgDown</span> to navigate
319331
<span className="border border-gray-300 dark:border-gray-600 rounded px-1.5 py-0.5"></span> to select
320332
</div>
321333
<div className="font-semibold text-gray-400">

src/components/Sidebar.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
SquaresFourIcon,
2727
GearSixIcon,
2828
MagnifyingGlassIcon,
29+
TimerIcon,
2930
} from '@phosphor-icons/react';
3031

3132
import Fez from './Fez';
@@ -75,7 +76,8 @@ const Sidebar = ({ isOpen, toggleSidebar, toggleModal, setIsPaletteOpen }) => {
7576
location.pathname.startsWith('/blog') ||
7677
location.pathname.startsWith('/projects') ||
7778
location.pathname.startsWith('/logs') ||
78-
location.pathname.startsWith('/news');
79+
location.pathname.startsWith('/news') ||
80+
location.pathname.startsWith('/timeline');
7981

8082
const isAppsActive = location.pathname.startsWith('/apps') || location.pathname.startsWith('/commands');
8183

@@ -180,6 +182,10 @@ const Sidebar = ({ isOpen, toggleSidebar, toggleModal, setIsPaletteOpen }) => {
180182
<GlobeSimpleIcon size={24} />
181183
<span>News</span>
182184
</NavLink>
185+
<NavLink to="/timeline" className={getLinkClass}>
186+
<TimerIcon size={24} />
187+
<span>Timeline</span>
188+
</NavLink>
183189
</nav>
184190
)}
185191
</div>

src/hooks/useSearchableData.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ const useSearchableData = () => {
5454
{ title: 'Projects', slug: '/projects', type: 'page', path: '/projects' },
5555
{ title: 'About Me', slug: '/about', type: 'page', path: '/about' },
5656
{ title: 'Logs', slug: '/logs', type: 'page', path: '/logs' },
57+
{ title: 'News', slug: '/news', type: 'page', path: '/news' },
58+
{ title: 'Timeline', slug: '/timeline', type: 'page', path: '/timeline' },
5759
{ title: 'Settings', slug: '/settings', type: 'page', path: '/settings' },
5860
{ title: 'Stories', slug: '/stories', type: 'page', path: '/stories' },
5961
{ title: 'Apps', slug: '/apps', type: 'page', path: '/apps' },

src/pages/LogsPage.js

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,31 @@ const categories = [
2525
'Tools',
2626
];
2727

28+
const iconColors = [
29+
"text-red-500",
30+
"text-orange-500",
31+
"text-amber-500",
32+
"text-yellow-500",
33+
"text-lime-500",
34+
"text-green-500",
35+
"text-emerald-500",
36+
"text-teal-500",
37+
"text-cyan-500",
38+
"text-sky-500",
39+
"text-blue-500",
40+
"text-indigo-500",
41+
"text-violet-500",
42+
// "text-purple-500",
43+
// "text-fuchsia-500",
44+
// "text-pink-500",
45+
// "text-rose-500",
46+
// "text-slate-500",
47+
// "text-gray-500",
48+
// "text-zinc-500",
49+
// "text-neutral-500",
50+
// "text-stone-500",
51+
];
52+
2853
const LogsPage = () => {
2954
useSeo({
3055
title: 'Logs | Fezcodex',
@@ -47,6 +72,7 @@ const LogsPage = () => {
4772
const [selectedCategories, setSelectedCategories] = useState([]); // Empty means all
4873
const [searchQuery, setSearchQuery] = useState('');
4974
const [filteredLogs, setFilteredLogs] = useState([]);
75+
const [iconColor, setIconColor] = useState('text-white');
5076

5177
useEffect(() => {
5278
const fetchLogs = async () => {
@@ -65,7 +91,6 @@ const LogsPage = () => {
6591
setLoading(false);
6692
}
6793
};
68-
6994
fetchLogs();
7095
}, []);
7196

@@ -83,6 +108,8 @@ const LogsPage = () => {
83108
return matchesCategory && matchesSearch;
84109
}),
85110
);
111+
const randomIconColor = iconColors[Math.floor(Math.random() * iconColors.length)]
112+
setIconColor(randomIconColor);
86113
}, [logs, selectedCategories, searchQuery]);
87114

88115
const toggleCategory = (category) => {
@@ -120,12 +147,13 @@ const LogsPage = () => {
120147
<LogIcon
121148
size={48}
122149
weight="fill"
123-
className="mr-4 text-primary-500"
150+
className={`mr-4 mt-2 ${iconColor}`}
124151
/>
125152
<span className="text-gray-100">fc</span>
126153
<span className="text-gray-500">::</span>
127154
<span className="text-gray-100">logs</span>
128-
<span className="text-gray-500">::[</span>
155+
<span className="text-gray-500">::</span>
156+
<span className="text-gray-500">[</span>
129157
<span className="text-gray-100">{logs.length}</span>
130158
<span className="text-gray-500">]</span>
131159
{/*<span className="ml-4 text-2xl text-gray-500 bg-gray-800 px-3 py-1 rounded-full font-mono align-middle">*/}

0 commit comments

Comments
 (0)