diff --git a/src/components/CenterPanel/QRHistory.tsx b/src/components/CenterPanel/QRHistory.tsx new file mode 100644 index 0000000..593eda1 --- /dev/null +++ b/src/components/CenterPanel/QRHistory.tsx @@ -0,0 +1,115 @@ +import { useState } from 'react'; +import { useHistory } from '../../context/HistoryContext'; +import { useQR } from '../../context/QRContext'; +import { QR_TYPES } from '../../config/qrTypes'; +import { useTheme } from '../../context/ThemeContext'; + +function timeAgo(ms: number) { + const s = Math.floor((Date.now() - ms) / 1000); + if (s < 60) return 'just now'; + if (s < 3600) return `${Math.floor(s / 60)}m ago`; + if (s < 86400) return `${Math.floor(s / 3600)}h ago`; + return `${Math.floor(s / 86400)}d ago`; +} + +export function QRHistory() { + const { history, remove, clear } = useHistory(); + const { dispatch } = useQR(); + const { isDark } = useTheme(); + const [open, setOpen] = useState(false); + + if (!history.length) return null; + + const restore = (e: (typeof history)[0]) => { + dispatch({ type: 'SET_TYPE', payload: e.type }); + dispatch({ type: 'SET_QR_COLOR', payload: e.snapshot.qrColor }); + dispatch({ type: 'SET_BG_COLOR', payload: e.snapshot.bgColor }); + dispatch({ type: 'SET_PATTERN', payload: e.snapshot.pattern }); + dispatch({ type: 'SET_THEME', payload: e.snapshot.theme }); + dispatch({ type: 'SET_GRADIENT', payload: e.snapshot.gradientEnabled }); + dispatch({ type: 'SET_GRADIENT_COLOR2', payload: e.snapshot.gradientColor2 }); + dispatch({ type: 'SET_CORNER_SQUARE', payload: e.snapshot.cornerSquareStyle }); + dispatch({ type: 'SET_CORNER_DOT', payload: e.snapshot.cornerDotStyle }); + dispatch({ type: 'SET_LOGO', payload: e.snapshot.logoDataUrl }); + // restore form data for that type + const fd = e.formData[e.type] as unknown as Record; + Object.entries(fd).forEach(([field, value]) => + dispatch({ type: 'SET_FORM_FIELD', qrType: e.type, field, value }) + ); + }; + + return ( +
+ {/* Header */} + + + {/* List */} + {open && ( +
+ {history.map(entry => { + const typeConfig = QR_TYPES.find(t => t.key === entry.type); + const thumb = isDark ? typeConfig?.thumbDark : typeConfig?.thumb; + return ( +
(e.currentTarget.style.background = 'var(--hover-bg)')} + onMouseLeave={e => (e.currentTarget.style.background = 'transparent')} + > + {thumb && {entry.type}} +
+

{entry.label}

+

{entry.type.toUpperCase()} ยท {timeAgo(entry.savedAt)}

+
+
+ + +
+
+ ); + })} +
+ )} +
+ ); +}