"use client"; import { ChevronRight, Layers, Pencil, Plus, Globe, Lock, Trash2, } from "lucide-react"; import { CircleButton, LightButton } from "@/design-system/base/button"; import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import { useTranslations } from "next-intl"; import { toast } from "sonner"; import { PageLayout } from "@/components/ui/PageLayout"; import { PageHeader } from "@/components/ui/PageHeader"; import { CardList } from "@/components/ui/CardList"; import { actionCreateDeck, actionDeleteDeck, actionGetDecksByUserId, actionUpdateDeck, actionGetDeckById, } from "@/modules/deck/deck-action"; import type { ActionOutputDeck } from "@/modules/deck/deck-action-dto"; import { ImportButton, ExportButton } from "@/components/deck/ImportExport"; interface DeckCardProps { deck: ActionOutputDeck; onUpdateDeck: (deckId: number, updates: Partial) => void; onDeleteDeck: (deckId: number) => void; } const DeckCard = ({ deck, onUpdateDeck, onDeleteDeck }: DeckCardProps) => { const router = useRouter(); const t = useTranslations("decks"); const handleToggleVisibility = async (e: React.MouseEvent) => { e.stopPropagation(); const newVisibility = deck.visibility === "PUBLIC" ? "PRIVATE" : "PUBLIC"; const result = await actionUpdateDeck({ deckId: deck.id, visibility: newVisibility, }); if (result.success) { onUpdateDeck(deck.id, { visibility: newVisibility }); } else { toast.error(result.message); } }; const handleRename = async (e: React.MouseEvent) => { e.stopPropagation(); const newName = prompt(t("enterNewName"))?.trim(); if (newName && newName.length > 0) { const result = await actionUpdateDeck({ deckId: deck.id, name: newName, }); if (result.success) { onUpdateDeck(deck.id, { name: newName }); } else { toast.error(result.message); } } }; const handleDelete = async (e: React.MouseEvent) => { e.stopPropagation(); const confirm = prompt(t("confirmDelete", { name: deck.name })); if (confirm === deck.name) { const result = await actionDeleteDeck({ deckId: deck.id }); if (result.success) { onDeleteDeck(deck.id); } else { toast.error(result.message); } } }; return (
{ router.push(`/decks/${deck.id}`); }} >

{deck.name}

{deck.visibility === "PUBLIC" ? ( ) : ( )} {deck.visibility === "PUBLIC" ? t("public") : t("private")}

{t("deckInfo", { id: deck.id, name: deck.name, totalCards: deck.cardCount ?? 0, })}

{deck.visibility === "PUBLIC" ? ( ) : ( )}
); }; interface DecksClientProps { userId: string; } export function DecksClient({ userId }: DecksClientProps) { const t = useTranslations("decks"); const router = useRouter(); const [decks, setDecks] = useState([]); const [loading, setLoading] = useState(true); const loadDecks = async () => { setLoading(true); const result = await actionGetDecksByUserId(userId); if (result.success && result.data) { setDecks(result.data); } setLoading(false); }; useEffect(() => { loadDecks(); }, [userId]); const handleUpdateDeck = (deckId: number, updates: Partial) => { setDecks((prev) => prev.map((d) => (d.id === deckId ? { ...d, ...updates } : d)) ); }; const handleDeleteDeck = (deckId: number) => { setDecks((prev) => prev.filter((d) => d.id !== deckId)); }; const handleCreateDeck = async () => { const deckName = prompt(t("enterDeckName")); if (!deckName?.trim()) return; const result = await actionCreateDeck({ name: deckName.trim() }); if (result.success && result.deckId) { const deckResult = await actionGetDeckById({ deckId: result.deckId }); if (deckResult.success && deckResult.data) { setDecks((prev) => [...prev, deckResult.data!]); } } else { toast.error(result.message); } }; return (
{t("newDeck")}
{loading ? (

{t("loading")}

) : decks.length === 0 ? (

{t("noDecksYet")}

) : ( decks.map((deck) => ( )) )}
); }