mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-07 03:29:19 +02:00
312 lines
14 KiB
PHP
312 lines
14 KiB
PHP
<?php
|
|
require_once __DIR__ . "/../../config/bootstrap.php";
|
|
require_once __DIR__ . '/../../src/AdminAuth.php';
|
|
AdminAuth::requireLogin();
|
|
|
|
if (empty($_SESSION["csrf_token"])) {
|
|
$_SESSION["csrf_token"] = bin2hex(random_bytes(32));
|
|
}
|
|
|
|
$pageTitle = "Ajouter un TFE";
|
|
|
|
require_once __DIR__ . '/../../src/Database.php';
|
|
|
|
try {
|
|
$db = new Database();
|
|
$orientations = $db->getAllOrientations();
|
|
$apPrograms = $db->getAllAPPrograms();
|
|
$finalityTypes = $db->getAllFinalityTypes();
|
|
$languages = $db->getAllLanguages();
|
|
$formatTypes = $db->getAllFormatTypes();
|
|
$licenseTypes = $db->getAllLicenseTypes();
|
|
} catch (Exception $e) {
|
|
error_log("Failed to load form data: " . $e->getMessage());
|
|
die("Erreur lors du chargement du formulaire.");
|
|
}
|
|
|
|
$error = $_SESSION["form_error"] ?? null;
|
|
$formData = $_SESSION["form_data"] ?? [];
|
|
unset($_SESSION["form_error"], $_SESSION["form_data"]);
|
|
|
|
function old($key, $default = "") {
|
|
global $formData;
|
|
return isset($formData[$key]) ? htmlspecialchars($formData[$key]) : $default;
|
|
}
|
|
function wasSelected($key, $value) {
|
|
global $formData;
|
|
if (!isset($formData[$key])) return false;
|
|
if (is_array($formData[$key])) return in_array($value, $formData[$key]);
|
|
return $formData[$key] == $value;
|
|
}
|
|
?>
|
|
<?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?>
|
|
<?php include APP_ROOT . '/templates/header.php'; ?>
|
|
|
|
<main class="admin-main" id="main-content">
|
|
<h1 class="admin-page-title">Ajouter un TFE</h1>
|
|
|
|
<?php if ($error): ?>
|
|
<div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<form action="actions/formulaire.php" method="post" enctype="multipart/form-data" class="admin-form">
|
|
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION["csrf_token"]) ?>">
|
|
|
|
<!-- Titre -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="titre">Titre :</label>
|
|
<input class="admin-input" type="text" id="titre" name="titre"
|
|
value="<?= old('titre') ?>" required>
|
|
</div>
|
|
|
|
<!-- Sous-titre -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="subtitle">Sous-titre (si applicable) :</label>
|
|
<input class="admin-input" type="text" id="subtitle" name="subtitle"
|
|
value="<?= old('subtitle') ?>">
|
|
</div>
|
|
|
|
<!-- Auteur·ice -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="auteurice">Auteur·ice(s) :</label>
|
|
<input class="admin-input" type="text" id="auteurice" name="auteurice"
|
|
value="<?= old('auteurice') ?>" required>
|
|
</div>
|
|
|
|
<!-- Contact -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="mail">Contact(s) (optionnel) [mail/site/insta/etc.] :</label>
|
|
<input class="admin-input" type="text" id="mail" name="mail"
|
|
value="<?= old('mail') ?>">
|
|
</div>
|
|
|
|
<!-- Composition du jury -->
|
|
<fieldset class="admin-fieldset">
|
|
<legend class="admin-fieldset-legend">Composition du jury</legend>
|
|
|
|
<!-- Président·e -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="jury_president">Président·e :</label>
|
|
<input class="admin-input" type="text" id="jury_president" name="jury_president"
|
|
value="<?= old('jury_president') ?>"
|
|
placeholder="Nom du/de la président·e (interne)">
|
|
</div>
|
|
|
|
<!-- Promoteur·ice -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="jury_promoteur">Promoteur·ice :</label>
|
|
<div class="admin-jury-row">
|
|
<input class="admin-input" type="text" id="jury_promoteur" name="jury_promoteur"
|
|
value="<?= old('jury_promoteur') ?>" placeholder="Nom">
|
|
<label class="admin-checkbox-label admin-jury-ext">
|
|
<input type="checkbox" name="jury_promoteur_ext" value="1"
|
|
<?= wasSelected('jury_promoteur_ext', '1') ? 'checked' : '' ?>>
|
|
Externe
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Lecteur·ices (dynamic) -->
|
|
<div class="admin-form-row" style="align-items:start;">
|
|
<label class="admin-label">Lecteur·ices :</label>
|
|
<div id="jury-lecteurs-list" class="admin-jury-list">
|
|
<!-- rows injected by JS; start with one empty row -->
|
|
<div class="admin-jury-entry">
|
|
<input class="admin-input" type="text" name="jury_lecteurs[]" placeholder="Nom">
|
|
<label class="admin-checkbox-label admin-jury-ext">
|
|
<input type="checkbox" name="jury_lecteurs_ext[0]" value="1"> Externe
|
|
</label>
|
|
<button type="button" class="admin-btn-remove" onclick="removeJuryRow(this)" aria-label="Supprimer ce lecteur">✕</button>
|
|
</div>
|
|
</div>
|
|
<button type="button" class="admin-btn-secondary" style="margin-top:.5rem;"
|
|
onclick="addJuryRow()">+ Ajouter un·e lecteur·ice</button>
|
|
</div>
|
|
</fieldset>
|
|
<script>
|
|
var juryIdx = 1;
|
|
function addJuryRow() {
|
|
var list = document.getElementById('jury-lecteurs-list');
|
|
var div = document.createElement('div');
|
|
div.className = 'admin-jury-entry';
|
|
div.innerHTML = '<input class="admin-input" type="text" name="jury_lecteurs[]" placeholder="Nom">'
|
|
+ '<label class="admin-checkbox-label admin-jury-ext">'
|
|
+ '<input type="checkbox" name="jury_lecteurs_ext[' + juryIdx + ']" value="1"> Externe'
|
|
+ '</label>'
|
|
+ '<button type="button" class="admin-btn-remove" onclick="removeJuryRow(this)" aria-label="Supprimer ce lecteur">✕</button>';
|
|
list.appendChild(div);
|
|
juryIdx++;
|
|
}
|
|
function removeJuryRow(btn) {
|
|
btn.closest('.admin-jury-entry').remove();
|
|
}
|
|
</script>
|
|
|
|
<!-- Année -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="année">Année :</label>
|
|
<input class="admin-input" type="number" id="année" name="année"
|
|
min="2000" max="<?= date('Y') + 1 ?>"
|
|
placeholder="<?= date('Y') ?>"
|
|
value="<?= old('année') ?>" required>
|
|
</div>
|
|
|
|
<!-- Orientation -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="orientation">Orientation :</label>
|
|
<select class="admin-select" id="orientation" name="orientation" required>
|
|
<option value=""></option>
|
|
<?php foreach ($orientations as $o): ?>
|
|
<option value="<?= htmlspecialchars($o['id']) ?>"
|
|
<?= wasSelected('orientation', $o['id']) ? 'selected' : '' ?>>
|
|
<?= htmlspecialchars($o['name']) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- AP -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="ap">Atelier pluridisciplinaire :</label>
|
|
<select class="admin-select" id="ap" name="ap" required>
|
|
<option value=""></option>
|
|
<?php foreach ($apPrograms as $ap): ?>
|
|
<option value="<?= htmlspecialchars($ap['id']) ?>"
|
|
<?= wasSelected('ap', $ap['id']) ? 'selected' : '' ?>>
|
|
<?= htmlspecialchars($ap['name']) ?><?php if ($ap['code']): ?> (<?= htmlspecialchars($ap['code']) ?>)<?php endif; ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Finalité -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="finality">Finalité du master :</label>
|
|
<select class="admin-select" id="finality" name="finality" required>
|
|
<option value=""></option>
|
|
<?php foreach ($finalityTypes as $f): ?>
|
|
<option value="<?= htmlspecialchars($f['id']) ?>"
|
|
<?= wasSelected('finality', $f['id']) ? 'selected' : '' ?>>
|
|
<?= htmlspecialchars($f['name']) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Langue(s) -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label">Langue(s) :</label>
|
|
<div class="admin-checkbox-list">
|
|
<?php foreach ($languages as $lang): ?>
|
|
<label class="admin-checkbox-label">
|
|
<input type="checkbox" name="languages[]"
|
|
value="<?= htmlspecialchars($lang['id']) ?>"
|
|
<?= wasSelected('languages', $lang['id']) ? 'checked' : '' ?>>
|
|
<?= htmlspecialchars($lang['name']) ?>
|
|
</label>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Format(s) -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label">Format(s) :</label>
|
|
<div class="admin-checkbox-list">
|
|
<?php foreach ($formatTypes as $fmt): ?>
|
|
<label class="admin-checkbox-label">
|
|
<input type="checkbox" name="formats[]"
|
|
value="<?= htmlspecialchars($fmt['id']) ?>"
|
|
<?= wasSelected('formats', $fmt['id']) ? 'checked' : '' ?>>
|
|
<?= htmlspecialchars($fmt['name']) ?>
|
|
</label>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mots-clés -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="tag">Mots-clés :</label>
|
|
<div>
|
|
<input class="admin-input" type="text" id="tag" name="tag"
|
|
placeholder="sociologie, anthropologie, ..."
|
|
value="<?= old('tag') ?>">
|
|
<p class="admin-hint">Séparez par des virgules. Max 10 mots-clés.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Synopsis -->
|
|
<div class="admin-form-row" style="align-items:start;">
|
|
<label class="admin-label" for="synopsis">Synopsis :</label>
|
|
<textarea class="admin-textarea" id="synopsis" name="synopsis"
|
|
rows="7" required><?= old('synopsis') ?></textarea>
|
|
</div>
|
|
|
|
<!-- Licence -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="license_id">Licence :</label>
|
|
<select class="admin-select" id="license_id" name="license_id">
|
|
<option value="">— Inconnue —</option>
|
|
<?php foreach ($licenseTypes as $lt): ?>
|
|
<option value="<?= htmlspecialchars($lt['id']) ?>"
|
|
<?= wasSelected('license_id', $lt['id']) ? 'selected' : '' ?>>
|
|
<?= htmlspecialchars($lt['name']) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Durée/Taille -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="duration_info">Durée / Taille :</label>
|
|
<div>
|
|
<input class="admin-input" type="text" id="duration_info" name="duration_info"
|
|
placeholder="Ex : 84 pages"
|
|
value="<?= old('duration_info') ?>">
|
|
<p class="admin-hint">Durée (minutes) ou nombre de pages.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Lien -->
|
|
<div class="admin-form-row">
|
|
<label class="admin-label" for="lien">Lien (site / ressource) :</label>
|
|
<input class="admin-input" type="url" id="lien" name="lien"
|
|
placeholder="https://..."
|
|
value="<?= old('lien') ?>">
|
|
</div>
|
|
|
|
<!-- Image couverture -->
|
|
<div class="admin-form-row" style="align-items:start;">
|
|
<label class="admin-label">Image de couverture :</label>
|
|
<div class="admin-file-input">
|
|
<input type="file" id="couverture" name="couverture" accept="image/jpeg,image/png">
|
|
<p class="admin-hint">JPG, PNG. Taille max : 10 MB.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Image bannière -->
|
|
<div class="admin-form-row" style="align-items:start;">
|
|
<label class="admin-label">Image bannière (accueil) :</label>
|
|
<div class="admin-file-input">
|
|
<input type="file" id="banner" name="banner" accept="image/jpeg,image/png,image/webp">
|
|
<p class="admin-hint">JPG, PNG ou WEBP. Format paysage recommandé (4:1). Max 5 MB.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Fichiers -->
|
|
<div class="admin-form-row" style="align-items:start;">
|
|
<label class="admin-label">Fichiers du TFE :</label>
|
|
<div class="admin-file-input">
|
|
<input type="file" id="files" name="files[]" multiple
|
|
accept=".pdf,.jpg,.jpeg,.png,.mp4,.zip">
|
|
<p class="admin-hint">PDF, JPG, PNG, MP4, ZIP. Max 50 MB par fichier.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="admin-submit-wrap">
|
|
<button type="submit" name="go" class="admin-btn">Soumettre</button>
|
|
</div>
|
|
</form>
|
|
</main>
|
|
|
|
<?php require_once APP_ROOT . '/templates/admin/footer.php'; ?>
|