From ccf0e0a951404753940ac05c4ae6b069478a1748 Mon Sep 17 00:00:00 2001 From: lashman Date: Thu, 8 Jan 2026 00:42:52 +0200 Subject: [PATCH] play history --- frontend/src/components/PuzzleHistory.tsx | 81 +++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 frontend/src/components/PuzzleHistory.tsx diff --git a/frontend/src/components/PuzzleHistory.tsx b/frontend/src/components/PuzzleHistory.tsx new file mode 100644 index 0000000..34d0f05 --- /dev/null +++ b/frontend/src/components/PuzzleHistory.tsx @@ -0,0 +1,81 @@ +import { useState, useEffect } from 'react' +import { useTranslation } from 'react-i18next' +import { motion } from 'motion/react' +import { IconX } from '@tabler/icons-react' +import { fetchHistory, type HistoryEntry } from '../api' +import { useStore } from '../store' +import { useFocusTrap } from '../hooks/useFocusTrap' + +function formatTime(secs: number): string { + const m = Math.floor(secs / 60) + const s = secs % 60 + return `${m}:${s.toString().padStart(2, '0')}` +} + +export default function PuzzleHistory({ onClose }: { onClose: () => void }) { + const { t } = useTranslation() + const trapRef = useFocusTrap(true) + const [items, setItems] = useState([]) + const [loading, setLoading] = useState(true) + const loadByShortId = useStore(s => s.loadByShortId) + + useEffect(() => { + fetchHistory().then(setItems).finally(() => setLoading(false)) + }, []) + + return ( + + e.stopPropagation()} + role="dialog" aria-modal="true" aria-label={t('history.title')} + initial={{ opacity: 0, scale: 0.95, y: 12 }} + animate={{ opacity: 1, scale: 1, y: 0 }} + exit={{ opacity: 0, scale: 0.95, y: 12 }} + transition={{ duration: 0.2, ease: [0.25, 0.1, 0.25, 1] }}> +
+

{t('history.title')}

+ +
+
+ {loading &&

{t('common.loading')}

} + {!loading && items.length === 0 && ( +

{t('history.empty')}

+ )} + {items.map((item, i) => ( +
+
+ + {item.preset ? item.preset.charAt(0).toUpperCase() + item.preset.slice(1) : 'Custom'} + + + {item.date} + +
+
+ {formatTime(item.time)} + + {item.hints} {item.hints === 1 ? t('history.hint') : t('history.hints')} + + {item.short_id && ( + + )} +
+
+ ))} +
+
+
+ ) +}