import { useCallback, useEffect, useState } from "react"; import { Link, useParams } from "wouter"; import { ApiClientError, apiClient } from "../api"; import { CreateCardModal } from "../components/CreateCardModal"; import { DeleteCardModal } from "../components/DeleteCardModal"; import { EditCardModal } from "../components/EditCardModal"; interface Card { id: string; deckId: string; front: string; back: string; state: number; due: string; reps: number; lapses: number; createdAt: string; updatedAt: string; } interface Deck { id: string; name: string; description: string | null; } const CardStateLabels: Record = { 0: "New", 1: "Learning", 2: "Review", 3: "Relearning", }; export function DeckDetailPage() { const { deckId } = useParams<{ deckId: string }>(); const [deck, setDeck] = useState(null); const [cards, setCards] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); const [editingCard, setEditingCard] = useState(null); const [deletingCard, setDeletingCard] = useState(null); const fetchDeck = useCallback(async () => { if (!deckId) return; const authHeader = apiClient.getAuthHeader(); if (!authHeader) { throw new ApiClientError("Not authenticated", 401); } const res = await fetch(`/api/decks/${deckId}`, { headers: authHeader, }); if (!res.ok) { const errorBody = await res.json().catch(() => ({})); throw new ApiClientError( (errorBody as { error?: string }).error || `Request failed with status ${res.status}`, res.status, ); } const data = await res.json(); setDeck(data.deck); }, [deckId]); const fetchCards = useCallback(async () => { if (!deckId) return; const authHeader = apiClient.getAuthHeader(); if (!authHeader) { throw new ApiClientError("Not authenticated", 401); } const res = await fetch(`/api/decks/${deckId}/cards`, { headers: authHeader, }); if (!res.ok) { const errorBody = await res.json().catch(() => ({})); throw new ApiClientError( (errorBody as { error?: string }).error || `Request failed with status ${res.status}`, res.status, ); } const data = await res.json(); setCards(data.cards); }, [deckId]); const fetchData = useCallback(async () => { setIsLoading(true); setError(null); try { await Promise.all([fetchDeck(), fetchCards()]); } catch (err) { if (err instanceof ApiClientError) { setError(err.message); } else { setError("Failed to load data. Please try again."); } } finally { setIsLoading(false); } }, [fetchDeck, fetchCards]); useEffect(() => { fetchData(); }, [fetchData]); if (!deckId) { return (

Invalid deck ID

Back to decks
); } return (
← Back to Decks
{isLoading &&

Loading...

} {error && (
{error}
)} {!isLoading && !error && deck && (

{deck.name}

{deck.description && (

{deck.description}

)}

Cards ({cards.length})

{cards.length === 0 && (

This deck has no cards yet.

Add cards to start studying!

)} {cards.length > 0 && (
    {cards.map((card) => (
  • Front:

    {card.front}

    Back:

    {card.back}

    State: {CardStateLabels[card.state] || "Unknown"} Reviews: {card.reps} Lapses: {card.lapses}
  • ))}
)}
)} {deckId && ( setIsCreateModalOpen(false)} onCardCreated={fetchCards} /> )} {deckId && ( setEditingCard(null)} onCardUpdated={fetchCards} /> )} {deckId && ( setDeletingCard(null)} onCardDeleted={fetchCards} /> )}
); }