"use client"; import { useState, useEffect, useCallback } from "react"; import { useAuth } from "@/lib/AuthContext"; import { useRouter } from "next/navigation"; import { Lock, Users, Plus, X, Crown, Loader2, ChevronRight, } from "lucide-react"; import ErrorFeedback from "@/components/ErrorFeedback"; interface GroupMember { id: string; userId: string; role: "owner" | "admin" | "member"; user: { id: string; name: string; isPremium: boolean; isPro: boolean; }; } interface Group { id: string; name: string; description?: string; inviteCode: string; createdAt: string; ownerId: string; owner: { id: string; name: string; isPremium: boolean; isPro: boolean; }; members: GroupMember[]; _count: { members: number; threads: number; }; } export default function GroupsPage() { const { user, token, loading } = useAuth(); const router = useRouter(); const [groups, setGroups] = useState([]); const [loadingData, setLoadingData] = useState(true); const [error, setError] = useState(null); // Create group modal const [showCreateModal, setShowCreateModal] = useState(false); const [createName, setCreateName] = useState(""); const [createDescription, setCreateDescription] = useState(""); const [creating, setCreating] = useState(false); const [createError, setCreateError] = useState(null); // Join group modal const [showJoinModal, setShowJoinModal] = useState(false); const [joinCode, setJoinCode] = useState(""); const [joining, setJoining] = useState(false); const [joinError, setJoinError] = useState(null); const [joinSuccess, setJoinSuccess] = useState(null); const canCreateGroup = user?.isPremium || user?.isPro; const fetchGroups = useCallback(async () => { setLoadingData(true); setError(null); try { const res = await fetch("/mobile/api/groups", { headers: { Authorization: `Bearer ${token}`, }, }); const data = await res.json(); if (res.ok) { setGroups(data.groups || []); } else { setError(data.error || "Failed to load groups"); } } catch { setError("Network error. Please try again."); } finally { setLoadingData(false); } }, [token]); useEffect(() => { if (!loading && !token) { router.push("/auth"); return; } }, [loading, token, router]); useEffect(() => { if (token) { fetchGroups(); } }, [token, fetchGroups]); const handleCreateGroup = async (e: React.FormEvent) => { e.preventDefault(); setCreateError(null); setCreating(true); try { const res = await fetch("/mobile/api/groups", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify({ name: createName.trim(), description: createDescription.trim() || undefined, }), }); const data = await res.json(); if (res.ok) { setShowCreateModal(false); setCreateName(""); setCreateDescription(""); fetchGroups(); } else { setCreateError(data.error || "Failed to create group"); } } catch { setCreateError("Network error. Please try again."); } finally { setCreating(false); } }; const handleJoinGroup = async (e: React.FormEvent) => { e.preventDefault(); setJoinError(null); setJoinSuccess(null); setJoining(true); try { const res = await fetch("/mobile/api/groups/join", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify({ inviteCode: joinCode.trim(), }), }); const data = await res.json(); if (res.ok) { setJoinSuccess("Joined group successfully!"); setJoinCode(""); setTimeout(() => { setShowJoinModal(false); setJoinSuccess(null); fetchGroups(); }, 1200); } else { setJoinError(data.error || "Failed to join group"); } } catch { setJoinError("Network error. Please try again."); } finally { setJoining(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 */}

Groups

Private forum groups

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

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

)} {/* Groups list */}
{loadingData ? (

Loading groups...

) : error ? ( ) : groups.length === 0 ? (

No groups yet

{canCreateGroup ? "Create a private group to discuss topics with select members." : "Join a private group using an invite code."}

{canCreateGroup && ( )}
) : (
{groups.map((group) => ( ))}
)}
{/* Create group modal */} {showCreateModal && (
setShowCreateModal(false)} />

Create Group

setCreateName(e.target.value)} placeholder="e.g., Book Club, Quran Study" required maxLength={100} 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" />