Skip to content

Commit 136f3f1

Browse files
committed
feat: implement dynamic routing for event kinds and add KindPageClient component
1 parent c11197a commit 136f3f1

3 files changed

Lines changed: 142 additions & 1 deletion

File tree

src/app/[kind]/KindPageClient.tsx

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
'use client'
2+
3+
import { useState } from 'react'
4+
import { useRouter } from 'next/navigation'
5+
import { Sidebar } from '@/components/Sidebar'
6+
import { MainContent } from '@/components/MainContent'
7+
import { SearchBar } from '@/components/SearchBar'
8+
import { ThemeToggle } from '@/components/ThemeToggle'
9+
10+
interface KindPageClientProps {
11+
kindNum: number
12+
}
13+
14+
export function KindPageClient({ kindNum }: KindPageClientProps) {
15+
const router = useRouter()
16+
const [searchQuery, setSearchQuery] = useState('')
17+
const [sidebarOpen, setSidebarOpen] = useState(false)
18+
19+
return (
20+
<div className="flex h-screen bg-gray-100 dark:bg-gray-900 overflow-hidden">
21+
{/* Mobile sidebar overlay */}
22+
{sidebarOpen && (
23+
<div
24+
className="fixed inset-0 z-40 bg-black bg-opacity-25 lg:hidden"
25+
onClick={() => setSidebarOpen(false)}
26+
/>
27+
)}
28+
29+
{/* Sidebar */}
30+
<div className={`
31+
flex flex-col w-80 bg-white dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700
32+
lg:relative lg:translate-x-0
33+
fixed inset-y-0 left-0 z-50 transform transition-transform duration-300 ease-in-out
34+
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
35+
`}>
36+
<div className="p-4 border-b border-gray-200 dark:border-gray-700">
37+
<div className="flex items-center justify-between mb-3">
38+
<h1 className="text-xl font-bold text-gray-900 dark:text-gray-100">
39+
Nostr Event Kinds
40+
</h1>
41+
<div className="flex items-center gap-2">
42+
<div className="hidden lg:block">
43+
<ThemeToggle />
44+
</div>
45+
<button
46+
className="lg:hidden p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700"
47+
onClick={() => setSidebarOpen(false)}
48+
>
49+
<span className="text-gray-500 dark:text-gray-400"></span>
50+
</button>
51+
</div>
52+
</div>
53+
<SearchBar
54+
searchQuery={searchQuery}
55+
onSearchChange={setSearchQuery}
56+
/>
57+
</div>
58+
<Sidebar
59+
selectedKind={kindNum}
60+
onKindSelect={(kind) => {
61+
// Navigate to the new kind URL
62+
router.push(`/${kind}`)
63+
setSidebarOpen(false)
64+
}}
65+
searchQuery={searchQuery}
66+
/>
67+
</div>
68+
69+
{/* Main content */}
70+
<div className="flex-1 flex flex-col lg:ml-0">
71+
{/* Mobile header */}
72+
<div className="lg:hidden flex items-center justify-between p-4 bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
73+
<button
74+
onClick={() => setSidebarOpen(true)}
75+
className="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700"
76+
>
77+
<span className="text-gray-700 dark:text-gray-300"></span>
78+
</button>
79+
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">
80+
Kind {kindNum}
81+
</h2>
82+
<div className="block lg:hidden">
83+
<ThemeToggle />
84+
</div>
85+
</div>
86+
87+
<MainContent selectedKind={kindNum} />
88+
</div>
89+
</div>
90+
)
91+
}

src/app/[kind]/page.tsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { notFound } from 'next/navigation'
2+
import { eventKinds } from '@/data/eventKinds'
3+
import { KindPageClient } from './KindPageClient'
4+
5+
interface KindPageProps {
6+
params: Promise<{
7+
kind: string
8+
}>
9+
}
10+
11+
export async function generateStaticParams() {
12+
// Generate static pages for all known event kinds
13+
return eventKinds.map((eventKind) => ({
14+
kind: eventKind.kind.toString(),
15+
}))
16+
}
17+
18+
export async function generateMetadata({ params }: KindPageProps) {
19+
const resolvedParams = await params
20+
const kindNum = parseInt(resolvedParams.kind)
21+
const eventKind = eventKinds.find(kind => kind.kind === kindNum)
22+
23+
if (!eventKind) {
24+
return {
25+
title: 'Event Kind Not Found - Nostr Event Kinds Reference',
26+
description: 'The requested event kind was not found',
27+
}
28+
}
29+
30+
return {
31+
title: `Kind ${kindNum}: ${eventKind.name} - Nostr Event Kinds Reference`,
32+
description: eventKind.description,
33+
}
34+
}
35+
36+
export default async function KindPage({ params }: KindPageProps) {
37+
const resolvedParams = await params
38+
const kindNum = parseInt(resolvedParams.kind)
39+
40+
// Validate that the kind exists
41+
const eventKind = eventKinds.find(kind => kind.kind === kindNum)
42+
if (!eventKind || isNaN(kindNum)) {
43+
notFound()
44+
}
45+
46+
return <KindPageClient kindNum={kindNum} />
47+
}

src/app/page.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
'use client'
22

33
import { useState } from 'react'
4+
import { useRouter } from 'next/navigation'
45
import { Sidebar } from '@/components/Sidebar'
56
import { MainContent } from '@/components/MainContent'
67
import { SearchBar } from '@/components/SearchBar'
78
import { ThemeToggle } from '@/components/ThemeToggle'
89

910
export default function Home() {
11+
const router = useRouter()
1012
const [selectedKind, setSelectedKind] = useState<number | null>(null)
1113
const [searchQuery, setSearchQuery] = useState('')
1214
const [sidebarOpen, setSidebarOpen] = useState(false)
@@ -53,7 +55,8 @@ export default function Home() {
5355
<Sidebar
5456
selectedKind={selectedKind}
5557
onKindSelect={(kind) => {
56-
setSelectedKind(kind)
58+
// Navigate to the specific kind URL
59+
router.push(`/${kind}`)
5760
setSidebarOpen(false) // Close sidebar on mobile after selection
5861
}}
5962
searchQuery={searchQuery}

0 commit comments

Comments
 (0)