import React, { useState, useEffect } from 'react';
import { useAuth } from '../context/AuthContext';
import api from '../api/axios';
function History() {
const { isAuthenticated } = useAuth();
const [sessions, setSessions] = useState([]);
const [selectedSession, setSelectedSession] = useState(null);
const [sessionGames, setSessionGames] = useState([]);
const [loading, setLoading] = useState(true);
const [showChatImport, setShowChatImport] = useState(false);
const [closingSession, setClosingSession] = useState(null);
useEffect(() => {
loadSessions();
}, []);
const loadSessions = async () => {
try {
const response = await api.get('/sessions');
setSessions(response.data);
} catch (err) {
console.error('Failed to load sessions', err);
} finally {
setLoading(false);
}
};
const loadSessionGames = async (sessionId) => {
try {
const response = await api.get(`/sessions/${sessionId}/games`);
setSessionGames(response.data);
setSelectedSession(sessionId);
} catch (err) {
console.error('Failed to load session games', err);
}
};
const handleCloseSession = async (sessionId, notes) => {
try {
await api.post(`/sessions/${sessionId}/close`, { notes });
await loadSessions();
setClosingSession(null);
if (selectedSession === sessionId) {
setSelectedSession(null);
setSessionGames([]);
}
} catch (err) {
alert('Failed to close session');
}
};
if (loading) {
return (
);
}
return (
Session History
{/* Sessions List */}
Sessions
{sessions.length === 0 ? (
No sessions found
) : (
{sessions.map(session => (
loadSessionGames(session.id)}
className={`p-4 border rounded-lg cursor-pointer transition ${
selectedSession === session.id
? 'border-indigo-500 bg-indigo-50'
: 'border-gray-300 hover:border-indigo-300'
}`}
>
Session #{session.id}
{session.is_active === 1 && (
Active
)}
{new Date(session.created_at).toLocaleDateString()}
{session.games_played} game{session.games_played !== 1 ? 's' : ''} played
{isAuthenticated && session.is_active === 1 && (
{
e.stopPropagation();
setClosingSession(session.id);
}}
className="mt-2 w-full bg-yellow-600 text-white px-3 py-1 rounded text-sm hover:bg-yellow-700 transition"
>
Close Session
)}
))}
)}
{/* Session Details */}
{selectedSession ? (
Session #{selectedSession}
{sessions.find(s => s.id === selectedSession)?.created_at &&
new Date(sessions.find(s => s.id === selectedSession).created_at).toLocaleString()}
{isAuthenticated && sessions.find(s => s.id === selectedSession)?.is_active === 1 && (
setShowChatImport(true)}
className="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition"
>
Import Chat Log
)}
{showChatImport && (
setShowChatImport(false)}
onImportComplete={() => {
loadSessionGames(selectedSession);
setShowChatImport(false);
}}
/>
)}
{sessionGames.length === 0 ? (
No games played in this session
) : (
Games Played ({sessionGames.length})
{sessionGames.map((game, index) => (
{index + 1}. {game.title}
{game.pack_name}
{new Date(game.played_at).toLocaleTimeString()}
{game.manually_added === 1 && (
Manual
)}
Players: {game.min_players}-{game.max_players}
Type: {game.game_type || 'N/A'}
Popularity: {' '}
= 0 ? 'text-green-600' : 'text-red-600'}>
{game.popularity_score > 0 ? '+' : ''}{game.popularity_score}
))}
)}
) : (
Select a session to view details
)}
{/* Close Session Modal */}
{closingSession && (
setClosingSession(null)}
onConfirm={handleCloseSession}
/>
)}
);
}
function CloseSessionModal({ sessionId, onClose, onConfirm }) {
const [notes, setNotes] = useState('');
return (
Close Session #{sessionId}
Session Notes (optional)
onConfirm(sessionId, notes)}
className="flex-1 bg-indigo-600 text-white py-3 rounded-lg hover:bg-indigo-700 transition"
>
Close Session
Cancel
);
}
function ChatImportPanel({ sessionId, onClose, onImportComplete }) {
const [chatData, setChatData] = useState('');
const [importing, setImporting] = useState(false);
const [result, setResult] = useState(null);
const handleImport = async () => {
if (!chatData.trim()) {
alert('Please enter chat data');
return;
}
setImporting(true);
setResult(null);
try {
const parsedData = JSON.parse(chatData);
const response = await api.post(`/sessions/${sessionId}/chat-import`, {
chatData: parsedData
});
setResult(response.data);
setTimeout(() => {
onImportComplete();
}, 2000);
} catch (err) {
alert('Import failed: ' + (err.response?.data?.error || err.message));
} finally {
setImporting(false);
}
};
return (
Import Chat Log
Paste JSON array with format: [{"{"}"username": "...", "message": "...", "timestamp": "..."{"}"}]
The system will detect "thisgame++" and "thisgame--" patterns and update game popularity.
Chat JSON Data
{result && (
Import Successful!
Imported {result.messagesImported} messages, processed {result.votesProcessed} votes
{result.votesByGame && Object.keys(result.votesByGame).length > 0 && (
Votes by game:
{Object.values(result.votesByGame).map((vote, i) => (
{vote.title}: +{vote.upvotes} / -{vote.downvotes}
))}
)}
)}
{importing ? 'Importing...' : 'Import'}
Close
);
}
export default History;