"use client"; import { useState, useEffect } from "react"; import { CheckCircle, XCircle, Trash2, RotateCcw, History, Disc, Music } from "lucide-react"; import { api } from "@/lib/api"; import { cn } from "@/utils/cn"; interface DownloadHistory { id: string; subject: string; type: string; status: string; error?: string; createdAt: string; completedAt?: string; } export function HistoryTab() { const [history, setHistory] = useState([]); const [loading, setLoading] = useState(true); const [retrying, setRetrying] = useState>(new Set()); const fetchHistory = async () => { try { const data = await api.getDownloadHistory(); setHistory(data); } catch (error) { console.error("Failed to fetch download history:", error); } finally { setLoading(false); } }; useEffect(() => { fetchHistory(); // Refresh on window focus const handleFocus = () => fetchHistory(); window.addEventListener("focus", handleFocus); return () => window.removeEventListener("focus", handleFocus); }, []); const handleClear = async (id: string) => { try { await api.clearDownloadFromHistory(id); setHistory((prev) => prev.filter((h) => h.id !== id)); // Notify other components that download status has changed window.dispatchEvent(new CustomEvent("download-status-changed")); } catch (error) { console.error("Failed to clear download:", error); } }; const handleClearAll = async () => { try { await api.clearAllDownloadHistory(); setHistory([]); // Notify other components that download status has changed window.dispatchEvent(new CustomEvent("download-status-changed")); } catch (error) { console.error("Failed to clear all history:", error); } }; const handleRetry = async (id: string) => { try { setRetrying((prev) => new Set(prev).add(id)); const result = await api.retryFailedDownload(id); if (result.success) { // Remove from history (it's now in active) setHistory((prev) => prev.filter((h) => h.id !== id)); } } catch (error) { console.error("Failed to retry download:", error); } finally { setRetrying((prev) => { const next = new Set(prev); next.delete(id); return next; }); } }; const formatTime = (dateStr: string) => { const date = new Date(dateStr); const now = new Date(); const diff = now.getTime() - date.getTime(); if (diff < 60000) return "Just now"; if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`; if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`; return date.toLocaleDateString(); }; const completed = history.filter((h) => h.status === "completed"); const failed = history.filter((h) => h.status === "failed" || h.status === "exhausted"); if (loading) { return (
); } if (history.length === 0) { return (

No download history

Completed downloads will appear here

); } return (
{/* Header with clear all */}
{completed.length > 0 && ( {completed.length} )} {failed.length > 0 && ( {failed.length} )}
{/* History list */}
{/* Failed section first */} {failed.length > 0 && (
Failed ({failed.length})
{failed.map((item) => ( ))}
)} {/* Completed section */} {completed.length > 0 && (
Completed ({completed.length})
{completed.map((item) => ( ))}
)}
); } function HistoryItem({ item, onClear, onRetry, isRetrying, }: { item: DownloadHistory; onClear: (id: string) => void; onRetry?: (id: string) => void; isRetrying?: boolean; }) { const isCompleted = item.status === "completed"; const isFailed = item.status === "failed" || item.status === "exhausted"; const formatTime = (dateStr: string) => { const date = new Date(dateStr); const now = new Date(); const diff = now.getTime() - date.getTime(); if (diff < 60000) return "Just now"; if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`; if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`; return date.toLocaleDateString(); }; return (
{isCompleted ? ( ) : ( )}

{item.subject}

{item.type === "album" ? ( ) : ( )} {item.type} {formatTime(item.completedAt || item.createdAt)}
{item.error && (

{item.error}

)}
{isFailed && onRetry && ( )}
); }