Skip to content

Commit 8927726

Browse files
Fixed navigation problem
1 parent 4b1d4ed commit 8927726

File tree

6 files changed

+178
-129
lines changed

6 files changed

+178
-129
lines changed

app/layout.tsx

Lines changed: 77 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,74 @@
1-
"use client";
1+
'use client';
22
import { Hubballi } from "next/font/google";
3-
import React, { ReactNode } from "react";
3+
import React from "react";
44
import "./globals.css";
55
import Link from "next/link";
66
import { GoogleAnalytics } from "@next/third-parties/google";
7-
87
import SocialMediaButton from "../components/SocialMediaButton";
9-
108
import { links } from "../data/links";
11-
12-
interface RootLayoutProps {
13-
children: ReactNode;
14-
}
9+
import { useTab, TabProvider } from "../context/TabContext";
1510

1611
const hubballi = Hubballi({
17-
weight: ["400"],
18-
subsets: ["latin"],
12+
weight: ["400"],
13+
subsets: ["latin"],
1914
});
2015

21-
export default function RootLayout({ children }: RootLayoutProps) {
22-
return (
23-
<html lang="en">
24-
<body className={`${hubballi.className}`}>
25-
<GoogleAnalytics gaId="G-B1TRQFQPF3" />
26-
<div className="max-w-screen-xl w-full flex lg:flex-row md:flex-row flex-col items-center mx-auto gap-y-10 gap-x-5 mt-12 px-5">
27-
<img
28-
src="/img/github_photo.png"
29-
width={400}
30-
height={419}
31-
alt="Haries' Profile Picture"
32-
style={{ borderRadius: "50%" }}
33-
/>
34-
<div className="flex flex-col">
35-
<p style={{ fontSize: 50 }} className="leading-10 mb-4">
36-
Hi! I am{" "}
37-
<span className="text-gray-300">Muhamad</span>{" "}
38-
Haries{" "}
39-
<span className="text-gray-300">Ramdhani</span>
40-
</p>
41-
<div className="flex flex-row gap-x-2 mb-8">
42-
{links.map((link) => (
43-
<SocialMediaButton
44-
key={link.image_filename}
45-
url={link.url}
46-
image_filename={link.image_filename}
47-
/>
48-
))}
49-
</div>
50-
<p
16+
function NavItems() {
17+
const { setActiveTab, activeTab } = useTab();
18+
19+
const tabs = [
20+
{ id: 'projects', label: 'Side Projects' },
21+
{ id: 'blog', label: 'Blog' },
22+
{ id: 'research', label: 'Research' },
23+
{ id: 'presentation', label: 'Presentation' },
24+
{ id: 'teaching', label: 'Teaching' },
25+
];
26+
27+
return (
28+
<div className="flex flex-wrap gap-x-8">
29+
{tabs.map((tab) => (
30+
<button
31+
key={tab.id}
32+
onClick={() => setActiveTab(tab.id)}
33+
className={`mb-5 px-2 rounded-lg ${activeTab === tab.id ? 'bg-gray-200' : 'text-gray-400'}`}
34+
style={{ fontSize: 24 }}
35+
>
36+
{tab.label}
37+
</button>
38+
))}
39+
</div>
40+
);
41+
}
42+
43+
export default function RootLayout({ children }: { children: React.ReactNode }) {
44+
return (
45+
<html lang="en">
46+
<body className={`${hubballi.className}`}>
47+
<GoogleAnalytics gaId="G-B1TRQFQPF3" />
48+
<TabProvider>
49+
<div className="max-w-screen-xl w-full flex lg:flex-row md:flex-row flex-col items-center mx-auto gap-y-10 gap-x-5 mt-12 px-5">
50+
<img
51+
src="/img/github_photo.png"
52+
width={400}
53+
height={419}
54+
alt="Haries' Profile Picture"
55+
style={{ borderRadius: "50%" }}
56+
/>
57+
<div className="flex flex-col">
58+
<p style={{ fontSize: 50 }} className="leading-10 mb-4">
59+
Hi! I am <span className="text-gray-300">Muhamad</span> Haries{" "}
60+
<span className="text-gray-300">Ramdhani</span>
61+
</p>
62+
<div className="flex flex-row gap-x-2 mb-8">
63+
{links.map((link) => (
64+
<SocialMediaButton
65+
key={link.image_filename}
66+
url={link.url}
67+
image_filename={link.image_filename}
68+
/>
69+
))}
70+
</div>
71+
<p
5172
style={{ fontSize: 24 }}
5273
className="leading-7 text-justify"
5374
>
@@ -119,52 +140,19 @@ export default function RootLayout({ children }: RootLayoutProps) {
119140
</Link>{" "}
120141
through the IMS studentship.
121142
</p>
122-
</div>
123-
</div>
124-
<div className="max-w-screen-xl w-full flex flex-col items-start gap-x-5 mt-12 mx-auto px-5">
125-
<div className="flex flex-wrap gap-x-8">
126-
<Link href="/">
127-
<h1
128-
style={{ fontSize: 24 }}
129-
className="mb-5 px-2 bg-gray-200 rounded-lg"
130-
>
131-
Side Projects
132-
</h1>
133-
</Link>
134-
<h1
135-
style={{ fontSize: 24 }}
136-
className="mb-5 text-gray-400"
137-
>
138-
Blog
139-
</h1>
140-
<h1
141-
style={{ fontSize: 24 }}
142-
className="mb-5 text-gray-400"
143-
>
144-
Research
145-
</h1>
146-
<h1
147-
style={{ fontSize: 24 }}
148-
className="mb-5 text-gray-400"
149-
>
150-
Presentation
151-
</h1>
152-
<h1
153-
style={{ fontSize: 24 }}
154-
className="mb-5 text-gray-400"
155-
>
156-
Teaching
157-
</h1>
158-
</div>
159-
160-
<div className="w-full grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-10 gap-y-4">
161-
{children}
162-
</div>
163-
</div>
164-
<div className="max-w-screen-xl w-full flex flex-col items-center gap-x-5 mt-12 mx-auto px-5">
165-
<p>Haries Ramdhani © 2025.</p>
166-
</div>
167-
</body>
168-
</html>
169-
);
170-
}
143+
</div>
144+
</div>
145+
<div className="max-w-screen-xl w-full flex flex-col items-start gap-x-5 mt-12 mx-auto px-5">
146+
<NavItems />
147+
<div className="w-full grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-10 gap-y-4">
148+
{children}
149+
</div>
150+
</div>
151+
<div className="max-w-screen-xl w-full flex flex-col items-center gap-x-5 mt-12 mx-auto px-5">
152+
<p>Haries Ramdhani © 2025.</p>
153+
</div>
154+
</TabProvider>
155+
</body>
156+
</html>
157+
);
158+
}

app/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import ProjectCard from "@/components/ProjectCard";
1+
import GenericCard from "@/components/GenericCard";
22

33
export const metadata = {
44
title: "Haries Ramdhani",
@@ -13,7 +13,7 @@ export const metadata = {
1313
export default function Home() {
1414
return (
1515
<>
16-
<ProjectCard />
16+
<GenericCard />
1717
</>
1818
);
1919
}

components/GenericCard.tsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
'use client';
2+
3+
import React, { useEffect, useState } from "react";
4+
import Card from "./Card";
5+
import { useTab } from "../context/TabContext";
6+
7+
interface CardData {
8+
url: string | null;
9+
image_filename: string;
10+
title: string;
11+
description: string;
12+
}
13+
14+
export default function GenericCard() {
15+
const { activeTab } = useTab();
16+
const [data, setData] = useState<CardData[]>([]);
17+
const [loading, setLoading] = useState(true);
18+
const [error, setError] = useState<string | null>(null);
19+
20+
useEffect(() => {
21+
const fetchData = async () => {
22+
try {
23+
setLoading(true);
24+
setError(null);
25+
console.log('Fetching data for:', activeTab);
26+
27+
const response = await fetch(`/data/${activeTab}.json`);
28+
29+
if (!response.ok) {
30+
throw new Error(`Failed to load ${activeTab} data`);
31+
}
32+
33+
const jsonData = await response.json();
34+
setData(jsonData);
35+
} catch (err) {
36+
console.error('Error fetching data:', err);
37+
setError(`Failed to load ${activeTab} data`);
38+
setData([]);
39+
} finally {
40+
setLoading(false);
41+
}
42+
};
43+
44+
fetchData();
45+
}, [activeTab]);
46+
47+
if (loading) return <div>Loading...</div>;
48+
if (error) return <div>{error}</div>;
49+
50+
return (
51+
<>
52+
{data.map((item) => (
53+
<Card
54+
key={item.image_filename}
55+
url={item.url ?? '#'}
56+
image_filename={item.image_filename}
57+
title={item.title}
58+
description={item.description}
59+
/>
60+
))}
61+
</>
62+
);
63+
}

components/ProjectCard.tsx

Lines changed: 0 additions & 38 deletions
This file was deleted.

context/TabContext.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use client';
2+
3+
import React, { createContext, useContext, useState } from "react";
4+
5+
type TabContextType = {
6+
activeTab: string;
7+
setActiveTab: (tab: string) => void;
8+
};
9+
10+
const TabContext = createContext<TabContextType | undefined>(undefined);
11+
12+
export function TabProvider({ children }: { children: React.ReactNode }) {
13+
const [activeTab, setActiveTab] = useState('projects');
14+
15+
return (
16+
<TabContext.Provider value={{ activeTab, setActiveTab }}>
17+
{children}
18+
</TabContext.Provider>
19+
);
20+
}
21+
22+
export function useTab() {
23+
const context = useContext(TabContext);
24+
if (context === undefined) {
25+
throw new Error('useTab must be used within a TabProvider');
26+
}
27+
return context;
28+
}

public/data/blog.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
{
3+
"url": "https://github.com/SPARC-FAIR-Codeathon/SPARCTA",
4+
"image_filename": "sparcta",
5+
"title": "SPARCTA",
6+
"description": "SPARC Tiff Annotator (3rd Prize Winner at the SPARC FAIR CODEATHON 2024)"
7+
}
8+
]

0 commit comments

Comments
 (0)