feat: student mode support for thanks page (admin-auth only)

- add hidden student_mode field in add.php form
- pass mode=student through redirect to thanks.php in formulaire.php
- thanks.php renders clean student thank-you page (no header, centered button)
- add CSS for .thanks-student-page, .btn-new-form, .thanks-success, .thanks-error
- admin auth always required; student mode is purely UI variant on the physical machine
This commit is contained in:
Pontoporeia
2026-04-15 13:49:25 +02:00
parent c3affd2285
commit f4aba500e6
7 changed files with 254 additions and 81 deletions

View File

@@ -23,11 +23,9 @@ try {
$formData = $_SESSION['form_data'] ?? [];
unset($_SESSION['form_data']);
$autofocusField = App::consumeAutofocus();
// Flash error consumed by the flash-messages partial below.
/**
* Merge autofocus into the $attrs array for a given field.
* Only adds the attribute when $autofocusField matches $fieldName.
*/
function withAutofocus(string $fieldName, array $attrs = []): array {
global $autofocusField;
@@ -74,83 +72,147 @@ if ($studentMode) {
<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"]) ?>">
<?php if ($studentMode): ?>
<input type="hidden" name="student_mode" value="1">
<?php endif; ?>
<?php $name = 'titre'; $label = 'Titre :'; $value = old('titre'); $required = true; $attrs = withAutofocus('titre'); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'subtitle'; $label = 'Sous-titre (si applicable) :'; $value = old('subtitle'); $required = false; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'auteurice'; $label = 'Auteur·ice(s) :'; $value = old('auteurice'); $required = true; $attrs = withAutofocus('auteurice', ['autocomplete' => 'name']); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'mail'; $label = 'Contact(s) (optionnel) [mail/site/insta/etc.] :'; $value = old('mail'); $attrs = ['autocomplete' => 'email']; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<!-- ═══════════════════ Informations du TFE ═══════════════════ -->
<fieldset>
<legend>Informations du TFE</legend>
<!-- Contact visibility -->
<div class="admin-form-group">
<label class="admin-checkbox-label">
<input type="checkbox" name="contact_public" value="1"
<?= isset($formData['contact_public']) ? 'checked' : '' ?>>
Je veux que mon contact soit accessible à toustes depuis la plateforme xamxam
</label>
<small>Si cette case est cochée, votre contact apparaîtra sur la page publique de votre TFE.</small>
</div>
<?php $name = 'titre'; $label = 'Titre :'; $value = old('titre'); $required = true; $attrs = withAutofocus('titre'); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'subtitle'; $label = 'Sous-titre (si applicable) :'; $value = old('subtitle'); $required = false; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'auteurice'; $label = 'Auteur·ice(s) :'; $value = old('auteurice'); $required = true; $attrs = withAutofocus('auteurice', ['autocomplete' => 'name']); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'mail'; $label = 'Contact(s) (optionnel) [mail/site/insta/etc.] :'; $value = old('mail'); $attrs = ['autocomplete' => 'email']; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<div class="admin-form-group">
<label class="admin-checkbox-label">
<input type="checkbox" name="contact_public" value="1"
<?= isset($formData['contact_public']) ? 'checked' : '' ?>>
Je veux que mon contact soit accessible à toustes depuis la plateforme xamxam
</label>
<small>Si cette case est cochée, votre contact apparaîtra sur la page publique de votre TFE.</small>
</div>
<div>
<label for="synopsis">Synopsis :</label>
<textarea id="synopsis" name="synopsis"
rows="7" required
<?= $autofocusField === 'synopsis' ? 'autofocus' : '' ?>><?= old('synopsis') ?></textarea>
</div>
</fieldset>
<!-- ═══════════════════ Composition du jury ═══════════════════ -->
<?php require APP_ROOT . '/templates/partials/form/jury-fieldset.php'; ?>
<?php
$name = 'année'; $label = 'Année :'; $value = old('année'); $required = true;
$type = 'number';
$placeholder = date('Y');
$attrs = withAutofocus('année', ['min' => 2000, 'max' => date('Y') + 1]);
include APP_ROOT . '/templates/partials/form/text-field.php';
?>
<!-- ═══════════════════ Cadre académique ═══════════════════ -->
<fieldset>
<legend>Cadre académique</legend>
<?php $name = 'orientation'; $label = 'Orientation :'; $options = $orientations; $selected = $formData['orientation'] ?? ''; $required = true; $placeholder = ''; $attrs = withAutofocus('orientation'); include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
<?php
$name = 'année'; $label = 'Année :'; $value = old('année'); $required = true;
$type = 'number';
$placeholder = date('Y');
$attrs = withAutofocus('année', ['min' => 2000, 'max' => date('Y') + 1]);
include APP_ROOT . '/templates/partials/form/text-field.php';
?>
<?php $name = 'ap'; $label = 'Atelier pluridisciplinaire :'; $options = $apPrograms; $selected = $formData['ap'] ?? ''; $required = true; $placeholder = ''; $attrs = withAutofocus('ap'); include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
<?php $name = 'orientation'; $label = 'Orientation :'; $options = $orientations; $selected = $formData['orientation'] ?? ''; $required = true; $placeholder = ''; $attrs = withAutofocus('orientation'); include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
<?php $name = 'ap'; $label = 'Atelier pluridisciplinaire :'; $options = $apPrograms; $selected = $formData['ap'] ?? ''; $required = true; $placeholder = ''; $attrs = withAutofocus('ap'); include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
<?php $name = 'finality'; $label = 'Finalité du master :'; $options = $finalityTypes; $selected = $formData['finality'] ?? ''; $required = true; $placeholder = ''; $attrs = withAutofocus('finality'); include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
<?php $name = 'finality'; $label = 'Finalité du master :'; $options = $finalityTypes; $selected = $formData['finality'] ?? ''; $required = true; $placeholder = ''; $attrs = withAutofocus('finality'); include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
<?php $name = 'languages'; $label = 'Langue(s) :'; $options = $languages; $checked = $formData['languages'] ?? []; include APP_ROOT . '/templates/partials/form/checkbox-list.php'; ?>
<?php $name = 'formats'; $label = 'Format(s) :'; $options = $formatTypes; $checked = $formData['formats'] ?? []; include APP_ROOT . '/templates/partials/form/checkbox-list.php'; ?>
<?php $name = 'languages'; $label = 'Langue(s) :'; $options = $languages; $checked = $formData['languages'] ?? []; include APP_ROOT . '/templates/partials/form/checkbox-list.php'; ?>
<?php $name = 'tag'; $label = 'Mots-clés :'; $value = old('tag'); $placeholder = 'sociologie, anthropologie, ...'; $hint = 'Séparez par des virgules. Max 10 mots-clés.'; $attrs = withAutofocus('tag'); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
</fieldset>
<?php $name = 'formats'; $label = 'Format(s) :'; $options = $formatTypes; $checked = $formData['formats'] ?? []; include APP_ROOT . '/templates/partials/form/checkbox-list.php'; ?>
<!-- ═══════════════════ Fichiers ═══════════════════ -->
<fieldset>
<legend>Fichiers</legend>
<?php $name = 'tag'; $label = 'Mots-clés :'; $value = old('tag'); $placeholder = 'sociologie, anthropologie, ...'; $hint = 'Séparez par des virgules. Max 10 mots-clés.'; $attrs = withAutofocus('tag'); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'couverture'; $label = 'Image de couverture :'; $accept = 'image/jpeg,image/png'; $hint = 'JPG, PNG. Taille max : 10 MB.'; include APP_ROOT . '/templates/partials/form/file-field.php'; ?>
<?php $name = 'banner'; $label = 'Image bannière (accueil) :'; $accept = 'image/jpeg,image/png,image/webp'; $hint = 'JPG, PNG ou WEBP. Format paysage recommandé (4:1). Max 5 MB.'; include APP_ROOT . '/templates/partials/form/file-field.php'; ?>
<?php $name = 'files'; $label = 'Fichiers du TFE :'; $accept = '.pdf,.jpg,.jpeg,.png,.mp4,.zip,.vtt'; $hint = 'PDF, JPG, PNG, MP4, ZIP. Max 50 MB par fichier. Pour les vidéos, un fichier .vtt de sous-titres peut être joint (il sera associé automatiquement à la vidéo correspondante).'; $multiple = true; include APP_ROOT . '/templates/partials/form/file-field.php'; ?>
</fieldset>
<!-- Synopsis -->
<div>
<label for="synopsis">Synopsis :</label>
<textarea id="synopsis" name="synopsis"
rows="7" required
<?= $autofocusField === 'synopsis' ? 'autofocus' : '' ?>><?= old('synopsis') ?></textarea>
</div>
<!-- ═══════════════════ Métadonnées complémentaires ═══════════════════ -->
<fieldset>
<legend>Métadonnées complémentaires</legend>
<?php $name = 'license_id'; $label = 'Licence :'; $options = $licenseTypes; $selected = $formData['license_id'] ?? ''; $placeholder = '— Inconnue —'; include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
<?php $name = 'license_id'; $label = 'Licence :'; $options = $licenseTypes; $selected = $formData['license_id'] ?? ''; $placeholder = '— Inconnue —'; include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
<?php $name = 'duration_info'; $label = 'Durée / Taille :'; $value = old('duration_info'); $placeholder = 'Ex : 84 pages'; $hint = 'Durée (minutes) ou nombre de pages.'; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'duration_info'; $label = 'Durée / Taille :'; $value = old('duration_info'); $placeholder = 'Ex : 84 pages'; $hint = 'Durée (minutes) ou nombre de pages.'; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'lien'; $label = 'Lien (site / ressource) :'; $value = old('lien'); $type = 'url'; $placeholder = 'https://...'; $attrs = withAutofocus('lien'); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'lien'; $label = 'Lien (site / ressource) :'; $value = old('lien'); $type = 'url'; $placeholder = 'https://...'; $attrs = withAutofocus('lien'); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'couverture'; $label = 'Image de couverture :'; $accept = 'image/jpeg,image/png'; $hint = 'JPG, PNG. Taille max : 10 MB.'; include APP_ROOT . '/templates/partials/form/file-field.php'; ?>
<?php
$accessOptions = array_map(function($at) {
return ['id' => $at['id'], 'name' => $at['name']];
}, $enabledAccessTypes);
$defaultAccessType = 2;
$selectedAccessType = isset($formData['access_type_id'])
? (int)$formData['access_type_id']
: $defaultAccessType;
$name = 'access_type_id';
$label = 'Visibilité / Accès :';
$options = $accessOptions;
$selected = $selectedAccessType;
$placeholder = null;
$required = true;
$attrs = [];
include APP_ROOT . '/templates/partials/form/select-field.php';
?>
</fieldset>
<?php $name = 'banner'; $label = 'Image bannière (accueil) :'; $accept = 'image/jpeg,image/png,image/webp'; $hint = 'JPG, PNG ou WEBP. Format paysage recommandé (4:1). Max 5 MB.'; include APP_ROOT . '/templates/partials/form/file-field.php'; ?>
<?php if ($studentMode): ?>
<!-- ═══════════════════ Degrés d'ouverture ═══════════════════ -->
<fieldset class="licence-explanation">
<legend>Degrés d'ouverture et licences</legend>
<?php $name = 'files'; $label = 'Fichiers du TFE :'; $accept = '.pdf,.jpg,.jpeg,.png,.mp4,.zip,.vtt'; $hint = 'PDF, JPG, PNG, MP4, ZIP. Max 50 MB par fichier. Pour les vidéos, un fichier .vtt de sous-titres peut être joint (il sera associé automatiquement à la vidéo correspondante).'; $multiple = true; include APP_ROOT . '/templates/partials/form/file-field.php'; ?>
<div class="licence-info">
<h3>Je veux que mon TFE soit disponible sous les conditions suivantes :</h3>
<?php
// Visibility select — only show options enabled in settings
$accessOptions = array_map(function($at) {
return ['id' => $at['id'], 'name' => $at['name']];
}, $enabledAccessTypes);
// Default: Interne (id=2)
$defaultAccessType = 2;
$selectedAccessType = isset($formData['access_type_id'])
? (int)$formData['access_type_id']
: $defaultAccessType;
$name = 'access_type_id';
$label = 'Visibilité / Accès :';
$options = $accessOptions;
$selected = $selectedAccessType;
$placeholder = null;
$required = true;
$attrs = [];
include APP_ROOT . '/templates/partials/form/select-field.php';
?>
<div class="licence-degree">
<h4>🔓 Libre</h4>
<p>Mon TFE est en libre accès à tout le monde sur la plateforme des TFE ainsi que dans la bibliothèque de l'erg. Je suis conscient·e des responsabilités et obligations légales qui viennent avec une diffusion externe et acquiesce avoir lu la documentation prévue à cet effet par l'erg, ainsi qu'avoir discuté des enjeux d'une publication avec l'équipe pédagogique. J'accepte de partager mes droits de diffusion avec l'erg, ce uniquement dans le cadre d'une diffusion sur la plateforme xamxam.</p>
<ul>
<li><label><input type="checkbox" name="cc4r" value="1"> J'accepte les conditions collectives de réutilisation (CC4r) <em class="hint">(pas obligatoire)</em></label></li>
<li><label><input type="checkbox" name="specific_license" value="1"> Je souhaite appliquer une licence spécifique à mon travail <em class="hint">(pas obligatoire)</em></label></li>
</ul>
<p class="licence-note"><em>Au moins une des deux cases doit être cochée pour le degré Libre.</em></p>
</div>
<div class="licence-degree">
<h4>🔒 Interne</h4>
<p>Mon TFE et ma note d'intention ne sont accessibles que sur place en physique ainsi que sur la plateforme xamxam par la communauté erg. Une note descriptive est disponible sur le site à toustes. J'autorise une (ré-)utilisation et diffusion dans un contexte académique et didactique au sein de l'erg.</p>
<p class="licence-note"><em>La diffusion limitée est protégée par le cadre académique/didactique, le travail pourrait donc être diffusé en interne et être cité par d'autres étudiant·es sans implications légales pour l'auteur·ice ni pour l'école.</em></p>
<ul>
<li><label><input type="checkbox" name="cc4r" value="1"> J'accepte les conditions collectives de réutilisation (CC4r) <em class="hint">(pas obligatoire)</em></label></li>
<li><label><input type="checkbox" name="specific_license" value="1"> Je souhaite appliquer une licence spécifique à mon travail <em class="hint">(pas obligatoire)</em></label></li>
</ul>
<p class="licence-note"><em>Au moins une des deux cases doit être cochée.</em></p>
</div>
<div class="licence-degree">
<h4>🚫 Interdit</h4>
<p>Mon TFE n'est pas disponible en physique ni sur le site. Une note descriptive est disponible sur le site.</p>
</div>
</div>
<div class="licence-generalites">
<h3>Généralités</h3>
<ul>
<li>L'auteur·ice peut décider entre trois degrés de partage de son travail : <strong>libre</strong>, <strong>interne</strong>, <strong>interdit</strong>.</li>
<li>L'auteur·ice peut, à tout moment, décider de <strong>restreindre</strong> le degré d'accès à son travail. Il ne peut néanmoins pas l'ouvrir davantage.</li>
<li>Le choix effectué dans ce formulaire sera d'application <strong>une semaine après la soutenance orale</strong> de l'auteur·ice. Celui-ci peut donc décider de restreindre ce choix avant sa publication (mais pas l'ouvrir).</li>
<li>L'erg se réserve le droit de restreindre le degré d'ouverture du TFE ce en accord avec le règlement.</li>
<li>Dans tous les cas, l'auteur·ice garde les droits d'auteurs, de diffusion, d'utilisation, etc. de son travail sauf si la licence choisie restreindrait ses droits.</li>
<li>La diffusion « xamxam » est indépendante de la diffusion à la BAIU.</li>
</ul>
</div>
</fieldset>
<?php endif; ?>
<div class="form-footer">
<button type="submit" name="go">Soumettre</button>