()
| 15 | } |
| 16 | |
| 17 | const HistoryPage: React.FC = () => { |
| 18 | const [books, setBooks] = useState<DownloadedBook[]>([]); |
| 19 | const [loading, setLoading] = useState(false); |
| 20 | const [error, setError] = useState(''); |
| 21 | const [page, setPage] = useState(1); |
| 22 | const [hasMore, setHasMore] = useState(true); |
| 23 | const { getCoverUrl } = useCoverCache(); |
| 24 | |
| 25 | useEffect(() => { |
| 26 | loadHistory(); |
| 27 | }, [page]); |
| 28 | |
| 29 | const loadHistory = async () => { |
| 30 | setLoading(true); |
| 31 | setError(''); |
| 32 | |
| 33 | try { |
| 34 | const result: any = await invoke('get_download_history', { |
| 35 | order: 'date_down', |
| 36 | page: page, |
| 37 | limit: 20 |
| 38 | }); |
| 39 | |
| 40 | if (result.books) { |
| 41 | if (page === 1) { |
| 42 | setBooks(result.books); |
| 43 | } else { |
| 44 | setBooks(prev => [...prev, ...result.books]); |
| 45 | } |
| 46 | setHasMore(result.books.length === 20); |
| 47 | } else { |
| 48 | setError('No download history found'); |
| 49 | setHasMore(false); |
| 50 | } |
| 51 | } catch (err: any) { |
| 52 | console.error('Failed to load history:', err); |
| 53 | setError(err.toString() || 'Failed to load download history. Please login first.'); |
| 54 | setHasMore(false); |
| 55 | } finally { |
| 56 | setLoading(false); |
| 57 | } |
| 58 | }; |
| 59 | |
| 60 | const formatFileSize = (bytes?: number) => { |
| 61 | if (!bytes) return 'Unknown'; |
| 62 | const mb = bytes / (1024 * 1024); |
| 63 | return `${mb.toFixed(2)} MB`; |
| 64 | }; |
| 65 | |
| 66 | const formatDate = (dateStr?: string) => { |
| 67 | if (!dateStr) return 'Unknown date'; |
| 68 | try { |
| 69 | const date = new Date(dateStr); |
| 70 | return date.toLocaleDateString('en-US', { |
| 71 | year: 'numeric', |
| 72 | month: 'short', |
| 73 | day: 'numeric', |
| 74 | hour: '2-digit', |
nothing calls this directly
no test coverage detected