Import source: src/context/HistoryContext
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
@@ -0,0 +1,65 @@
|
|||||||
|
import { createContext, useContext, useState, useCallback, type ReactNode } from 'react';
|
||||||
|
import type { QRState } from '../types';
|
||||||
|
|
||||||
|
export interface HistoryEntry {
|
||||||
|
id: number;
|
||||||
|
type: QRState['selectedType'];
|
||||||
|
label: string;
|
||||||
|
snapshot: Pick<QRState, 'qrColor' | 'bgColor' | 'pattern' | 'theme' | 'gradientEnabled' | 'gradientColor2' | 'cornerSquareStyle' | 'cornerDotStyle' | 'logoDataUrl'>;
|
||||||
|
formData: QRState['formData'];
|
||||||
|
savedAt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HistoryCtx {
|
||||||
|
history: HistoryEntry[];
|
||||||
|
push: (state: QRState, label: string) => void;
|
||||||
|
remove: (id: number) => void;
|
||||||
|
clear: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const KEY = 'cqrc_history';
|
||||||
|
const MAX = 20;
|
||||||
|
|
||||||
|
function load(): HistoryEntry[] {
|
||||||
|
try { return JSON.parse(localStorage.getItem(KEY) ?? '[]'); } catch { return []; }
|
||||||
|
}
|
||||||
|
function save(h: HistoryEntry[]) {
|
||||||
|
try { localStorage.setItem(KEY, JSON.stringify(h)); } catch { /* storage full */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
const HistoryContext = createContext<HistoryCtx>({ history: [], push: () => {}, remove: () => {}, clear: () => {} });
|
||||||
|
|
||||||
|
export function HistoryProvider({ children }: { children: ReactNode }) {
|
||||||
|
const [history, setHistory] = useState<HistoryEntry[]>(load);
|
||||||
|
|
||||||
|
const push = useCallback((state: QRState, label: string) => {
|
||||||
|
setHistory(prev => {
|
||||||
|
const entry: HistoryEntry = {
|
||||||
|
id: Date.now(),
|
||||||
|
type: state.selectedType,
|
||||||
|
label: label.slice(0, 60),
|
||||||
|
snapshot: {
|
||||||
|
qrColor: state.qrColor, bgColor: state.bgColor, pattern: state.pattern,
|
||||||
|
theme: state.theme, gradientEnabled: state.gradientEnabled,
|
||||||
|
gradientColor2: state.gradientColor2, cornerSquareStyle: state.cornerSquareStyle,
|
||||||
|
cornerDotStyle: state.cornerDotStyle, logoDataUrl: state.logoDataUrl,
|
||||||
|
},
|
||||||
|
formData: state.formData,
|
||||||
|
savedAt: Date.now(),
|
||||||
|
};
|
||||||
|
const next = [entry, ...prev.filter(e => e.label !== label)].slice(0, MAX);
|
||||||
|
save(next);
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const remove = useCallback((id: number) => {
|
||||||
|
setHistory(prev => { const next = prev.filter(e => e.id !== id); save(next); return next; });
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const clear = useCallback(() => { setHistory([]); localStorage.removeItem(KEY); }, []);
|
||||||
|
|
||||||
|
return <HistoryContext.Provider value={{ history, push, remove, clear }}>{children}</HistoryContext.Provider>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useHistory = () => useContext(HistoryContext);
|
||||||
Reference in New Issue
Block a user