diff --git a/src/app/forum/page.tsx b/src/app/forum/page.tsx index 5750a7f..a721744 100644 --- a/src/app/forum/page.tsx +++ b/src/app/forum/page.tsx @@ -2,73 +2,162 @@ import { useState, useEffect } from 'react' import { useAuth } from '@/lib/AuthContext' -import { Plus, ChevronRight } from 'lucide-react' +import { Plus, ChevronRight, MessageCircle, X, ArrowLeft } from 'lucide-react' interface Category { id: string; name: string; description: string; icon: string } -interface Thread { id: string; title: string; content: string; author: { name: string }; category: { name: string }; _count: { posts: number }; createdAt: string } +interface Thread { + id: string; title: string; content: string + author: { name: string }; category: { name: string } + _count: { posts: number }; createdAt: string +} export default function ForumPage() { const { token } = useAuth() const [categories, setCategories] = useState([]) const [threads, setThreads] = useState([]) - const [selectedCat, setSelectedCat] = useState(null) + const [selectedCat, setSelectedCat] = useState(null) const [view, setView] = useState<'categories' | 'threads'>('categories') const [showCreate, setShowCreate] = useState(false) + const [loading, setLoading] = useState(true) + const [toast, setToast] = useState('') - useEffect(() => { fetch('/api/forum/categories').then(r => r.json()).then(d => setCategories(d.categories || [])) }, []) + useEffect(() => { + fetch('/api/forum/categories') + .then(r => r.json()) + .then(d => setCategories(d.categories || [])) + .finally(() => setLoading(false)) + }, []) - const loadThreads = async (catId?: string) => { - const params = catId ? `?categoryId=${catId}` : '' - const res = await fetch(`/api/forum/threads${params}`) + const loadThreads = async (catId: string) => { + setLoading(true) + const res = await fetch(`/api/forum/threads?categoryId=${catId}`) const data = await res.json() setThreads(data.threads || []) + setLoading(false) } + const showToast = (msg: string) => { setToast(msg); setTimeout(() => setToast(''), 3000) } + return ( -
-
-

Forum

+
+ + {/* Header */} +
+
+ {view === 'threads' && ( + + )} +
+

{view === 'threads' && selectedCat ? selectedCat.name : 'Forum'}

+

+ {view === 'categories' ? 'Community discussions' : `${threads.length} threads`} +

+
+
{token && ( - + )}
- {view === 'categories' ? ( -
- {categories.map(c => ( - ))}
- ) : ( -
- - {threads.map(t => ( -
-

{t.title}

-

{t.content}

-
- {t.author.name}{t.category.name}{t._count.posts} replies{new Date(t.createdAt).toLocaleDateString()} + )} + + {/* Threads view */} + {!loading && view === 'threads' && ( +
+ {threads.length === 0 ? ( +
+
💬
+

No threads yet

+

Start the first discussion

+
+ ) : threads.map(t => ( +
+

{t.title}

+

{t.content}

+
+
+
+ {t.author.name[0]} +
+ {t.author.name} +
+
+ + {t._count.posts} +
))}
)} - {showCreate && token && setShowCreate(false)} onCreated={() => { setShowCreate(false); if (selectedCat) loadThreads(selectedCat) }} />} + + {/* Toast */} + {toast && ( +
+ {toast} +
+ )} + + {/* Create thread bottom sheet */} + {showCreate && token && ( + setShowCreate(false)} + onCreated={() => { if (selectedCat) loadThreads(selectedCat.id); showToast('Thread posted!') }} + showToast={showToast} + /> + )}
) } -function CreateThreadModal({ token, categories, onClose, onCreated }: { token: string; categories: Category[]; onClose: () => void; onCreated: () => void }) { +function CreateThreadSheet({ token, categories, onClose, onCreated, showToast }: { + token: string; categories: Category[]; onClose: () => void; onCreated: () => void; showToast: (m: string) => void +}) { const [title, setTitle] = useState('') const [content, setContent] = useState('') const [categoryId, setCategoryId] = useState(categories[0]?.id || '') @@ -76,29 +165,58 @@ function CreateThreadModal({ token, categories, onClose, onCreated }: { token: s const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() + if (!categoryId) return setLoading(true) - const res = await fetch('/api/forum/threads', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ title, content, categoryId }) }) + try { + const res = await fetch('/api/forum/threads', { + method: 'POST', + headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, + body: JSON.stringify({ title, content, categoryId }), + }) + const data = await res.json() + if (res.ok) { onCreated(); onClose() } + else showToast(data.error || 'Failed to post') + } catch { showToast('Something went wrong') } setLoading(false) - if (res.ok) { onCreated() } else { const d = await res.json(); alert(d.error) } } return ( -
-
-

New Thread

- setCategoryId(e.target.value)} + className="w-full bg-[#0a0a0f] border border-gray-800 rounded-2xl px-4 py-4 text-sm text-white focus:border-[#D4AF37]/50 focus:outline-none" + > + {categories.map(c => )} - setTitle(e.target.value)} required - className="w-full bg-[#0a0a0f] border border-gray-700 rounded px-3 py-2 text-sm focus:border-[#D4AF37] outline-none" /> -