diff --git a/app/page.tsx b/app/page.tsx index f305589..d3e57a3 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,6 +1,7 @@ 'use client'; import { FileConverter } from '@/components/converter/FileConverter'; +import { ConversionHistory } from '@/components/converter/ConversionHistory'; import { ThemeToggle } from '@/components/layout/ThemeToggle'; import { ToastProvider } from '@/components/ui/Toast'; @@ -23,7 +24,10 @@ export default function Home() { {/* Main content */}
- +
+ + +
{/* Footer */} diff --git a/components/converter/ConversionHistory.tsx b/components/converter/ConversionHistory.tsx new file mode 100644 index 0000000..f751133 --- /dev/null +++ b/components/converter/ConversionHistory.tsx @@ -0,0 +1,169 @@ +'use client'; + +import * as React from 'react'; +import { History, Trash2, ArrowRight, Clock } from 'lucide-react'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/Card'; +import { Button } from '@/components/ui/Button'; +import { formatFileSize } from '@/lib/utils/fileUtils'; +import { getHistory, clearHistory, removeHistoryItem } from '@/lib/storage/history'; +import type { ConversionHistoryItem } from '@/types/conversion'; + +export function ConversionHistory() { + const [history, setHistory] = React.useState([]); + + // Load history on mount and listen for updates + React.useEffect(() => { + const loadHistory = () => { + const items = getHistory(); + setHistory(items); + }; + + loadHistory(); + + // Listen for storage changes (e.g., from other tabs) + const handleStorageChange = (e: StorageEvent) => { + if (e.key === 'convert-ui-history') { + loadHistory(); + } + }; + + // Listen for custom event (same-page updates) + const handleHistoryUpdate = () => { + loadHistory(); + }; + + window.addEventListener('storage', handleStorageChange); + window.addEventListener('conversionHistoryUpdated', handleHistoryUpdate); + + return () => { + window.removeEventListener('storage', handleStorageChange); + window.removeEventListener('conversionHistoryUpdated', handleHistoryUpdate); + }; + }, []); + + const handleClearHistory = () => { + if (confirm('Are you sure you want to clear all conversion history?')) { + clearHistory(); + setHistory([]); + } + }; + + const handleRemoveItem = (id: string) => { + removeHistoryItem(id); + setHistory((prev) => prev.filter((item) => item.id !== id)); + }; + + const formatTimestamp = (timestamp: number) => { + const date = new Date(timestamp); + const now = new Date(); + const diffMs = now.getTime() - date.getTime(); + const diffMins = Math.floor(diffMs / 60000); + const diffHours = Math.floor(diffMs / 3600000); + const diffDays = Math.floor(diffMs / 86400000); + + if (diffMins < 1) return 'Just now'; + if (diffMins < 60) return `${diffMins} minute${diffMins > 1 ? 's' : ''} ago`; + if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`; + if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`; + + return date.toLocaleDateString(); + }; + + if (history.length === 0) { + return ( + + + + + Conversion History + + Your recent conversions will appear here + + +
+ +

No conversion history yet

+

Convert some files to see them here

+
+
+
+ ); + } + + return ( + + +
+
+ + + Conversion History + + + Recent conversions ({history.length} item{history.length > 1 ? 's' : ''}) + +
+ +
+
+ +
+ {history.map((item) => ( +
+
+
+ {/* File conversion info */} +
+ + {item.inputFileName} + + + + {item.outputFileName} + +
+ + {/* Format conversion */} +
+ + {item.inputFormat} + + + + {item.outputFormat} + + + {formatFileSize(item.fileSize)} +
+ + {/* Timestamp */} +
+ + {formatTimestamp(item.timestamp)} +
+
+ + {/* Remove button */} + +
+
+ ))} +
+
+
+ ); +} diff --git a/lib/storage/history.ts b/lib/storage/history.ts index a15972c..6782ddd 100644 --- a/lib/storage/history.ts +++ b/lib/storage/history.ts @@ -43,6 +43,9 @@ export function addToHistory(item: Omit