import React, { useCallback, useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import { groupsApi } from "../api/groups"; import type { GroupListItem } from "../../packages/shared/src/types"; import { useAuth } from "../context/AuthContext"; const styles = { container: { maxWidth: 800, margin: "0 auto", padding: "24px 16px", } satisfies React.CSSProperties, header: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 24, } satisfies React.CSSProperties, title: { fontSize: 28, fontWeight: 700, margin: 0, } satisfies React.CSSProperties, createBtn: { padding: "10px 20px", backgroundColor: "#3b82f6", color: "#fff", border: "none", borderRadius: 8, fontSize: 14, fontWeight: 600, cursor: "pointer", minHeight: 44, minWidth: 44, } satisfies React.CSSProperties, groupCard: { border: "1px solid #e5e7eb", borderRadius: 12, padding: 20, marginBottom: 12, cursor: "pointer", transition: "box-shadow 0.15s", } satisfies React.CSSProperties, groupName: { fontSize: 18, fontWeight: 600, margin: "0 0 4px 0", } satisfies React.CSSProperties, groupDesc: { fontSize: 14, color: "#6b7280", margin: "0 0 8px 0", } satisfies React.CSSProperties, groupMeta: { display: "flex", gap: 12, fontSize: 13, color: "#9ca3af", } satisfies React.CSSProperties, badge: { display: "inline-block", padding: "2px 8px", borderRadius: 6, fontSize: 11, fontWeight: 600, } satisfies React.CSSProperties, adminBadge: { backgroundColor: "#dbeafe", color: "#1d4ed8", } satisfies React.CSSProperties, memberBadge: { backgroundColor: "#f3f4f6", color: "#6b7280", } satisfies React.CSSProperties, empty: { textAlign: "center" as const, padding: 60, color: "#9ca3af", }, loadingText: { textAlign: "center" as const, padding: 60, color: "#9ca3af", fontSize: 16, }, errorText: { textAlign: "center" as const, padding: 40, color: "#ef4444", fontSize: 14, }, }; export function GroupsListPage() { const navigate = useNavigate(); const { user } = useAuth(); const [groups, setGroups] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const loadGroups = useCallback(async () => { setLoading(true); setError(null); try { const data = await groupsApi.listGroups(); setGroups(data); } catch (err: unknown) { setError(err instanceof Error ? err.message : "Failed to load groups"); } finally { setLoading(false); } }, []); useEffect(() => { loadGroups(); }, [loadGroups]); if (loading) { return
Loading groups...
; } if (error) { return (
{error}
); } return (

Groups

{groups.length === 0 ? (

You're not in any groups yet.

Create a group to start reading together with friends!

) : ( groups.map((group) => (
navigate(`/groups/${group.id}`)} onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); navigate(`/groups/${group.id}`); } }} role="button" tabIndex={0} >

{group.name}

{group.description && (

{group.description}

)}
{group.member_count} member{group.member_count !== 1 ? "s" : ""} {group.user_role === "admin" ? ( Admin ) : group.user_role === "member" ? ( Member ) : null}
)) )}
); }