Files
oscars-pool/public/control.html
T
Mathieu Moran 9868d2c39a Refine admin control layout and stats tabs
Tighten admin tab layout/styling and simplify control UI while aligning stats tab spacing and labels.
2026-01-27 02:45:49 -05:00

1395 lines
65 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pool Oscars - Admin</title>
<script src="./js/app_theme.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="./css/app.css" rel="stylesheet">
<link rel="preload" as="image" href="img/logo_w.png">
<script src="./js/app_header_boot.js" defer></script>
<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");
}
.admin-tabs-content {
font-size: 0.95rem;
}
.admin-tabs-content .info-line {
display: flex;
align-items: center;
gap: 0.5rem;
line-height: 1;
align-self: center;
transform: translateY(-2px);
}
.admin-tabs-content .info-line .badge {
display: inline-flex;
align-items: center;
justify-content: center;
line-height: 1;
width: 1.2em;
height: 1.2em;
padding: 0;
}
.admin-tabs-content .info-line .info-text {
display: inline-flex;
align-items: center;
line-height: 1;
}
.admin-tabs-content .btn-compact {
padding: 0.2rem 0.5rem;
font-size: 0.85rem;
line-height: 1.2;
}
.admin-tabs-content .btn-check-compact {
padding-left: 0.35rem;
padding-right: 0.35rem;
}
.admin-tabs-content .app-version-create {
font-size: 0.95rem;
}
.admin-tabs-content .app-version-create .fw-semibold {
font-size: 0.95rem;
}
.admin-tabs-content .backup-restore-panel {
font-size: 0.95rem;
}
.admin-tabs-content .backup-restore-panel .form-label,
.admin-tabs-content .backup-restore-panel .form-check-label {
font-size: 0.95rem;
}
.admin-tabs-content .backup-restore-panel .alert {
font-size: 0.9rem;
padding: 0.5rem 0.75rem;
}
.admin-tabs-content .btn-check-small {
height: 1.9rem;
}
.admin-tabs-content .oscar-date-year-select {
max-width: 220px;
width: 220px;
margin-right: 0;
}
.admin-tabs-content .manage-year-select {
max-width: 110px;
width: 110px;
}
.admin-tabs-content .oscar-date-input {
max-width: 220px;
width: 220px;
}
.admin-tabs-content .points-input-half {
max-width: 110px;
width: 110px;
}
.admin-tabs-content .oscar-date-layout {
display: flex;
align-items: flex-start;
gap: 0.75rem;
}
.admin-tabs-content .oscar-date-fields {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.admin-tabs-content .oscar-date-fields .form-text {
margin-top: 0.2rem;
}
.admin-tabs-content .oscar-date-current {
display: inline-block;
width: fit-content;
max-width: 100%;
padding: 0.4rem 0.65rem;
min-width: 220px;
}
.admin-tabs-content .btn-check-wide {
padding-left: 0.55rem;
padding-right: 0.55rem;
}
.admin-tabs-content h4,
.admin-tabs-content h5 {
font-size: 1rem;
font-weight: 600;
letter-spacing: 0.01em;
}
.admin-subtabs .nav-link {
padding: 0.3rem 0.7rem;
font-size: 0.9rem;
line-height: 1.2;
}
html[data-theme="dark"] #adminAddMovieAccordion .accordion-item {
background-color: var(--app-surface-alt);
border-color: var(--app-border);
}
html[data-theme="dark"] #adminAddMovieAccordion .accordion-button {
background-color: var(--app-surface-alt);
color: var(--app-text);
box-shadow: none;
}
html[data-theme="dark"] #adminAddMovieAccordion .accordion-button::after {
filter: invert(1);
}
html[data-theme="dark"] #adminAddMovieAccordion .accordion-button:not(.collapsed) {
background-color: var(--app-surface);
color: var(--app-text);
box-shadow: none;
}
html[data-theme="dark"] #adminAddMovieAccordion .accordion-body {
background-color: var(--app-surface);
color: var(--app-text);
}
.admin-movies-add {
margin-top: 0.5rem;
}
.admin-movies-separator {
border-top: 1px solid var(--app-border);
margin: 0.75rem 0;
}
.admin-movies-meta {
margin: 0 0 0.5rem;
}
.admin-subtabs-tight {
margin-top: 0;
}
.admin-tabs-content .table,
.admin-tabs-content .table th,
.admin-tabs-content .table td {
font-size: 0.95rem;
}
</style>
</head>
<body class="bg-light">
<nav class="navbar navbar-expand-lg navbar-custom">
<div class="container">
<a class="navbar-brand" href="movies.html">
<img src="img/logo_w.png" width="220" height="70" loading="eager" fetchpriority="high" decoding="async" style="max-width: 220px; height: 70px; object-fit: contain;">
</a>
<span class="navbar-text ms-auto me-2 d-lg-none navbar-user-name-mobile" data-user-name></span>
<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="picks.html" class="nav-link btn btn-outline-light me-2" id="nav-link-picks" style="display: none;">Mes picks</a>
<a href="control.html" class="nav-link btn btn-outline-light me-2 active">Admin</a>
</div>
<div class="d-flex ms-auto mt-2 mt-lg-0 align-items-center gap-2 navbar-user">
<span id="user-name" class="navbar-text" data-user-name></span>
<button class="theme-toggle" type="button" data-theme-toggle role="switch" aria-checked="false" aria-label="Basculer le mode sombre">
<span class="theme-toggle-icon theme-toggle-icon-sun" aria-hidden="true">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="4"></circle>
<path d="M12 2v2"></path>
<path d="M12 20v2"></path>
<path d="M4.93 4.93l1.41 1.41"></path>
<path d="M17.66 17.66l1.41 1.41"></path>
<path d="M2 12h2"></path>
<path d="M20 12h2"></path>
<path d="M4.93 19.07l1.41-1.41"></path>
<path d="M17.66 6.34l1.41-1.41"></path>
</svg>
</span>
<span class="theme-toggle-thumb" aria-hidden="true"></span>
<span class="theme-toggle-icon theme-toggle-icon-moon" aria-hidden="true">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"></path>
</svg>
</span>
</button>
<button id="log-off" class="btn btn-danger">Déconnexion</button>
</div>
</div>
</div>
</nav>
<div class="container mt-4 pb-5">
<div id="response" class="alert d-none" role="alert"></div>
<ul class="nav nav-tabs" id="adminTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="admin-settings-tab" data-bs-toggle="tab" data-bs-target="#admin-settings" type="button" role="tab" aria-controls="admin-settings" aria-selected="true">
Réglages
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="admin-movies-tab" data-bs-toggle="tab" data-bs-target="#admin-movies" type="button" role="tab" aria-controls="admin-movies" aria-selected="false">
Films
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="admin-users-tab" data-bs-toggle="tab" data-bs-target="#admin-users" type="button" role="tab" aria-controls="admin-users" aria-selected="false">
Utilisateurs
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="admin-modal-100-tab" data-bs-toggle="tab" data-bs-target="#admin-modal-100" type="button" role="tab" aria-controls="admin-modal-100" aria-selected="false">
Modal 100%
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="admin-winners-tab" data-bs-toggle="tab" data-bs-target="#admin-winners" type="button" role="tab" aria-controls="admin-winners" aria-selected="false">
Gagnants
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="admin-categories-tab" data-bs-toggle="tab" data-bs-target="#admin-categories" type="button" role="tab" aria-controls="admin-categories" aria-selected="false">
Catégories Oscars
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="admin-backup-tab" data-bs-toggle="tab" data-bs-target="#admin-backup" type="button" role="tab" aria-controls="admin-backup" aria-selected="false">
Backup / Restore
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="admin-version-tab" data-bs-toggle="tab" data-bs-target="#admin-version" type="button" role="tab" aria-controls="admin-version" aria-selected="false">
Version
</button>
</li>
</ul>
<div class="tab-content pt-3 admin-tabs-content">
<div class="tab-pane fade show active" id="admin-settings" role="tabpanel" aria-labelledby="admin-settings-tab">
<div class="card p-3">
<div class="d-flex flex-wrap align-items-end justify-content-between gap-2">
<div class="info-line small text-muted">
<span class="badge bg-light text-dark border" aria-hidden="true">i</span>
<span class="info-text">Paramètres globaux du site (année, dates, options du lecteur).</span>
</div>
</div>
<ul class="nav nav-pills admin-subtabs mt-3" id="adminSettingsSubTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="admin-settings-subtab-oscar-date" data-bs-toggle="tab" data-bs-target="#admin-settings-pane-oscar-date" type="button" role="tab" aria-controls="admin-settings-pane-oscar-date" aria-selected="true">
Date Oscars
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="admin-settings-subtab-visibility" data-bs-toggle="tab" data-bs-target="#admin-settings-pane-visibility" type="button" role="tab" aria-controls="admin-settings-pane-visibility" aria-selected="false">
Visibilité
</button>
</li>
</ul>
<div class="tab-content pt-3">
<!-- Oscar date + points -->
<div class="tab-pane fade show active" id="admin-settings-pane-oscar-date" role="tabpanel" aria-labelledby="admin-settings-subtab-oscar-date" tabindex="0">
<div class="row g-3">
<div class="col-12 col-xxl-6">
<div class="border rounded p-3 bg-light h-100">
<div class="text-muted small mb-3">
Configure la date de cérémonie pour le compte à rebours (Films &amp; Checklist). Défaut: <code>15 mars</code>.
</div>
<div class="oscar-date-layout">
<div class="oscar-date-fields">
<div>
<label for="oscar_date_year" class="form-label visually-hidden">Année</label>
<div class="input-group align-items-center">
<select class="form-select oscar-date-year-select" id="oscar_date_year"></select>
<button type="button" id="save-active-year" class="btn btn-warning btn-compact btn-check-compact btn-check-small btn-check-wide rounded-3 ms-1" aria-label="Appliquer l'année active">✓</button>
</div>
<div class="form-text">Basé sur les années présentes dans les films.</div>
</div>
<div>
<label for="oscar_date_value" class="form-label visually-hidden">Date</label>
<div class="input-group align-items-center">
<input type="date" class="form-control oscar-date-input" id="oscar_date_value">
<button type="button" id="save-oscar-date" class="btn btn-warning btn-compact btn-check-compact btn-check-small btn-check-wide rounded-3 ms-1" aria-label="Enregistrer">✓</button>
</div>
<div class="form-text">Format: YYYY-MM-DD.</div>
</div>
</div>
</div>
<div class="mt-3">
<div class="text-muted small mb-1">Dates configurées</div>
<div id="oscar-date-current" class="border rounded bg-white oscar-date-current">—</div>
</div>
</div>
</div>
<div class="col-12 col-xxl-6">
<div class="border rounded p-3 bg-light h-100">
<div class="text-muted small mb-3">
Configure les points attribués pour les films regardés et les bonnes réponses aux Oscars.
</div>
<div id="points-config-alert" class="alert d-none" role="alert"></div>
<div class="row g-3">
<div class="col-12">
<label for="points-per-movie" class="form-label">Points par film regardé</label>
<input type="number" class="form-control points-input-half" id="points-per-movie" min="0" step="1" value="1">
<div class="form-text">Points attribués pour chaque film complété.</div>
</div>
<div class="col-12">
<label for="points-per-correct-pick" class="form-label">Points par bonne réponse</label>
<input type="number" class="form-control points-input-half" id="points-per-correct-pick" min="0" step="1" value="1">
<div class="form-text">Points attribués pour chaque bonne réponse aux Oscars.</div>
</div>
</div>
<div class="mt-3">
<div class="d-flex gap-2">
<button type="button" id="points-config-reload" class="btn btn-outline-secondary btn-compact">Recharger</button>
<button type="button" id="points-config-save" class="btn btn-warning btn-compact">Enregistrer</button>
</div>
</div>
<div class="mt-3">
<div class="text-muted small mb-1">Calcul des points</div>
<div class="border rounded p-2 bg-white">
<div class="small">
<strong>Total =</strong> (Films regardés × <span id="points-per-movie-preview">1</span>) + (Bonnes réponses × <span id="points-per-correct-pick-preview">1</span>)
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Visibility settings -->
<div class="tab-pane fade" id="admin-settings-pane-visibility" role="tabpanel" aria-labelledby="admin-settings-subtab-visibility" tabindex="0">
<div class="border rounded p-3 bg-light">
<div id="visibility-config-alert" class="alert d-none mb-3" role="alert"></div>
<div class="form-check mb-4">
<input class="form-check-input" type="checkbox" id="visibility-show-picks-features">
<label class="form-check-label" for="visibility-show-picks-features">
Afficher les fonctionnalités "Picks"
</label>
<div class="form-text small text-muted">Contrôle l'affichage du bouton "Mes picks" dans la navigation et de la colonne "Bon picks" dans les statistiques.</div>
</div>
<div class="form-check mb-4">
<input class="form-check-input" type="checkbox" id="player_ui_show_status">
<label class="form-check-label" for="player_ui_show_status">
Afficher "Source" + "Progress" (admins)
</label>
<div class="form-text small text-muted">Contrôle l'affichage du bloc debug dans <code>player.html</code> (admins uniquement).</div>
</div>
<div class="d-flex gap-2">
<button type="button" id="visibility-config-save" class="btn btn-warning btn-compact">Enregistrer</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="admin-version" role="tabpanel" aria-labelledby="admin-version-tab">
<div class="card p-3">
<div class="d-flex flex-wrap align-items-end justify-content-between gap-2">
<div class="info-line small text-muted">
<span class="badge bg-light text-dark border" aria-hidden="true">i</span>
<span class="info-text">Contrôle la version affichée dans le footer (stockée en DB). Clique sur ✓ pour activer une version, puis vérifie l’aperçu.</span>
</div>
</div>
<div id="app_version_alert" class="alert d-none mt-3 mb-0" role="alert"></div>
<div class="pt-3">
<div class="row g-3">
<div class="col-12 col-xxl-7">
<div id="app_version_list" class="border rounded bg-white app-version-list">—</div>
</div>
<div class="col-12 col-xxl-5">
<div class="border rounded p-3 bg-light app-version-create">
<div class="fw-semibold mb-1">Créer une nouvelle version</div>
<div class="text-muted small mb-3">
Ajoute une entrée dans l’historique (tu peux l’activer immédiatement).
</div>
<div class="row g-3">
<div class="col-12 col-md-5">
<label for="app_version_new_version" class="form-label">Version</label>
<input id="app_version_new_version" type="text" class="form-control" placeholder="ex: 1.0.1" maxlength="80">
<div class="form-text">Ex: <code>1.2.3</code></div>
</div>
<div class="col-12 col-md-7">
<label for="app_version_new_message" class="form-label">Message (optionnel)</label>
<input id="app_version_new_message" type="text" class="form-control" placeholder="ex: Hotfix login" maxlength="500">
<div class="form-text">Court &amp; lisible (affiché dans le footer).</div>
</div>
<div class="col-12 d-flex flex-wrap justify-content-end gap-2">
<button type="button" id="app_version_create" class="btn btn-primary btn-compact">Créer</button>
<button type="button" id="app_version_create_and_activate" class="btn btn-warning btn-compact">Créer &amp; activer</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="admin-modal-100" role="tabpanel" aria-labelledby="admin-modal-100-tab">
<div class="card p-3">
<div class="d-flex flex-wrap align-items-end justify-content-between gap-2">
<div class="info-line small text-muted">
<span class="badge bg-light text-dark border" aria-hidden="true">i</span>
<span class="info-text">Contenu affiché quand un utilisateur a vu 100% des films.</span>
</div>
</div>
<div class="pt-3">
<!-- Edit + Live preview side-by-side -->
<div>
<div class="row g-3">
<div class="col-12 col-xxl-7">
<div class="border rounded p-3 bg-light h-100">
<div class="fw-semibold mb-1">Contenu</div>
<div class="text-muted small mb-3">
Modifie le contenu puis enregistre. L’aperçu est live (non sauvegardé tant que tu n’enregistres pas).
</div>
<div class="mb-3">
<label for="completion_modal_title" class="form-label">Titre</label>
<input type="text" class="form-control" id="completion_modal_title" maxlength="200" placeholder="Félicitations! ...">
</div>
<div class="mb-3">
<label for="completion_modal_body_text" class="form-label">Texte (optionnel)</label>
<textarea class="form-control" id="completion_modal_body_text" rows="4" placeholder="Texte affiché dans le modal (retours à la ligne conservés)"></textarea>
<div class="form-text">Affiché en texte brut (safe). Laisse vide si tu n’en veux pas.</div>
</div>
<div class="mb-3">
<label for="completion_modal_body_html" class="form-label">HTML (optionnel)</label>
<textarea class="form-control font-monospace" id="completion_modal_body_html" rows="6" placeholder="<p>…</p>"></textarea>
<div class="form-text">
Affiché comme HTML (le serveur retire les <code>&lt;script&gt;</code> et les handlers <code>on*</code>).
</div>
</div>
<div class="mb-3">
<label for="completion_modal_video_src" class="form-label">Video src (optionnel)</label>
<input type="text" class="form-control" id="completion_modal_video_src" maxlength="2048" placeholder="video/reward.mp4">
<div class="form-text">Chemin relatif (ex: <code>video/reward.mp4</code>) ou URL complète. Vide = pas de vidéo.</div>
</div>
<div class="d-flex flex-wrap justify-content-end gap-2">
<button type="button" id="completion_modal_save" class="btn btn-warning btn-compact">Enregistrer</button>
</div>
</div>
</div>
<div class="col-12 col-xxl-5">
<div class="border rounded p-3 bg-light">
<div class="d-flex align-items-center justify-content-between gap-2 mb-2">
<div class="fw-semibold" id="completion_modal_preview_title">—</div>
</div>
<div id="completion_modal_preview_custom" class="text-start d-none"></div>
<div id="completion_modal_preview_text" class="text-start" style="white-space: pre-wrap;"></div>
<div class="mt-3">
<video id="completion_modal_preview_video" width="55%" controls class="d-none">
<source id="completion_modal_preview_video_source" src="" type="video/mp4">
Votre navigateur ne supporte pas la vidéo.
</video>
</div>
<div class="border rounded p-3 bg-white mt-3">
<ul class="mb-0 text-muted">
<li><strong>Texte</strong>: affiché tel quel (safe), retours à la ligne conservés.</li>
<li><strong>HTML</strong>: le serveur retire les <code>&lt;script&gt;</code> et les attributs <code>on*</code>.</li>
<li><strong>Vidéo</strong>: accepte un chemin relatif (ex: <code>video/reward.mp4</code>) ou une URL complète.</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="admin-users" role="tabpanel" aria-labelledby="admin-users-tab">
<div class="row g-3">
<div class="col-12">
<div class="card p-3">
<div class="d-flex flex-wrap align-items-end justify-content-between gap-2 mb-2">
<div class="info-line small text-muted">
<span class="badge bg-light text-dark border" aria-hidden="true">i</span>
<span class="info-text"><span id="admin-users-count">—</span> utilisateur(s)</span>
</div>
<div class="d-flex gap-2">
<button type="button" id="open-add-user-modal" class="btn btn-warning btn-sm btn-compact">Ajouter un utilisateur</button>
<button type="button" id="refresh-users" class="btn btn-outline-primary btn-sm btn-compact">Rafraîchir</button>
</div>
</div>
<div class="table-responsive">
<table class="table table-sm align-middle mb-0">
<thead>
<tr>
<th>Nom</th>
<th>Email</th>
<th style="width: 1%;">Statut</th>
<th style="width: 1%;">Actions</th>
</tr>
</thead>
<tbody id="admin-users-body">
<tr><td colspan="4" class="text-muted">Charge la liste…</td></tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="admin-movies" role="tabpanel" aria-labelledby="admin-movies-tab">
<div class="card p-3">
<div class="admin-movies-add">
<div class="info-line small text-muted mb-3">
<span class="badge bg-light text-dark border" aria-hidden="true">i</span>
<span class="info-text">Ajout de films : cette section récupère automatiquement les infos du film via l’<code>imdb_id</code> (OMDb).</span>
</div>
<form id="add-movie-form">
<div class="row g-3">
<div class="col-12 col-md-4">
<label for="oscar_year" class="form-label">Oscar year</label>
<input type="number" class="form-control" id="oscar_year" placeholder="2026" min="1900" max="3000" required>
<div class="form-text">Sépare films &amp; stats par année.</div>
</div>
<div class="col-12 col-md-4">
<label for="imdb_id" class="form-label">IMDB ID</label>
<input type="text" class="form-control" id="imdb_id" placeholder="tt1234567" required>
</div>
<div class="col-12 col-md-4">
<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="col-12 d-flex flex-wrap justify-content-end gap-2">
<button type="submit" class="btn btn-primary btn-compact">Ajouter</button>
</div>
</div>
</form>
</div>
<div class="admin-movies-separator"></div>
<div class="d-flex flex-wrap align-items-end justify-content-between gap-2 admin-movies-meta">
<div class="text-muted small">
<span id="admin-movies-table-count"></span>
</div>
</div>
<div class="row g-2 align-items-end">
<div class="col-12 col-md-4 col-xl-3">
<label for="manage_year" class="form-label visually-hidden">Oscar year</label>
<select id="manage_year" class="form-select manage-year-select">
<option value="">Toutes</option>
</select>
</div>
<div class="col-12 col-md-8 col-xl-9 d-flex gap-2 justify-content-end">
<button type="button" id="refresh-movies" class="btn btn-outline-primary btn-compact">Rafraîchir</button>
<button type="button" id="delete-selected" class="btn btn-danger btn-compact" disabled>Supprimer</button>
</div>
<div class="col-12">
<div class="d-flex justify-content-between align-items-center">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="select-all-movies">
<label class="form-check-label" for="select-all-movies">Tout sélectionner</label>
</div>
<small class="text-muted"><span id="selected-count">0</span> sélectionné(s)</small>
</div>
</div>
</div>
<div class="table-responsive mt-2">
<table class="table table-sm align-middle mb-0 admin-movies-table">
<thead>
<tr>
<th style="width: 1%;">Sel.</th>
<th style="width: 1%;">ID</th>
<th>Titre</th>
<th style="width: 12%;">Player</th>
<th style="width: 20%;">Catégorie</th>
<th style="width: 12%;">Année</th>
<th style="width: 1%;">Actions</th>
</tr>
</thead>
<tbody id="admin-movies-body">
<tr><td colspan="7" class="text-muted">Charge la liste…</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="tab-pane fade" id="admin-backup" role="tabpanel" aria-labelledby="admin-backup-tab">
<div class="card p-3">
<div class="d-flex flex-wrap align-items-end justify-content-between gap-2">
<div class="info-line small text-muted">
<span class="badge bg-light text-dark border" aria-hidden="true">i</span>
<span class="info-text">Sauvegarde et restauration de la base MongoDB.</span>
</div>
</div>
<ul class="nav nav-pills admin-subtabs mt-3" id="adminBackupSubTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="admin-backup-subtab-backup" data-bs-toggle="tab" data-bs-target="#admin-backup-pane-backup" type="button" role="tab" aria-controls="admin-backup-pane-backup" aria-selected="true">
Backup
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="admin-backup-subtab-restore" data-bs-toggle="tab" data-bs-target="#admin-backup-pane-restore" type="button" role="tab" aria-controls="admin-backup-pane-restore" aria-selected="false">
Restore
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="admin-backup-subtab-help" data-bs-toggle="tab" data-bs-target="#admin-backup-pane-help" type="button" role="tab" aria-controls="admin-backup-pane-help" aria-selected="false">
Aide
</button>
</li>
</ul>
<div class="tab-content pt-3">
<!-- Backup -->
<div class="tab-pane fade show active" id="admin-backup-pane-backup" role="tabpanel" aria-labelledby="admin-backup-subtab-backup" tabindex="0">
<div class="d-flex flex-wrap align-items-end justify-content-between gap-2 mb-2">
<div>
<div class="fw-semibold">Sauvegardes</div>
<div class="text-muted small">Format <code>.ndjson.gz</code>, stocké sur le serveur.</div>
</div>
<div class="d-flex flex-wrap gap-2">
<button type="button" id="db-backup-create" class="btn btn-warning btn-compact">Créer une sauvegarde</button>
<button type="button" id="db-backup-refresh" class="btn btn-outline-secondary btn-compact">Rafraîchir</button>
</div>
</div>
<div class="table-responsive">
<table class="table table-sm align-middle mb-0">
<thead>
<tr>
<th>Fichier</th>
<th class="text-nowrap" style="width: 1%;">Taille</th>
<th class="text-nowrap" style="width: 1%;">Modifié</th>
<th class="text-nowrap text-end" style="width: 1%;">Actions</th>
</tr>
</thead>
<tbody id="db-backup-list">
<tr><td colspan="4" class="text-muted">Ouvre l’onglet pour charger la liste…</td></tr>
</tbody>
</table>
</div>
</div>
<!-- Restore -->
<div class="tab-pane fade" id="admin-backup-pane-restore" role="tabpanel" aria-labelledby="admin-backup-subtab-restore" tabindex="0">
<div class="row g-3">
<div class="col-12 col-xxl-7">
<div class="border rounded p-3 bg-light">
<div class="fw-semibold text-danger mb-1">Restaurer une sauvegarde</div>
<div class="text-muted small mb-3">
Restaure un fichier <code>.ndjson.gz</code>. L’option <strong>drop</strong> est recommandée.
</div>
<div class="alert alert-warning mb-3">
La restauration peut <strong>écraser</strong> les données. Fais un backup juste avant si besoin.
</div>
<div class="mb-3">
<label for="db-restore-file" class="form-label">Fichier de backup</label>
<input class="form-control" type="file" id="db-restore-file" accept=".gz,.ndjson.gz,application/gzip">
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="db-restore-drop" checked>
<label class="form-check-label" for="db-restore-drop">
Drop les collections avant restore (recommandé)
</label>
</div>
<div class="d-flex flex-wrap justify-content-end gap-2">
<button type="button" id="db-restore-run" class="btn btn-danger btn-compact">Restaurer</button>
</div>
<div id="db-restore-result" class="small text-muted mt-3"></div>
</div>
</div>
<div class="col-12 col-xxl-5">
<div class="border rounded p-3 bg-white">
<div class="fw-semibold mb-2">Conseil</div>
<div class="text-muted">
Utilise <strong>drop</strong> sauf si tu sais exactement ce que tu fais (sinon risque de doublons/erreurs).
</div>
</div>
</div>
</div>
</div>
<!-- Help -->
<div class="tab-pane fade" id="admin-backup-pane-help" role="tabpanel" aria-labelledby="admin-backup-subtab-help" tabindex="0">
<div class="row g-3">
<div class="col-12 col-xxl-8">
<div class="border rounded p-3 bg-white">
<div class="fw-semibold mb-2">Fonctionnement</div>
<ul class="mb-0 text-muted">
<li><strong>Backup</strong>: crée un fichier <code>.ndjson.gz</code> (export MongoDB) et le garde sur le serveur.</li>
<li><strong>Télécharger</strong>: récupère le fichier localement (utile avant une manipulation risquée).</li>
<li><strong>Restore</strong>: importe le fichier. Avec <strong>drop</strong>, les collections restaurées sont d’abord supprimées.</li>
</ul>
</div>
</div>
<div class="col-12 col-xxl-4">
<div class="border rounded p-3 bg-light">
<div class="fw-semibold mb-2">Check rapide</div>
<div class="text-muted">
Après restore, recharge la page et vérifie “Films”, “Checklist” et “Statistiques”.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="admin-categories" role="tabpanel" aria-labelledby="admin-categories-tab">
<div class="card p-3">
<div class="d-flex flex-wrap align-items-end justify-content-between gap-2">
<div class="info-line small text-muted">
<span class="badge bg-light text-dark border" aria-hidden="true">i</span>
<span class="info-text">Créez et gérez les catégories manuellement.</span>
</div>
</div>
<ul class="nav nav-pills admin-subtabs mt-3" id="adminCategoriesSubTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="admin-categories-subtab-manual" data-bs-toggle="tab" data-bs-target="#admin-categories-pane-manual" type="button" role="tab" aria-controls="admin-categories-pane-manual" aria-selected="true">
Création manuelle
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="admin-categories-subtab-list" data-bs-toggle="tab" data-bs-target="#admin-categories-pane-list" type="button" role="tab" aria-controls="admin-categories-pane-list" aria-selected="false">
Liste
</button>
</li>
</ul>
<div class="tab-content pt-3">
<!-- Manual creation -->
<div class="tab-pane fade show active" id="admin-categories-pane-manual" role="tabpanel" aria-labelledby="admin-categories-subtab-manual" tabindex="0">
<div class="row g-3">
<div class="col-12 col-xxl-7">
<div class="border rounded p-3 bg-light">
<div class="fw-semibold mb-1">Créer une catégorie manuellement</div>
<div class="text-muted small mb-3">
Ajoutez une catégorie et ses nommés un par un.
</div>
<div id="categories-manual-alert" class="alert d-none" role="alert"></div>
<form id="create-category-form">
<div class="mb-3">
<label for="manual-year" class="form-label">Année</label>
<select class="form-select" id="manual-year" required>
<option value="">Chargement...</option>
</select>
</div>
<div class="mb-3">
<label for="category-number" class="form-label">Numéro de catégorie</label>
<input type="number" class="form-control" id="category-number" placeholder="1" min="1" max="50" required>
</div>
<div class="mb-3">
<label for="category-name" class="form-label">Nom de la catégorie</label>
<input type="text" class="form-control" id="category-name" placeholder="Best Picture" required>
</div>
<div class="mb-3">
<label for="nominees-list" class="form-label">Nommés (un par ligne)</label>
<textarea class="form-control" id="nominees-list" rows="10" placeholder="Anora&#10;The Brutalist&#10;Dune: Part Two" required></textarea>
<div class="form-text">Entrez un nommé par ligne.</div>
</div>
<div class="d-flex flex-wrap justify-content-end gap-2">
<button type="submit" class="btn btn-primary">Créer</button>
</div>
</form>
</div>
</div>
<div class="col-12 col-xxl-5">
<div class="border rounded p-3 bg-white">
<div class="fw-semibold mb-2">Note</div>
<div class="text-muted">
Vous pouvez créer plusieurs catégories pour la même année.
Le numéro de catégorie doit être unique par année.
</div>
</div>
</div>
</div>
</div>
<!-- List -->
<div class="tab-pane fade" id="admin-categories-pane-list" role="tabpanel" aria-labelledby="admin-categories-subtab-list" tabindex="0">
<div class="d-flex flex-wrap align-items-end justify-content-between gap-2 mb-2">
<div>
<div class="fw-semibold">Catégories importées</div>
<div class="text-muted small">Gérez les catégories existantes</div>
</div>
<div class="d-flex flex-column gap-2">
<div class="d-flex gap-2">
<select class="form-select" id="list-year-filter" style="width: 150px;">
<option value="">Toutes les années</option>
</select>
<button type="button" id="refresh-categories-list" class="btn btn-outline-secondary">Rafraîchir</button>
<button type="button" id="bulk-delete-categories-btn" class="btn btn-sm btn-danger" disabled>Supprimer</button>
</div>
<div id="categories-selection-text" class="text-muted small" style="display: none;">
<span id="bulk-delete-count">0</span> catégorie(s) sélectionnée(s)
</div>
</div>
</div>
<div id="categories-list-container" class="border rounded bg-white p-3">
<div class="text-muted">Charge la liste…</div>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="admin-winners" role="tabpanel" aria-labelledby="admin-winners-tab">
<div class="card p-3">
<div class="d-flex flex-wrap align-items-end justify-content-between gap-2">
<div class="info-line small text-muted">
<span class="badge bg-light text-dark border" aria-hidden="true">i</span>
<span class="info-text">Définis un ou plusieurs gagnants par année (égalité possible).</span>
</div>
</div>
<ul class="nav nav-pills admin-subtabs mt-3" id="adminWinnersSubTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="admin-winners-subtab-set" data-bs-toggle="tab" data-bs-target="#admin-winners-pane-set" type="button" role="tab" aria-controls="admin-winners-pane-set" aria-selected="true">
Gérer
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="admin-winners-subtab-help" data-bs-toggle="tab" data-bs-target="#admin-winners-pane-help" type="button" role="tab" aria-controls="admin-winners-pane-help" aria-selected="false">
Aide
</button>
</li>
</ul>
<div class="tab-content pt-3">
<!-- Set -->
<div class="tab-pane fade show active" id="admin-winners-pane-set" role="tabpanel" aria-labelledby="admin-winners-subtab-set" tabindex="0">
<div class="row g-3">
<div class="col-12 col-xxl-7">
<div class="border rounded p-3 bg-light">
<div class="fw-semibold mb-1">Ajouter un gagnant</div>
<div class="text-muted small mb-3">
Tu peux ajouter plusieurs gagnants pour une même année (égalité).
</div>
<div class="row g-3">
<div class="col-12 col-md-4">
<label for="winner_year" class="form-label">Année</label>
<select id="winner_year" class="form-select"></select>
<div class="form-text">Basé sur les années présentes dans les films.</div>
</div>
<div class="col-12 col-md-5">
<label for="winner_user" class="form-label">Utilisateur</label>
<select id="winner_user" class="form-select">
<option value="">—</option>
</select>
<div class="form-text">Pour retirer: utilise la liste ci-dessous.</div>
</div>
<div class="col-12 col-md-3">
<label for="winner_points" class="form-label">Points (optionnel)</label>
<input id="winner_points" type="number" class="form-control" placeholder="ex: 42" min="0" step="1">
<div class="form-text">Laisse vide si non applicable.</div>
</div>
</div>
<div class="d-flex flex-wrap justify-content-end gap-2 mt-3">
<button type="button" id="winner_reload" class="btn btn-outline-secondary btn-compact">Recharger</button>
<button type="button" id="winner_clear" class="btn btn-outline-danger btn-compact">Tout supprimer</button>
<button type="button" id="winner_save" class="btn btn-warning btn-compact">Ajouter</button>
</div>
</div>
</div>
<div class="col-12 col-xxl-5">
<div class="border rounded p-3 bg-white h-100">
<div class="d-flex flex-wrap align-items-end justify-content-between gap-2 mb-2">
<div>
<div class="fw-semibold">Gagnants actuels</div>
<div class="text-muted small">Vue globale (toutes les années).</div>
</div>
</div>
<div id="winner_current" class="border rounded p-2 bg-light">—</div>
</div>
</div>
</div>
</div>
<!-- Help -->
<div class="tab-pane fade" id="admin-winners-pane-help" role="tabpanel" aria-labelledby="admin-winners-subtab-help" tabindex="0">
<div class="row g-3">
<div class="col-12 col-xxl-8">
<div class="border rounded p-3 bg-white">
<div class="fw-semibold mb-2">Comment ça marche</div>
<ul class="mb-0 text-muted">
<li>Une année peut avoir <strong>plusieurs gagnants</strong> (égalité).</li>
<li>Les points sont <strong>optionnels</strong> (affichage uniquement).</li>
<li>Pour retirer un gagnant, utilise le bouton “Retirer” dans la liste “Gagnants actuels”.</li>
</ul>
</div>
</div>
<div class="col-12 col-xxl-4">
<div class="border rounded p-3 bg-light">
<div class="fw-semibold mb-2">Astuce</div>
<div class="text-muted">
Si tu changes l’année active du site, vérifie aussi les gagnants de cette année.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Reset user password modal -->
<div class="modal fade" id="resetUserPasswordModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Reset mot de passe</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="text-muted mb-2">
Génère un mot de passe temporaire. L'utilisateur devra le changer à sa prochaine connexion.
</div>
<div class="mb-3">
<div class="fw-semibold" id="reset_user_label">—</div>
<div class="text-muted small" id="reset_user_email_label">—</div>
</div>
<div id="reset-user-modal-response" class="alert d-none" role="alert"></div>
<div id="reset-user-modal-result" class="border rounded p-2 bg-light d-none">
<div class="small text-muted mb-1">Mot de passe temporaire (affiché une seule fois)</div>
<div class="d-flex gap-2 align-items-center">
<code class="flex-grow-1" id="reset-user-temp-password">—</code>
<button type="button" class="btn btn-outline-secondary btn-sm" id="copy-temp-password">Copier</button>
</div>
<div class="small text-muted mt-2" id="reset-user-expires-at"></div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary btn-compact" data-bs-dismiss="modal">Fermer</button>
<button type="button" class="btn btn-danger btn-compact" id="confirm-reset-user-password">Générer</button>
</div>
</div>
</div>
</div>
<!-- Delete user confirmation modal -->
<div class="modal fade" id="deleteUserModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title text-danger">Supprimer un utilisateur</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-2">
Tu es sur le point de supprimer:
<div class="fw-semibold" id="delete_user_label">—</div>
<div class="text-muted small" id="delete_user_email_label">—</div>
</div>
<div class="alert alert-warning">
Cette action est <strong>irréversible</strong>.
</div>
<div class="mb-2">
Pour confirmer, tape l'email exact:
</div>
<input type="text" class="form-control" id="delete_user_verify_input" placeholder="[email protected]">
<div class="form-text">
Le bouton “Supprimer” s'activera seulement si l'email correspond.
</div>
<div id="delete-user-modal-response" class="alert d-none mt-3" role="alert"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary btn-compact" data-bs-dismiss="modal">Annuler</button>
<button type="button" class="btn btn-danger btn-compact" id="confirm-delete-user" disabled>Supprimer</button>
</div>
</div>
</div>
</div>
<!-- Add user modal -->
<div class="modal fade" id="addUserModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Ajouter un utilisateur</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="text-muted mb-2">
Crée un compte avec un <strong>mot de passe temporaire</strong> (affiché une seule fois). L’utilisateur devra le changer à sa prochaine connexion.
</div>
<div id="add-user-response" class="alert d-none" role="alert"></div>
<form id="add-user-form">
<div class="mb-3">
<label for="add_user_name" class="form-label">Nom</label>
<input type="text" class="form-control" id="add_user_name" placeholder="Prénom / pseudo" required>
</div>
<div class="mb-3">
<label for="add_user_email" class="form-label">Email</label>
<input type="email" class="form-control" id="add_user_email" placeholder="[email protected]" required>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="add_user_admin">
<label class="form-check-label" for="add_user_admin">Admin</label>
</div>
<div id="add-user-result" class="border rounded p-2 bg-light d-none">
<div class="small text-muted mb-1">Mot de passe temporaire (affiché une seule fois)</div>
<div class="d-flex gap-2 align-items-center">
<code class="flex-grow-1" id="add-user-temp-password">—</code>
<button type="button" class="btn btn-outline-secondary btn-sm" id="copy-add-user-temp-password">Copier</button>
</div>
<div class="small text-muted mt-2" id="add-user-expires-at"></div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Fermer</button>
<button type="button" id="add-user-reset" class="btn btn-outline-secondary">Reset</button>
<button type="submit" form="add-user-form" class="btn btn-warning" id="add-user-submit">Créer</button>
</div>
</div>
</div>
</div>
<!-- Edit category modal -->
<div class="modal fade" id="editCategoryModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modifier la catégorie</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<input type="hidden" id="edit_category_id">
<div class="mb-3">
<label for="edit_category_number" class="form-label">Numéro de catégorie</label>
<input type="number" class="form-control" id="edit_category_number" min="1" max="50" required>
</div>
<div class="mb-3">
<label for="edit_category_name" class="form-label">Nom de la catégorie</label>
<input type="text" class="form-control" id="edit_category_name" required>
</div>
<div class="mb-3">
<label for="edit_nominees_list" class="form-label">Nommés (un par ligne)</label>
<textarea class="form-control" id="edit_nominees_list" rows="10" required></textarea>
<div class="form-text">Entrez un nommé par ligne.</div>
</div>
<div id="edit-category-alert" class="alert d-none" role="alert"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Annuler</button>
<button type="button" class="btn btn-primary" id="save-category-changes">Enregistrer</button>
</div>
</div>
</div>
</div>
<!-- Edit movie modal -->
<div class="modal fade" id="editMovieModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editMovieModalTitle">Modifier le film</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<input type="hidden" id="edit_movie_id">
<div class="mb-3">
<div class="text-muted small mb-1">Movie ID</div>
<div class="d-flex gap-2 align-items-center">
<code class="flex-grow-1" id="edit_movie_id_label">—</code>
<button type="button" class="btn btn-outline-secondary btn-sm" id="copy-movie-id">Copier</button>
</div>
</div>
<ul class="nav nav-tabs" id="editMovieTabs" role="tablist">
<li class="nav-item" role="presentation">
<button
class="nav-link active"
id="edit-movie-tab-info"
data-bs-toggle="tab"
data-bs-target="#edit-movie-pane-info"
type="button"
role="tab"
aria-controls="edit-movie-pane-info"
aria-selected="true"
>
Info
</button>
</li>
<li class="nav-item" role="presentation">
<button
class="nav-link"
id="edit-movie-tab-video"
data-bs-toggle="tab"
data-bs-target="#edit-movie-pane-video"
type="button"
role="tab"
aria-controls="edit-movie-pane-video"
aria-selected="false"
>
Player / Vidéo
</button>
</li>
</ul>
<div class="tab-content pt-3" id="editMovieTabsContent">
<!-- Info tab -->
<div
class="tab-pane fade show active"
id="edit-movie-pane-info"
role="tabpanel"
aria-labelledby="edit-movie-tab-info"
tabindex="0"
>
<div class="row g-3">
<div class="col-md-6">
<label for="edit_imdb_id" class="form-label">IMDB ID (ex: tt1234567)</label>
<input type="text" class="form-control" id="edit_imdb_id" placeholder="tt..." required>
</div>
<div class="col-md-6">
<label for="edit_year" class="form-label">Oscar year</label>
<input type="number" class="form-control" id="edit_year" placeholder="2026" min="1900" max="3000">
</div>
<div class="col-md-6">
<label for="edit_category" class="form-label">Catégorie</label>
<input type="text" class="form-control" id="edit_category" placeholder="Best Picture, etc." required>
</div>
<div class="col-md-6">
<label for="edit_rating" class="form-label">Rating (imdbRating)</label>
<input type="text" class="form-control" id="edit_rating" placeholder="7.9">
</div>
<div class="col-md-6 d-flex align-items-end">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="edit_cam_flag">
<label class="form-check-label" for="edit_cam_flag">Tag CAM</label>
</div>
</div>
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="edit_refresh_omdb">
<label class="form-check-label" for="edit_refresh_omdb">
Recharger depuis OMDb (écrase titre / plot / rating / poster)
</label>
</div>
<div class="form-text">Si coché, le serveur refait un appel OMDb via l’IMDB ID au moment de l’enregistrement.</div>
</div>
<div class="col-12">
<label for="edit_title" class="form-label">Titre</label>
<input type="text" class="form-control" id="edit_title" placeholder="Title">
</div>
<div class="col-12">
<label for="edit_poster" class="form-label">Poster URL</label>
<input type="url" class="form-control" id="edit_poster" placeholder="https://...">
</div>
<div class="col-12">
<label for="edit_description" class="form-label">Description (Plot)</label>
<textarea class="form-control" id="edit_description" rows="4" placeholder="Plot..."></textarea>
</div>
</div>
</div>
<!-- Video tab -->
<div
class="tab-pane fade"
id="edit-movie-pane-video"
role="tabpanel"
aria-labelledby="edit-movie-tab-video"
tabindex="0"
>
<div class="row g-3">
<div class="col-12">
<label class="form-label">Lecteur (source)</label>
<div class="row g-2">
<div class="col-12 col-lg-4">
<label for="edit_player_mode" class="form-label">Mode</label>
<select id="edit_player_mode" class="form-select">
<option value="auto">Auto</option>
<option value="video">Video</option>
<option value="embed">Embed</option>
</select>
<div class="form-text">Auto = video_src → embed_src → vod_link.</div>
</div>
<div class="col-12 col-lg-8">
<label for="edit_video_src" class="form-label">Video URL (mp4/webm/m3u8)</label>
<input type="text" class="form-control" id="edit_video_src" placeholder="https://.../movie.mp4 or .../playlist.m3u8">
<div class="form-text">If you use a server file (below) and leave this empty, it will auto-use <code>/api/video/&lt;movieId&gt;</code>.</div>
</div>
<div class="col-12">
<label for="edit_video_file" class="form-label">Server video file (optional)</label>
<input type="text" class="form-control font-monospace" id="edit_video_file" placeholder="my_movie.mp4 or 2026/my_movie.mp4">
<div class="form-text">Relative path under <code>VIDEO_FILES_DIR</code> (default: <code>public/video</code>).</div>
</div>
<div class="col-12">
<label for="edit_video_file_low" class="form-label">Server video file (low quality, optional)</label>
<input type="text" class="form-control font-monospace" id="edit_video_file_low" placeholder="LOW/my_movie.LOW.mp4">
<div class="form-text">Relative path under <code>VIDEO_FILES_DIR</code>. Example: <code>LOW/123.LOW.mp4</code>.</div>
</div>
<div class="col-12">
<label for="edit_subtitle_file" class="form-label">Sous-titres (SRT, optionnel)</label>
<input type="file" class="form-control" id="edit_subtitle_file" accept=".srt,.vtt,text/plain,text/vtt">
<div class="form-text">Sous-titres existants:</div>
<div id="edit_subtitle_list" class="d-flex flex-column gap-2 mt-1"></div>
<div class="form-text">Ajoute un fichier par langue; répète l’upload pour plusieurs sous-titres.</div>
</div>
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="edit_subtitle_remove">
<label class="form-check-label" for="edit_subtitle_remove">Supprimer tous les sous-titres</label>
</div>
<div class="form-text">Efface les fichiers VTT/SRT et réinitialise les champs de langue/label.</div>
</div>
<div class="col-12 col-lg-4">
<label for="edit_subtitle_lang" class="form-label">Langue (ex: fr, en)</label>
<input type="text" class="form-control" id="edit_subtitle_lang" placeholder="fr">
</div>
<div class="col-12 col-lg-4">
<label for="edit_subtitle_label" class="form-label">Label (affiché)</label>
<input type="text" class="form-control" id="edit_subtitle_label" placeholder="Français">
</div>
<div class="col-12 col-lg-4 d-flex align-items-end">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="edit_subtitle_default">
<label class="form-check-label" for="edit_subtitle_default">Par défaut</label>
</div>
</div>
<div class="col-12">
<label for="edit_embed_src" class="form-label">Embed URL or iframe code</label>
<textarea class="form-control font-monospace" id="edit_embed_src" rows="3" placeholder="https://... OR <iframe ...>"></textarea>
</div>
<div class="col-12">
<label for="edit_vod_link" class="form-label">Legacy VOD link (optional)</label>
<input type="text" class="form-control" id="edit_vod_link" placeholder="https://...">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Annuler</button>
<button type="button" class="btn btn-primary" id="save-movie-changes">Enregistrer</button>
</div>
</div>
</div>
</div>
<!-- Footer Section -->
<footer>
<p id="footer-copy">Oscar Pool <span aria-hidden="true">·</span> <a id="copy" href="https://github.com/quoije/oscars-pool">quoije</a></p>
<p id="footer-text"></p>
</footer>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="./js/app_control.js"></script>
<script src="./js/app_version.js"></script>
</body>
</html>