feat: refine session workflow with global state, quick tasting, and statistics

This commit is contained in:
2025-12-18 17:19:38 +01:00
parent 7f600698e4
commit ca1621e765
14 changed files with 399 additions and 116 deletions

View File

@@ -0,0 +1,67 @@
'use client';
import React, { createContext, useContext, useState, useEffect } from 'react';
import { validateSession } from '@/services/validate-session';
interface SessionData {
id: string;
name: string;
}
interface SessionContextType {
activeSession: SessionData | null;
setActiveSession: (session: SessionData | null) => void;
isLoading: boolean;
}
const SessionContext = createContext<SessionContextType | undefined>(undefined);
export const SessionProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [activeSession, setActiveSessionState] = useState<SessionData | null>(null);
const [isLoading, setIsLoading] = useState(true);
const setActiveSession = (session: SessionData | null) => {
setActiveSessionState(session);
if (session) {
localStorage.setItem('active_tasting_session', JSON.stringify(session));
} else {
localStorage.removeItem('active_tasting_session');
}
};
useEffect(() => {
const loadSession = async () => {
const stored = localStorage.getItem('active_tasting_session');
if (stored) {
try {
const session = JSON.parse(stored) as SessionData;
// Validate on load
const isValid = await validateSession(session.id);
if (isValid) {
setActiveSessionState(session);
} else {
localStorage.removeItem('active_tasting_session');
}
} catch (e) {
localStorage.removeItem('active_tasting_session');
}
}
setIsLoading(false);
};
loadSession();
}, []);
return (
<SessionContext.Provider value={{ activeSession, setActiveSession, isLoading }}>
{children}
</SessionContext.Provider>
);
};
export const useSession = () => {
const context = useContext(SessionContext);
if (context === undefined) {
throw new Error('useSession must be used within a SessionProvider');
}
return context;
};