UI enhancements, i18n, history drawer, and requested features
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faClock, faHistory, faTrashAlt, faTimes } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faClock, faHistory, faTrashAlt, faTimes, faCircleNotch } from "@fortawesome/free-solid-svg-icons";
|
||||
import {
|
||||
clearHistory,
|
||||
formatRelative,
|
||||
@@ -20,16 +20,26 @@ interface HistoryDrawerProps {
|
||||
|
||||
export function HistoryDrawer({ open, onClose, onLoad }: HistoryDrawerProps) {
|
||||
const [entries, setEntries] = useState<HistoryEntry[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { t } = useI18n();
|
||||
|
||||
useEffect(() => {
|
||||
setEntries(loadHistory());
|
||||
}, []);
|
||||
const fetchHistory = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await loadHistory();
|
||||
setEntries(data);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handler = () => setEntries(loadHistory());
|
||||
window.addEventListener(HISTORY_UPDATED_EVENT, handler);
|
||||
return () => window.removeEventListener(HISTORY_UPDATED_EVENT, handler);
|
||||
if (open) fetchHistory();
|
||||
}, [open]);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener(HISTORY_UPDATED_EVENT, fetchHistory);
|
||||
return () => window.removeEventListener(HISTORY_UPDATED_EVENT, fetchHistory);
|
||||
}, []);
|
||||
|
||||
// Close on Escape
|
||||
@@ -65,24 +75,27 @@ export function HistoryDrawer({ open, onClose, onLoad }: HistoryDrawerProps) {
|
||||
<span className="flex items-center gap-2 text-sm font-bold text-fg">
|
||||
<FontAwesomeIcon icon={faHistory} className="text-accent-primary" />
|
||||
{t.history}
|
||||
{entries.length > 0 && (
|
||||
{!loading && entries.length > 0 && (
|
||||
<span className="text-[10px] bg-accent-primary/15 text-accent-primary px-1.5 py-0.5 rounded-full font-bold">
|
||||
{entries.length}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="w-7 h-7 flex items-center justify-center rounded-lg text-fg-muted hover:text-fg hover:bg-bg-hover transition-colors"
|
||||
aria-label="Close history"
|
||||
>
|
||||
<FontAwesomeIcon icon={faTimes} />
|
||||
</button>
|
||||
<div className="flex items-center gap-2">
|
||||
{loading && <FontAwesomeIcon icon={faCircleNotch} spin className="text-fg-muted w-3 h-3" />}
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="w-7 h-7 flex items-center justify-center rounded-lg text-fg-muted hover:text-fg hover:bg-bg-hover transition-colors"
|
||||
aria-label="Close history"
|
||||
>
|
||||
<FontAwesomeIcon icon={faTimes} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Entries */}
|
||||
<div className="flex-1 overflow-y-auto scrollbar-thin p-2 space-y-1">
|
||||
{entries.length === 0 ? (
|
||||
{entries.length === 0 && !loading ? (
|
||||
<p className="px-3 py-10 text-xs text-fg-muted text-center italic">{t.noHistory}</p>
|
||||
) : (
|
||||
entries.map((e) => (
|
||||
@@ -90,7 +103,9 @@ export function HistoryDrawer({ open, onClose, onLoad }: HistoryDrawerProps) {
|
||||
key={e.id}
|
||||
entry={e}
|
||||
onLoad={() => { onLoad(e); onClose(); }}
|
||||
onRemove={() => setEntries(removeFromHistory(e.id))}
|
||||
onRemove={async () => {
|
||||
await removeFromHistory(e.id);
|
||||
}}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
@@ -101,11 +116,16 @@ export function HistoryDrawer({ open, onClose, onLoad }: HistoryDrawerProps) {
|
||||
<div className="p-2 border-t border-border shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => { clearHistory(); setEntries([]); }}
|
||||
onClick={async () => {
|
||||
if (window.confirm(t.clearHistoryConfirm)) {
|
||||
await clearHistory();
|
||||
setEntries([]);
|
||||
}
|
||||
}}
|
||||
className="w-full inline-flex items-center justify-center gap-2 text-xs font-semibold text-fg-muted hover:text-rose-400 hover:bg-rose-400/10 transition-colors py-2 rounded-lg"
|
||||
>
|
||||
<FontAwesomeIcon icon={faTrashAlt} />
|
||||
{t.history === 'History' ? 'Clear history' : 'Verlauf löschen'}
|
||||
{t.clearHistory}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user