// Movie Night — Frontend Logic const API = ''; let currentUser = null; let selectedUserIds = []; // --- Auth --- async function checkAuth() { try { const res = await fetch(`${API}/api/auth/me`); if (res.ok) { currentUser = await res.json(); showMainScreen(); } else { showLoginScreen(); } } catch { showLoginScreen(); } } async function login(username, password) { const res = await fetch(`${API}/api/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); if (!res.ok) { const err = await res.json().catch(() => ({ detail: 'Login failed' })); throw new Error(err.detail || 'Login failed'); } currentUser = await res.json(); showMainScreen(); } async function logout() { await fetch(`${API}/api/auth/logout`, { method: 'POST' }); currentUser = null; showLoginScreen(); } // --- Screens --- function showLoginScreen() { document.getElementById('login-screen').classList.remove('hidden'); document.getElementById('main-screen').classList.add('hidden'); } function showMainScreen() { document.getElementById('login-screen').classList.add('hidden'); document.getElementById('main-screen').classList.remove('hidden'); document.getElementById('user-name').textContent = currentUser.name; selectedUserIds = [currentUser.id]; loadUsers(); loadStats(); } // --- Users --- async function loadUsers() { try { const res = await fetch(`${API}/api/users`); if (!res.ok) return; const users = await res.json(); const container = document.getElementById('user-pills'); container.innerHTML = ''; users.forEach(user => { const pill = document.createElement('button'); pill.className = `user-pill border rounded-full px-4 py-1.5 text-sm ${selectedUserIds.includes(user.id) ? 'active' : ''}`; pill.textContent = user.name; pill.onclick = () => toggleUser(user.id, pill); container.appendChild(pill); }); } catch { /* ignore */ } } function toggleUser(userId, pill) { if (selectedUserIds.includes(userId)) { if (selectedUserIds.length > 1) { selectedUserIds = selectedUserIds.filter(id => id !== userId); pill.classList.remove('active'); } } else { selectedUserIds.push(userId); pill.classList.add('active'); } } // --- Mood / Recommendations --- async function findMovies() { const mood = document.getElementById('mood-input').value.trim(); if (!mood) return; document.getElementById('empty-state').classList.add('hidden'); document.getElementById('results').classList.add('hidden'); document.getElementById('error-state').classList.add('hidden'); document.getElementById('loading').classList.remove('hidden'); try { const additionalIds = selectedUserIds.filter(id => id !== currentUser.id); const res = await fetch(`${API}/api/mood`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ mood, additional_user_ids: additionalIds }) }); if (!res.ok) { const err = await res.json().catch(() => ({ detail: 'Something went wrong' })); throw new Error(err.detail || 'Failed to get recommendations'); } const data = await res.json(); renderResults(data); } catch (err) { document.getElementById('loading').classList.add('hidden'); document.getElementById('error-message').textContent = err.message; document.getElementById('error-state').classList.remove('hidden'); } } function renderResults(data) { document.getElementById('loading').classList.add('hidden'); const grid = document.getElementById('results-grid'); grid.innerHTML = ''; if (!data.recommendations || data.recommendations.length === 0) { document.getElementById('empty-state').classList.remove('hidden'); return; } data.recommendations.forEach(movie => { const card = document.createElement('div'); card.className = 'movie-card bg-dark-200 rounded-xl overflow-hidden border border-gray-800'; card.innerHTML = `
${movie.reasoning}
Watch