import React, { useState, useEffect, useCallback } from 'react'; import { useParams, useNavigate, Link } from 'react-router-dom'; import Markdown from 'react-markdown'; import { useAuth } from '../context/AuthContext'; import { useToast } from '../components/Toast'; import api from '../api/axios'; import { formatLocalDateTime, formatLocalTime } from '../utils/dateUtils'; import PopularityBadge from '../components/PopularityBadge'; function SessionDetail() { const { id } = useParams(); const navigate = useNavigate(); const { isAuthenticated } = useAuth(); const { error: showError, success } = useToast(); const [session, setSession] = useState(null); const [games, setGames] = useState([]); const [loading, setLoading] = useState(true); const [editing, setEditing] = useState(false); const [editedNotes, setEditedNotes] = useState(''); const [saving, setSaving] = useState(false); const [showDeleteNotesConfirm, setShowDeleteNotesConfirm] = useState(false); const [showDeleteSessionConfirm, setShowDeleteSessionConfirm] = useState(false); const [showChatImport, setShowChatImport] = useState(false); const [closingSession, setClosingSession] = useState(false); const loadSession = useCallback(async () => { try { const res = await api.get(`/sessions/${id}`); setSession(res.data); } catch (err) { if (err.response?.status === 404) { navigate('/history', { replace: true }); } console.error('Failed to load session', err); } }, [id, navigate]); const loadGames = useCallback(async () => { try { const res = await api.get(`/sessions/${id}/games`); setGames([...res.data].reverse()); } catch (err) { console.error('Failed to load session games', err); } }, [id]); useEffect(() => { Promise.all([loadSession(), loadGames()]).finally(() => setLoading(false)); }, [loadSession, loadGames]); useEffect(() => { if (!session || session.is_active !== 1) return; const interval = setInterval(() => { loadSession(); loadGames(); }, 3000); return () => clearInterval(interval); }, [session, loadSession, loadGames]); const handleSaveNotes = async () => { setSaving(true); try { await api.put(`/sessions/${id}/notes`, { notes: editedNotes }); await loadSession(); setEditing(false); success('Notes saved'); } catch (err) { showError('Failed to save notes'); } finally { setSaving(false); } }; const handleDeleteNotes = async () => { try { await api.delete(`/sessions/${id}/notes`); await loadSession(); setEditing(false); setShowDeleteNotesConfirm(false); success('Notes deleted'); } catch (err) { showError('Failed to delete notes'); } }; const handleDeleteSession = async () => { try { await api.delete(`/sessions/${id}`); success('Session deleted'); navigate('/history', { replace: true }); } catch (err) { showError('Failed to delete session: ' + (err.response?.data?.error || err.message)); } }; const handleCloseSession = async (sessionId, notes) => { try { await api.post(`/sessions/${sessionId}/close`, { notes }); await loadSession(); await loadGames(); setClosingSession(false); success('Session ended successfully'); } catch (err) { showError('Failed to close session'); } }; const handleExport = async (format) => { try { const response = await api.get(`/sessions/${id}/export?format=${format}`, { responseType: 'blob' }); const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', `session-${id}.${format === 'json' ? 'json' : 'txt'}`); document.body.appendChild(link); link.click(); link.parentNode.removeChild(link); window.URL.revokeObjectURL(url); success(`Session exported as ${format.toUpperCase()}`); } catch (err) { showError('Failed to export session'); } }; const startEditing = () => { setEditedNotes(session.notes || ''); setEditing(true); }; if (loading) { return (
{formatLocalDateTime(session.created_at)} {' • '} {session.games_played} game{session.games_played !== 1 ? 's' : ''} played
No games played in this session
) : ( <>Are you sure you want to delete Session #{session.id}? This will permanently delete all games and chat logs associated with this session. This action cannot be undone.
{session.notes_preview}
Log in to view full notes
> ) : (No notes for this session
)}No notes for this session
)}No Popularity Data
You haven't imported chat reactions yet. Import now to track which games your players loved!
Upload a JSON file or paste JSON array with format: [{"username": "...", "message": "...", "timestamp": "..."}]
The system will detect "thisgame++" and "thisgame--" patterns and update game popularity.
Import Successful!
Imported {result.messagesImported} messages, processed {result.votesProcessed} votes