"use client"; import { useState, useEffect, useCallback } from "react"; import { useAuth } from "@/lib/AuthContext"; import { useRouter } from "next/navigation"; import { MessageSquare, Search, Plus, X, Crown, Star, Pin, Clock, AlertTriangle, CheckCircle, Loader2, Lock, Users, MessageCircle, FileText, } from "lucide-react"; import PremiumBadge from "@/components/PremiumBadge"; interface Category { id: string; name: string; description?: string; icon?: string; order?: number; } interface Thread { id: string; title: string; content: string; categoryId: string; groupId?: string | null; pinned: boolean; shariahStatus: "pending" | "approved" | "rejected"; shariahFlags?: string; createdAt: string; author: { id: string; name: string; isPremium: boolean; isPro: boolean; }; category: { id: string; name: string; icon?: string; }; _count: { posts: number; }; group?: { id: string; name: string; } | null; } interface Group { id: string; name: string; description?: string; _count: { members: number; threads: number; }; } const SHARIAH_LABELS: Record = { pending: { label: "Pending Review", color: "text-amber-400", icon: Clock }, approved: { label: "Shariah Compliant", color: "text-emerald-400", icon: CheckCircle }, rejected: { label: "Flagged", color: "text-red-400", icon: AlertTriangle }, }; export default function ForumPage() { const { user, token, loading } = useAuth(); const router = useRouter(); const [categories, setCategories] = useState([]); const [threads, setThreads] = useState([]); const [groups, setGroups] = useState([]); const [loadingData, setLoadingData] = useState(true); const [error, setError] = useState(null); // Filters const [activeCategory, setActiveCategory] = useState(null); const [searchQuery, setSearchQuery] = useState(""); // Create thread modal const [showCreateModal, setShowCreateModal] = useState(false); const [createForm, setCreateForm] = useState({ title: "", content: "", categoryId: "", groupId: "", }); const [creating, setCreating] = useState(false); const [createError, setCreateError] = useState(null); const canPost = user?.isPremium || user?.isPro; const fetchCategories = useCallback(async () => { try { const res = await fetch("/mobile/api/forum/categories"); const data = await res.json(); if (res.ok) { setCategories(data.categories); // Auto-select first category in modal if (data.categories.length > 0) { setCreateForm((f) => ({ ...f, categoryId: data.categories[0].id, })); } } } catch { // ignore } }, []); const fetchGroups = useCallback(async () => { if (!canPost) return; try { const res = await fetch("/mobile/api/groups", { headers: { Authorization: `Bearer ${token}`, }, }); const data = await res.json(); if (res.ok) { setGroups(data.groups || []); } } catch { // ignore } }, [token, canPost]); const fetchThreads = useCallback(async () => { setLoadingData(true); setError(null); try { const params = new URLSearchParams(); if (activeCategory) params.set("categoryId", activeCategory); if (searchQuery.trim()) params.set("search", searchQuery.trim()); const res = await fetch(`/mobile/api/forum/threads?${params.toString()}`); const data = await res.json(); if (res.ok) { setThreads(data.threads); } else { setError(data.error || "Failed to load threads"); } } catch { setError("Network error. Please try again."); } finally { setLoadingData(false); } }, [activeCategory, searchQuery]); useEffect(() => { if (!loading && !token) { router.push("/auth"); return; } }, [loading, token, router]); useEffect(() => { if (token) { fetchCategories(); } }, [token, fetchCategories]); useEffect(() => { if (token) { fetchThreads(); } }, [token, fetchThreads]); useEffect(() => { if (token) { fetchGroups(); } }, [token, fetchGroups]); // Debounce search useEffect(() => { const timer = setTimeout(() => { if (token) fetchThreads(); }, 400); return () => clearTimeout(timer); }, [searchQuery]); const handleCreateThread = async (e: React.FormEvent) => { e.preventDefault(); setCreateError(null); setCreating(true); try { const res = await fetch("/mobile/api/forum/threads", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify({ title: createForm.title, content: createForm.content, categoryId: createForm.categoryId, ...(createForm.groupId ? { groupId: createForm.groupId } : {}), }), }); const data = await res.json(); if (res.ok) { setShowCreateModal(false); setCreateForm({ title: "", content: "", categoryId: categories[0]?.id || "", groupId: "" }); fetchThreads(); } else { setCreateError(data.error || "Failed to create thread"); } } catch { setCreateError("Network error. Please try again."); } finally { setCreating(false); } }; function timeAgo(dateStr: string): string { const now = Date.now(); const then = new Date(dateStr).getTime(); const diffSec = Math.floor((now - then) / 1000); if (diffSec < 60) return "just now"; const diffMin = Math.floor(diffSec / 60); if (diffMin < 60) return `${diffMin}m ago`; const diffHr = Math.floor(diffMin / 60); if (diffHr < 24) return `${diffHr}h ago`; const diffDay = Math.floor(diffHr / 24); if (diffDay < 7) return `${diffDay}d ago`; return new Date(dateStr).toLocaleDateString(); } if (loading) { return (
); } if (!user) return null; return (
{/* Header */}

Forum

Community Discussions

{canPost && ( )}
{/* Premium gating banner for free users */} {!canPost && (

Free members can browse.{" "} Premium or{" "} Pro required to post.

)} {/* Search bar */}
setSearchQuery(e.target.value)} className="w-full bg-[#111118] border border-gray-800/60 rounded-xl pl-10 pr-4 py-3 text-sm text-white placeholder-gray-600 focus:outline-none focus:border-[#D4AF37]/40 transition" />
{/* Category pills */}
{categories.map((cat) => { const isActive = activeCategory === cat.id; return ( ); })}
{/* Threads list */}
{loadingData ? (

Loading threads...

) : error ? (

{error}

) : threads.length === 0 ? (

{searchQuery || activeCategory ? "No threads found" : "No discussions yet"}

{searchQuery || activeCategory ? "Try a different search or category" : canPost ? "Be the first to start a discussion!" : "No discussions yet. Check back soon."}

{canPost && !searchQuery && !activeCategory && ( )}
) : (
{threads.map((thread) => { const shariahInfo = SHARIAH_LABELS[thread.shariahStatus]; const ShariahIcon = shariahInfo.icon; return ( ); })}
)}
{/* Create thread modal */} {showCreateModal && (
setShowCreateModal(false)} />

New Thread

{groups.length > 0 && canPost && (

Group posts are only visible to group members.

)}
setCreateForm((f) => ({ ...f, title: e.target.value })) } placeholder="What's on your mind?" required maxLength={200} className="w-full bg-[#0a0a0f] border border-gray-800/60 rounded-xl px-3.5 py-3 text-sm text-white placeholder-gray-600 focus:outline-none focus:border-[#D4AF37]/40 transition" />