Update Oscars year to 2026 and add admin page
Co-authored-by: mathieumoran1 <[email protected]>
This commit is contained in:
co-authored by
mathieumoran1
parent
6108c8a40f
commit
f07547cc59
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Pool Oscars 2025 - Checklist</title>
|
||||
<title>Pool Oscars 2026 - Checklist</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="./css/app.css" rel="stylesheet">
|
||||
<style>
|
||||
@@ -65,6 +65,7 @@
|
||||
<a href="movies.html" class="nav-link btn btn-outline-light me-2">Films</a>
|
||||
<a href="checklist.html" class="nav-link btn btn-outline-light me-2">Checklist</a>
|
||||
<a href="user-stat.html" class="nav-link btn btn-outline-light me-2">Statistiques</a>
|
||||
<a id="admin-control-link" href="control.html" class="nav-link btn btn-warning me-2 d-none">Admin</a>
|
||||
</div>
|
||||
<!-- Move user info inside collapsible navbar and align it properly -->
|
||||
<div class="d-flex ms-auto mt-2 mt-lg-0 align-items-center">
|
||||
@@ -78,7 +79,7 @@
|
||||
<div class="container mt-5">
|
||||
<h2>Checklist</h2>
|
||||
<div id="watched-ratio" class="ratio"></div>
|
||||
<h3 class="fs-6" style="margin-bottom: -1px;">Temps avant les Oscars (2 mars 2025) - <span id="time-left"></span></h3>
|
||||
<h3 class="fs-6" style="margin-bottom: -1px;">Temps avant les Oscars (15 mars 2026) - <span id="time-left"></span></h3>
|
||||
<h3 class="fs-6"><span id="movies-per-day"></span></h3>
|
||||
<div class="progress my-3">
|
||||
<div id="progress-bar" class="progress-bar" role="progressbar" style="width: 0%; background-color: red;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Pool Oscars 2026 - Admin</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="./css/app.css" rel="stylesheet">
|
||||
<style>
|
||||
.navbar-custom {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
.navbar-custom .navbar-brand,
|
||||
.navbar-custom .nav-link {
|
||||
color: white;
|
||||
}
|
||||
.navbar-custom .nav-link:hover {
|
||||
color: #ddd;
|
||||
}
|
||||
.navbar-toggler {
|
||||
border-color: white;
|
||||
}
|
||||
.navbar-toggler-icon {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Cpath stroke='white' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E");
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-light">
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-custom">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" style="margin-left: -7px;">
|
||||
<img src="img/logo_w.png" style="max-width: 220px; height: 70px; object-fit: contain;">
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<div class="navbar-nav">
|
||||
<a href="movies.html" class="nav-link btn btn-outline-light me-2">Films</a>
|
||||
<a href="checklist.html" class="nav-link btn btn-outline-light me-2">Checklist</a>
|
||||
<a href="user-stat.html" class="nav-link btn btn-outline-light me-2">Statistiques</a>
|
||||
<a href="control.html" class="nav-link btn btn-warning me-2">Admin</a>
|
||||
</div>
|
||||
<div class="d-flex ms-auto mt-2 mt-lg-0 align-items-center">
|
||||
<span id="user-name" class="navbar-text me-3"></span>
|
||||
<button id="log-off" class="btn btn-danger">Déconnexion</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-5" style="max-width: 720px;">
|
||||
<h2>Admin - Ajouter un film</h2>
|
||||
<p class="text-muted mb-4">
|
||||
Ajoute un film via l’API (<code>/api/movies/add</code>). Le serveur récupère automatiquement le titre/plot/affiche depuis OMDb avec l’<code>imdb_id</code>.
|
||||
</p>
|
||||
|
||||
<div id="response" class="alert d-none" role="alert"></div>
|
||||
|
||||
<form id="add-movie-form" class="card p-3">
|
||||
<div class="mb-3">
|
||||
<label for="imdb_id" class="form-label">IMDB ID (ex: tt1234567)</label>
|
||||
<input type="text" class="form-control" id="imdb_id" placeholder="tt..." required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="category" class="form-label">Catégorie</label>
|
||||
<input type="text" class="form-control" id="category" placeholder="Best Picture, etc." required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="vod_link" class="form-label">Lien VOD</label>
|
||||
<input type="url" class="form-control" id="vod_link" placeholder="https://..." required>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary">Ajouter</button>
|
||||
<button type="button" id="reset-form" class="btn btn-outline-secondary">Reset</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="./js/app_control.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Pool Oscars 2025</title>
|
||||
<title>Pool Oscars 2026</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="./css/app.css" rel="stylesheet">
|
||||
<style>
|
||||
@@ -46,7 +46,7 @@
|
||||
<!-- Footer Section -->
|
||||
<footer>
|
||||
|
||||
<p id="footer-copy"><a id="copy" href="https://github.com/quoije/oscars-pool">quoije</a> - deux mille vingt-cinq</p>
|
||||
<p id="footer-copy"><a id="copy" href="https://github.com/quoije/oscars-pool">quoije</a> - deux mille vingt-six</p>
|
||||
<p id="footer-text"></p>
|
||||
</footer>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
window.onload = async function () {
|
||||
const token = localStorage.getItem('auth_token');
|
||||
|
||||
const targetDate = new Date('March 2, 2025');
|
||||
const targetDate = new Date('March 15, 2026');
|
||||
const currentDate = new Date();
|
||||
const timeDifference = targetDate - currentDate;
|
||||
const daysLeft = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
|
||||
@@ -12,6 +12,10 @@ window.onload = async function () {
|
||||
const decoded = JSON.parse(atob(token.split('.')[1]));
|
||||
const userName = decoded.name;
|
||||
document.getElementById('user-name').textContent = userName;
|
||||
if (decoded.admin) {
|
||||
const adminLink = document.getElementById('admin-control-link');
|
||||
if (adminLink) adminLink.classList.remove('d-none');
|
||||
}
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
if (decoded.exp && decoded.exp < currentTime) {
|
||||
localStorage.removeItem('auth_token');
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
window.onload = async function () {
|
||||
const token = localStorage.getItem('auth_token');
|
||||
if (!token) {
|
||||
window.location.href = '/';
|
||||
return;
|
||||
}
|
||||
|
||||
let decoded;
|
||||
try {
|
||||
decoded = JSON.parse(atob(token.split('.')[1]));
|
||||
} catch (e) {
|
||||
localStorage.removeItem('auth_token');
|
||||
window.location.href = '/';
|
||||
return;
|
||||
}
|
||||
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
if (decoded.exp && decoded.exp < currentTime) {
|
||||
localStorage.removeItem('auth_token');
|
||||
window.location.href = '/';
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById('user-name').textContent = decoded.name || '';
|
||||
|
||||
// Admin-only page: if token doesn't contain admin flag, bounce.
|
||||
if (!decoded.admin) {
|
||||
window.location.href = '/movies.html';
|
||||
return;
|
||||
}
|
||||
|
||||
const responseEl = document.getElementById('response');
|
||||
const form = document.getElementById('add-movie-form');
|
||||
|
||||
function showResponse(kind, message) {
|
||||
responseEl.classList.remove('d-none', 'alert-success', 'alert-danger', 'alert-warning');
|
||||
responseEl.classList.add(kind === 'success' ? 'alert-success' : kind === 'warning' ? 'alert-warning' : 'alert-danger');
|
||||
responseEl.textContent = message;
|
||||
}
|
||||
|
||||
document.getElementById('reset-form').addEventListener('click', function () {
|
||||
form.reset();
|
||||
responseEl.classList.add('d-none');
|
||||
});
|
||||
|
||||
document.getElementById('log-off').addEventListener('click', function () {
|
||||
localStorage.removeItem('auth_token');
|
||||
window.location.href = '/';
|
||||
});
|
||||
|
||||
form.addEventListener('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const imdb_id = document.getElementById('imdb_id').value.trim();
|
||||
const category = document.getElementById('category').value.trim();
|
||||
const vod_link = document.getElementById('vod_link').value.trim();
|
||||
|
||||
if (!/^tt\d{5,}$/.test(imdb_id)) {
|
||||
showResponse('warning', 'IMDB ID invalide. Exemple attendu: tt1234567');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/movies/add', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`
|
||||
},
|
||||
body: JSON.stringify({ imdb_id, category, vod_link })
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
showResponse('success', 'Film ajouté avec succès.');
|
||||
form.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
let errMessage = `Erreur (${res.status})`;
|
||||
try {
|
||||
const data = await res.json();
|
||||
errMessage = data.message || data.error || errMessage;
|
||||
} catch (_) {
|
||||
// ignore JSON parse errors
|
||||
}
|
||||
showResponse('danger', errMessage);
|
||||
} catch (err) {
|
||||
showResponse('danger', err.message || 'Erreur réseau');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
window.onload = async function () {
|
||||
const targetDate = new Date('March 2, 2025');
|
||||
const targetDate = new Date('March 15, 2026');
|
||||
const currentDate = new Date();
|
||||
const timeDifference = targetDate - currentDate;
|
||||
const daysLeft = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
|
||||
@@ -11,6 +11,10 @@ window.onload = async function () {
|
||||
const decoded = JSON.parse(atob(token.split('.')[1]));
|
||||
const userName = decoded.name;
|
||||
document.getElementById('user-name').textContent = userName;
|
||||
if (decoded.admin) {
|
||||
const adminLink = document.getElementById('admin-control-link');
|
||||
if (adminLink) adminLink.classList.remove('d-none');
|
||||
}
|
||||
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
if (decoded.exp && decoded.exp < currentTime) {
|
||||
|
||||
@@ -6,6 +6,10 @@ window.onload = async function () {
|
||||
const decoded = JSON.parse(atob(token.split('.')[1])); // Manually decoding JWT
|
||||
const userName = decoded.name;
|
||||
document.getElementById('user-name').textContent = userName;
|
||||
if (decoded.admin) {
|
||||
const adminLink = document.getElementById('admin-control-link');
|
||||
if (adminLink) adminLink.classList.remove('d-none');
|
||||
}
|
||||
|
||||
// Verify JWT expiration
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
|
||||
+4
-3
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Pool Oscars 2025 - Films</title>
|
||||
<title>Pool Oscars 2026 - Films</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="./css/app.css" rel="stylesheet">
|
||||
<style>
|
||||
@@ -80,6 +80,7 @@
|
||||
<a href="movies.html" class="nav-link btn btn-outline-light me-2">Films</a>
|
||||
<a href="checklist.html" class="nav-link btn btn-outline-light me-2">Checklist</a>
|
||||
<a href="user-stat.html" class="nav-link btn btn-outline-light me-2">Statistiques</a>
|
||||
<a id="admin-control-link" href="control.html" class="nav-link btn btn-warning me-2 d-none">Admin</a>
|
||||
</div>
|
||||
<!-- Move user info inside collapsible navbar and align it properly -->
|
||||
<div class="d-flex ms-auto mt-2 mt-lg-0 align-items-center">
|
||||
@@ -97,7 +98,7 @@
|
||||
|
||||
<!-- Displaying last updated vod_links -->
|
||||
<div class="alert alert-warning fade show" role="alert">
|
||||
Dernière mise à jour des films: <strong>09-02-2025</strong>
|
||||
Dernière mise à jour des films: <strong>—</strong>
|
||||
</div>
|
||||
|
||||
<!-- Displaying the ratio of watched movies -->
|
||||
@@ -105,7 +106,7 @@
|
||||
<!-- This will display the ratio -->
|
||||
</div>
|
||||
|
||||
<h3 class="fs-6">Temps avant les Oscars (2 mars 2025) - <span id="time-left"></span></h3>
|
||||
<h3 class="fs-6">Temps avant les Oscars (15 mars 2026) - <span id="time-left"></span></h3>
|
||||
<h3 class="fs-6 mb-0">
|
||||
|
||||
</h3>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Pool Oscars 2025 - Enregistrement</title>
|
||||
<title>Pool Oscars 2026 - Enregistrement</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="./css/app.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Pool Oscars 2025 - Statistiques des utilisateurs</title>
|
||||
<title>Pool Oscars 2026 - Statistiques des utilisateurs</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
.navbar-custom {
|
||||
@@ -48,6 +48,7 @@
|
||||
<a href="movies.html" class="nav-link btn btn-outline-light me-2">Films</a>
|
||||
<a href="checklist.html" class="nav-link btn btn-outline-light me-2">Checklist</a>
|
||||
<a href="user-stat.html" class="nav-link btn btn-outline-light me-2">Statistiques</a>
|
||||
<a id="admin-control-link" href="control.html" class="nav-link btn btn-warning me-2 d-none">Admin</a>
|
||||
</div>
|
||||
<!-- Move user info inside collapsible navbar and align it properly -->
|
||||
<div class="d-flex ms-auto mt-2 mt-lg-0 align-items-center">
|
||||
|
||||
Reference in New Issue
Block a user