Redesign UI to match target design images

- Flat purple-gradient nav bar with POSTERG/RÉPERTOIRE/À PROPOS links
- Full-width search bar with icon, bottom-border only, below nav
- Home: white bg, media card grid (thumbnail + author/title label below)
- Répertoire: 4-column index (Années/Catégories/Étudiantes/Mots-clés)
- TFE: 2-column layout (large text left, media right)
- À Propos: 2-column, large monospace text, new apropos.php page
- Admin: dark theme (#1a1a1a), purple gradient nav, bottom-border inputs
- New shared partials: templates/nav.php, templates/search-bar.php
- Rewrote all CSS: common, main, search, tfe, apropos, admin
This commit is contained in:
Pontoporeia
2026-02-24 23:34:16 +01:00
parent eaad740574
commit 2110d2b916
22 changed files with 2459 additions and 3043 deletions

View File

@@ -1,263 +1,238 @@
<?php
// Bootstrap application
require_once __DIR__ . "/../../config/bootstrap.php";
require_once __DIR__ . '/../../src/AdminAuth.php';
// PHP-level auth guard (defence-in-depth behind nginx Basic Auth)
AdminAuth::requireLogin();
if (empty($_SESSION["csrf_token"])) {
$_SESSION["csrf_token"] = bin2hex(random_bytes(32));
}
$pageTitle = "Ajout de TFE";
$pageTitle = "Ajouter un TFE";
// Load database helper
require_once __DIR__ . '/../../src/Database.php';
try {
$db = new Database();
$orientations = $db->getAllOrientations();
$apPrograms = $db->getAllAPPrograms();
$apPrograms = $db->getAllAPPrograms();
$finalityTypes = $db->getAllFinalityTypes();
$languages = $db->getAllLanguages();
$formatTypes = $db->getAllFormatTypes();
$languages = $db->getAllLanguages();
$formatTypes = $db->getAllFormatTypes();
} catch (Exception $e) {
error_log("Failed to load form data: " . $e->getMessage());
die("Erreur lors du chargement du formulaire. Veuillez réessayer plus tard.");
die("Erreur lors du chargement du formulaire.");
}
// Get error message and preserved form data from session (if redirected back from error)
$error = isset($_SESSION["form_error"]) ? $_SESSION["form_error"] : null;
$formData = isset($_SESSION["form_data"]) ? $_SESSION["form_data"] : [];
$error = $_SESSION["form_error"] ?? null;
$formData = $_SESSION["form_data"] ?? [];
unset($_SESSION["form_error"], $_SESSION["form_data"]);
// Clear session data after retrieving
unset($_SESSION["form_error"]);
unset($_SESSION["form_data"]);
// Helper function to get old form value
function old($key, $default = "")
{
function old($key, $default = "") {
global $formData;
return isset($formData[$key])
? htmlspecialchars($formData[$key])
: $default;
return isset($formData[$key]) ? htmlspecialchars($formData[$key]) : $default;
}
// Helper function to check if value was previously selected
function wasSelected($key, $value)
{
function wasSelected($key, $value) {
global $formData;
if (!isset($formData[$key])) {
return false;
}
if (is_array($formData[$key])) {
return in_array($value, $formData[$key]);
}
if (!isset($formData[$key])) return false;
if (is_array($formData[$key])) return in_array($value, $formData[$key]);
return $formData[$key] == $value;
}
?>
<?php require_once APP_ROOT . '/templates/admin/head.php'; ?>
<main>
<main class="admin-main">
<h1 class="admin-page-title">Ajouter un TFE</h1>
<?php if ($error): ?>
<div class="error-message">
<strong>⚠️ Erreur:</strong> <?php echo htmlspecialchars($error); ?>
</div>
<div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div>
<?php endif; ?>
<form action="actions/formulaire.php" method="post" enctype="multipart/form-data">
<!-- CSRF Protection -->
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars(
$_SESSION["csrf_token"],
); ?>">
<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>
<fieldset>
<legend>Informations de base</legend>
<label for="auteurice">Nom/Prénom/Pseudo *</label>
<input type="text" id="auteurice" name="auteurice" placeholder="Nom de l'auteur·ice" value="<?php echo old(
"auteurice",
); ?>" required>
<br>
<label for="mail">Contact (email, site web, insta, ...)</label>
<input type="text" id="mail" name="mail" placeholder="votre.email@example.com ou @instagram" value="<?php echo old(
"mail",
); ?>">
<br>
<label for="année">Année diplômante *</label>
<input type="number" id="année" name="année" min="2000" max="<?php echo date(
"Y",
) + 1; ?>" placeholder="<?php echo date(
"Y",
); ?>" value="<?php echo old("année"); ?>" required>
</fieldset>
<!-- 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>
<fieldset>
<legend>Informations académiques</legend>
<label for="orientation">Orientation principale *</label>
<select id="orientation" name="orientation" required>
<option value="">-- Sélectionner une orientation --</option>
<?php foreach ($orientations as $orientation): ?>
<option value="<?php echo htmlspecialchars(
$orientation["id"],
); ?>" <?php echo wasSelected(
"orientation",
$orientation["id"],
)
? "selected"
: ""; ?>>
<?php echo htmlspecialchars(
$orientation["name"],
); ?>
<!-- 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>
<!-- Promoteur interne -->
<div class="admin-form-row">
<label class="admin-label" for="promoteurice">Promoteur·ice interne :</label>
<input class="admin-input" type="text" id="promoteurice" name="promoteurice"
value="<?= old('promoteurice') ?>">
</div>
<!-- Promoteur externe -->
<div class="admin-form-row">
<label class="admin-label" for="promoteurice_externe">Promoteur·ice externe :</label>
<input class="admin-input" type="text" id="promoteurice_externe" name="promoteurice_externe"
value="<?= old('promoteurice_externe') ?>">
</div>
<!-- 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>
<br>
<label for="ap">Atelier Pratique (AP) *</label>
<select id="ap" name="ap" required>
<option value="">-- Sélectionner un AP --</option>
<!-- 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="<?php echo htmlspecialchars(
$ap["id"],
); ?>" <?php echo wasSelected("ap", $ap["id"])
? "selected"
: ""; ?>>
<?php echo htmlspecialchars($ap["name"]); ?>
<?php if (
$ap["code"]
): ?> (<?php echo htmlspecialchars(
$ap["code"],
); ?>)<?php endif; ?>
<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>
<br>
<label for="finality">Finalité du master *</label>
<select id="finality" name="finality" required>
<option value="">-- Sélectionner une finalité --</option>
<?php foreach ($finalityTypes as $finality): ?>
<option value="<?php echo htmlspecialchars(
$finality["id"],
); ?>" <?php echo wasSelected(
"finality",
$finality["id"],
)
? "selected"
: ""; ?>>
<?php echo htmlspecialchars($finality["name"]); ?>
<!-- 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>
<br>
<label for="promoteurice">Promoteur·ice(s)</label>
<input type="text" id="promoteurice" name="promoteurice" placeholder="Nom du/de la promoteur·ice (si plusieurs, séparer par des virgules)" value="<?php echo old(
"promoteurice",
); ?>">
</fieldset>
<fieldset>
<legend>À propos du TFE</legend>
<label for="titre">Titre du mémoire *</label>
<input type="text" id="titre" name="titre" placeholder="Titre de votre TFE" value="<?php echo old(
"titre",
); ?>" required>
<br>
<label for="subtitle">Sous-titre (si applicable)</label>
<input type="text" id="subtitle" name="subtitle" placeholder="Sous-titre de votre TFE" value="<?php echo old(
"subtitle",
); ?>">
<br>
<label for="synopsis">Synopsis (environ 200 mots) *</label>
<textarea id="synopsis" name="synopsis" rows="8" placeholder="Décrivez votre TFE en quelques paragraphes..." required><?php echo old(
"synopsis",
); ?></textarea>
<br>
<label for="problématique">Problématique</label>
<textarea id="problématique" name="problématique" rows="4" placeholder="La problématique principale de votre mémoire..."><?php echo old(
"problématique",
); ?></textarea>
<br>
<label>Langue(s) du TFE * (sélection multiple possible)</label>
<ul class="no-style">
<?php foreach ($languages as $language): ?>
<li>
<label class="checkbox-label">
<input type="checkbox" name="languages[]" value="<?php echo htmlspecialchars(
$language["id"],
); ?>" <?php echo wasSelected(
"languages",
$language["id"],
)
? "checked"
: ""; ?>>
<?php echo htmlspecialchars($language["name"]); ?>
</label>
</li>
<!-- 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; ?>
</ul>
</div>
</div>
<br>
<label>Format(s) (sélection multiple possible)</label>
<ul class="no-style">
<?php foreach ($formatTypes as $format): ?>
<li>
<label class="checkbox-label">
<input type="checkbox" name="formats[]" value="<?php echo htmlspecialchars(
$format["id"],
); ?>" <?php echo wasSelected(
"formats",
$format["id"],
)
? "checked"
: ""; ?>>
<?php echo htmlspecialchars($format["name"]); ?>
</label>
</li>
<!-- 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; ?>
</ul>
</div>
</div>
<br>
<label for="tag">Mots-clés (max 10, séparés par des virgules)</label>
<input type="text" id="tag" name="tag" placeholder="typographie, photographie, outils libre, post-colonial..." value="<?php echo old(
"tag",
); ?>">
<br>
<small>Séparez les mots-clés par des virgules. Maximum 10 mots-clés.</small>
<label for="duration_info">Durée/Taille (si applicable)</label>
<input type="text" id="duration_info" name="duration_info" placeholder="Ex: 68 minutes, 128 pages, 78 pages + 15 minutes" value="<?php echo old(
"duration_info",
); ?>">
<br>
<small>Indiquez la durée (en minutes) ou le nombre de pages de votre TFE.</small>
<label for="lien">Lien vers un site web ou ressource en ligne</label>
<input type="url" id="lien" name="lien" placeholder="https://monmemoire.erg.be/..." value="<?php echo old(
"lien",
); ?>">
</fieldset>
<!-- 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>
<fieldset>
<legend>Fichiers</legend>
<label for="couverture">Importer une image de couverture</label>
<small>Formats acceptés : JPG, PNG. Taille max : 10MB.</small>
<input type="file" id="couverture" name="couverture" accept="image/jpeg,image/png">
<!-- 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>
<label for="files">Importer le TFE et les fichiers annexes</label>
<small>Formats acceptés : PDF, JPG, PNG, MP4, ZIP. Taille max par fichier : 50MB.</small>
<small>Si vous voulez importer un dossier, créez une archive ZIP.</small>
<input type="file" id="files" name="files[]" multiple accept=".pdf,.jpg,.jpeg,.png,.mp4,.zip">
</fieldset>
<!-- 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>
<br>
<input type="submit" name="go" value="Soumettre mon TFE">
<!-- 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>
<!-- 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'; ?>
<?php require_once APP_ROOT . '/templates/admin/footer.php'; ?>