"use client"; import Link from "next/link"; import ActionConfirmingDialog from "@/components/ui/action-confirming-dialog"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Progress } from "@/components/ui/progress"; import { useDeleteImportSession, useImportSessionStats, } from "@/lib/hooks/useImportSessions"; import { useTranslation } from "@/lib/i18n/client"; import { formatDistanceToNow } from "date-fns"; import { AlertCircle, CheckCircle2, ClipboardList, Clock, ExternalLink, Loader2, Trash2, } from "lucide-react"; import type { ZImportSessionWithStats } from "@karakeep/shared/types/importSessions"; interface ImportSessionCardProps { session: ZImportSessionWithStats; } function getStatusColor(status: string) { switch (status) { case "pending": return "bg-muted text-muted-foreground"; case "in_progress": return "bg-blue-500/10 text-blue-700 dark:text-blue-400"; case "completed": return "bg-green-500/10 text-green-700 dark:text-green-400"; case "failed": return "bg-destructive/10 text-destructive"; default: return "bg-muted text-muted-foreground"; } } function getStatusIcon(status: string) { switch (status) { case "pending": return ; case "in_progress": return ; case "completed": return ; case "failed": return ; default: return ; } } export function ImportSessionCard({ session }: ImportSessionCardProps) { const { t } = useTranslation(); const { data: liveStats } = useImportSessionStats(session.id); const deleteSession = useDeleteImportSession(); const statusLabels: Record = { pending: t("settings.import_sessions.status.pending"), in_progress: t("settings.import_sessions.status.in_progress"), completed: t("settings.import_sessions.status.completed"), failed: t("settings.import_sessions.status.failed"), }; // Use live stats if available, otherwise fallback to session stats const stats = liveStats || session; const progress = stats.totalBookmarks > 0 ? ((stats.completedBookmarks + stats.failedBookmarks) / stats.totalBookmarks) * 100 : 0; const canDelete = stats.status !== "in_progress"; return (

{session.name}

{t("settings.import_sessions.created_at", { time: formatDistanceToNow(session.createdAt, { addSuffix: true, }), })}

{getStatusIcon(stats.status)} {statusLabels[stats.status] ?? stats.status.replace("_", " ")}
{/* Progress Section */}

{t("settings.import_sessions.progress")}

{stats.completedBookmarks + stats.failedBookmarks} /{" "} {stats.totalBookmarks} {Math.round(progress)}%
{stats.totalBookmarks > 0 && ( )}
{/* Stats Breakdown */} {stats.totalBookmarks > 0 && (
{stats.pendingBookmarks > 0 && ( {t("settings.import_sessions.badges.pending", { count: stats.pendingBookmarks, })} )} {stats.processingBookmarks > 0 && ( {t("settings.import_sessions.badges.processing", { count: stats.processingBookmarks, })} )} {stats.completedBookmarks > 0 && ( {t("settings.import_sessions.badges.completed", { count: stats.completedBookmarks, })} )} {stats.failedBookmarks > 0 && ( {t("settings.import_sessions.badges.failed", { count: stats.failedBookmarks, })} )}
)} {/* Root List Link */} {session.rootListId && (
{t("settings.import_sessions.imported_to")} {t("settings.import_sessions.view_list")}
)} {/* Message */} {stats.message && (
{stats.message}
)} {/* Actions */}
{canDelete && ( {t("settings.import_sessions.delete_dialog_description", { name: session.name, })}
} actionButton={(setDialogOpen) => ( )} > )}
); }