Add movie runtime, bulk OMDb refresh, and first-time setup
- Add runtime field to Movie model and display formatted duration (e.g., 2h 22min) on movie cards - Add bulk "Refresh OMDb" button in admin panel for selected movies - Add runtime field to movie edit modal in admin panel - Implement first-time setup flow: show admin creation form on login page when no admin exists - Block registration page until initial setup is complete Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
087f4f4023
commit
6186f3a051
+44
-13
@@ -22,24 +22,55 @@ async function applyActiveOscarYearToTitle() {
|
||||
// Fire and forget.
|
||||
applyActiveOscarYearToTitle();
|
||||
|
||||
// Check if the user is already logged in by looking for auth_token in localStorage
|
||||
const existingToken = localStorage.getItem('auth_token');
|
||||
if (existingToken) {
|
||||
// Check setup status
|
||||
async function checkSetupStatus() {
|
||||
try {
|
||||
const decoded = decodeJwt(existingToken);
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
if (decoded.exp && decoded.exp < currentTime) {
|
||||
localStorage.removeItem('auth_token');
|
||||
} else if (decoded.mustChangePassword) {
|
||||
window.location.href = '/change-password.html';
|
||||
} else {
|
||||
window.location.href = '/movies.html';
|
||||
}
|
||||
const res = await fetch('/api/users/setup/status', { method: 'GET', cache: 'no-store' });
|
||||
if (!res.ok) return { needsSetup: false };
|
||||
return await res.json();
|
||||
} catch (_) {
|
||||
localStorage.removeItem('auth_token');
|
||||
return { needsSetup: false };
|
||||
}
|
||||
}
|
||||
|
||||
async function initPage() {
|
||||
const setupNeededCard = document.getElementById('setup-needed-card');
|
||||
const registerCard = document.getElementById('register-card');
|
||||
|
||||
// Check if setup is needed
|
||||
const status = await checkSetupStatus();
|
||||
|
||||
if (status.needsSetup) {
|
||||
// Show setup-needed banner, hide registration form
|
||||
if (setupNeededCard) setupNeededCard.classList.remove('d-none');
|
||||
if (registerCard) registerCard.classList.add('d-none');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the user is already logged in by looking for auth_token in localStorage
|
||||
const existingToken = localStorage.getItem('auth_token');
|
||||
if (existingToken) {
|
||||
try {
|
||||
const decoded = decodeJwt(existingToken);
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
if (decoded.exp && decoded.exp < currentTime) {
|
||||
localStorage.removeItem('auth_token');
|
||||
} else if (decoded.mustChangePassword) {
|
||||
window.location.href = '/change-password.html';
|
||||
return;
|
||||
} else {
|
||||
window.location.href = '/movies.html';
|
||||
return;
|
||||
}
|
||||
} catch (_) {
|
||||
localStorage.removeItem('auth_token');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the page
|
||||
initPage();
|
||||
|
||||
// Handle registration form submission
|
||||
document.getElementById('register-form').addEventListener('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
Reference in New Issue
Block a user