formulaire: default interne, unpublished, contact toggle, settings section

This commit is contained in:
Pontoporeia
2026-04-15 11:57:55 +02:00
parent 67a4aaac26
commit 0cb4451218
13 changed files with 490 additions and 44 deletions

View File

@@ -0,0 +1,32 @@
<?php
require_once __DIR__ . '/../../../config/bootstrap.php';
require_once __DIR__ . '/../../../src/AdminAuth.php';
AdminAuth::requireLogin();
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|| !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
App::flash('error', "Erreur de sécurité : token invalide.");
header('Location: /admin/parametres.php');
exit;
}
require_once APP_ROOT . '/src/Database.php';
$db = new Database();
$section = $_POST['section'] ?? '';
if ($section === 'formulaire') {
// Save access-type toggle settings
$allowed = ['access_type_libre_enabled', 'access_type_interne_enabled', 'access_type_interdit_enabled'];
foreach ($allowed as $key) {
$value = isset($_POST[$key]) ? '1' : '0';
$db->setSetting($key, $value);
}
App::flash('success', "Paramètres du formulaire mis à jour.");
} else {
App::flash('error', "Section inconnue.");
}
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
header('Location: /admin/parametres.php');
exit;

View File

@@ -63,6 +63,16 @@ function wasSelected($key, $value) {
<?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'; ?>
<!-- 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 require APP_ROOT . '/templates/partials/form/jury-fieldset.php'; ?>
<?php
@@ -105,6 +115,26 @@ function wasSelected($key, $value) {
<?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'; ?>
<?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="admin-form-footer">
<button type="submit" name="go" class="admin-btn">Soumettre</button>
</div>

View File

@@ -45,7 +45,17 @@ try {
<input type="hidden" name="thesis_id" value="<?= $thesisId ?>">
<?php $name = 'auteurice'; $label = 'Auteur·ice(s) :'; $value = htmlspecialchars($thesis['authors']); $required = true; $attrs = array_merge(['autocomplete' => 'name'], $autofocusField === 'auteurice' ? ['autofocus' => true] : []); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'mail'; $label = 'Contact :'; $value = ''; $attrs = ['autocomplete' => 'email']; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<?php $name = 'mail'; $label = 'Contact :'; $value = htmlspecialchars($currentAuthorEmail ?? ''); $attrs = ['autocomplete' => 'email']; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
<!-- Contact visibility -->
<div class="admin-form-group">
<label class="admin-checkbox-label">
<input type="checkbox" name="contact_public" value="1"
<?= !empty($currentAuthorShowContact) ? 'checked' : '' ?>>
Je veux que mon contact soit accessible à toustes depuis la plateforme xamxam
</label>
<small>Si cette case est cochée, le contact apparaît sur la page publique du TFE.</small>
</div>
<?php
$name = 'année'; $label = 'Année :'; $value = htmlspecialchars((string)$thesis['year']); $required = true;

View File

@@ -9,6 +9,10 @@ $credentialsFile = APP_ROOT . '/config/admin_credentials.php';
$hasPassword = defined('ADMIN_PASSWORD_HASH');
$maintenanceOn = file_exists(APP_ROOT . '/storage/maintenance.flag');
require_once APP_ROOT . '/src/Database.php';
$db = new Database();
$siteSettings = $db->getAllSettings();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
@@ -56,7 +60,58 @@ if (empty($_SESSION['csrf_token'])) {
</section>
<!-- ══════════════════════════════════════════════════════════════
SECTION 2 — Compte administrateur
SECTION 2 — Formulaire
══════════════════════════════════════════════════════════════ -->
<section class="admin-settings-section" aria-labelledby="settings-formulaire-title">
<h2 class="admin-settings-section__title" id="settings-formulaire-title">Formulaire</h2>
<p>Options de visibilité disponibles dans le formulaire d'ajout de TFE.</p>
<p><small>L'option <strong>Libre</strong> ne sera activée qu'à partir de l'année académique prochaine.</small></p>
<form method="post" action="actions/settings.php" class="admin-form">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
<input type="hidden" name="section" value="formulaire">
<div class="admin-settings-toggles">
<label class="admin-toggle-row">
<span class="admin-toggle-label">
<strong>Interdit</strong>
<small>TFE non disponible en physique ni sur le site</small>
</span>
<input type="checkbox" name="access_type_interdit_enabled" value="1"
class="admin-toggle"
<?= ($siteSettings['access_type_interdit_enabled'] ?? '1') === '1' ? 'checked' : '' ?>>
</label>
<label class="admin-toggle-row">
<span class="admin-toggle-label">
<strong>Interne</strong>
<small>TFE accessible uniquement sur place en physique</small>
</span>
<input type="checkbox" name="access_type_interne_enabled" value="1"
class="admin-toggle"
<?= ($siteSettings['access_type_interne_enabled'] ?? '1') === '1' ? 'checked' : '' ?>>
</label>
<label class="admin-toggle-row admin-toggle-row--disabled">
<span class="admin-toggle-label">
<strong>Libre</strong>
<small>Libre accès — disponible à partir de l'année académique prochaine</small>
</span>
<input type="checkbox" name="access_type_libre_enabled" value="1"
class="admin-toggle"
<?= ($siteSettings['access_type_libre_enabled'] ?? '0') === '1' ? 'checked' : '' ?>>
</label>
</div>
<div class="admin-form-footer">
<button type="submit" class="admin-btn">Enregistrer</button>
</div>
</form>
</section>
<!-- ══════════════════════════════════════════════════════════════
SECTION 3 — Compte administrateur
══════════════════════════════════════════════════════════════ -->
<section class="admin-settings-section" aria-labelledby="settings-account-title">
<h2 class="admin-settings-section__title" id="settings-account-title">Compte administrateur</h2>

View File

@@ -1164,3 +1164,83 @@
height: 50vh;
border: 1px solid var(--border-primary);
}
/* ── Settings: formulaire toggles ──────────────────────────────────────────── */
.admin-settings-toggles {
display: flex;
flex-direction: column;
gap: var(--space-xs);
margin-bottom: var(--space-m);
}
.admin-toggle-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-m);
background: var(--bg-secondary);
border: 1px solid var(--border-primary);
border-radius: 4px;
padding: var(--space-xs) var(--space-m);
cursor: pointer;
}
.admin-toggle-row--disabled {
opacity: 0.6;
}
.admin-toggle-label {
display: flex;
flex-direction: column;
gap: 2px;
}
.admin-toggle-label strong {
font-size: var(--step-0);
}
.admin-toggle-label small {
color: var(--text-secondary);
font-size: var(--step--2);
}
/* Native checkbox styled as toggle pill */
.admin-toggle {
appearance: none;
-webkit-appearance: none;
width: 40px;
height: 22px;
background: var(--border-primary);
border-radius: 11px;
position: relative;
cursor: pointer;
flex-shrink: 0;
transition: background 0.2s;
}
.admin-toggle::after {
content: '';
position: absolute;
top: 3px;
left: 3px;
width: 16px;
height: 16px;
border-radius: 50%;
background: #fff;
transition: transform 0.2s;
}
.admin-toggle:checked {
background: var(--accent-primary);
}
.admin-toggle:checked::after {
transform: translateX(18px);
}
/* ── Form group (for checkbox inside .admin-form) ──────────────────────────── */
.admin-form-group {
display: flex;
flex-direction: column;
gap: var(--space-3xs);
}

View File

@@ -149,18 +149,42 @@ extract($ctrl->handle());
</div>
<?php endif; ?>
<?php if (!empty($data['baiu_link'])): ?>
<?php
$_contactHref = htmlspecialchars($data['baiu_link']);
$_contactLabel = preg_replace('#^https?://#i', '', rtrim($data['baiu_link'], '/'));
?>
<?php if (!empty($data['author_email']) && !empty($data['author_show_contact'])): ?>
<div>
<dt>Contact :</dt>
<dd>
<a href="<?= $_contactHref ?>" target="_blank" rel="noopener">
<?= htmlspecialchars($_contactLabel) ?>
<?php
$_contact = $data['author_email'];
$_isUrl = filter_var($_contact, FILTER_VALIDATE_URL) !== false;
$_isEmail = !$_isUrl && str_contains($_contact, '@');
if ($_isUrl):
?>
<a href="<?= htmlspecialchars($_contact) ?>" target="_blank" rel="noopener">
<?= htmlspecialchars(preg_replace('#^https?://#i', '', rtrim($_contact, '/'))) ?>
<span class="sr-only">(ouvre dans un nouvel onglet)</span>
</a>
<?php elseif ($_isEmail): ?>
<a href="mailto:<?= htmlspecialchars($_contact) ?>"><?= htmlspecialchars($_contact) ?></a>
<?php else: ?>
<?= htmlspecialchars($_contact) ?>
<?php endif; ?>
</dd>
</div>
<?php endif; ?>
<?php if (!empty($data['baiu_link'])): ?>
<?php
$_baiuHref = htmlspecialchars($data['baiu_link']);
$_baiuLabel = preg_replace('#^https?://#i', '', rtrim($data['baiu_link'], '/'));
?>
<div>
<dt>Lien :</dt>
<dd>
<a href="<?= $_baiuHref ?>" target="_blank" rel="noopener">
<?= htmlspecialchars($_baiuLabel) ?>
<span class="sr-only">(ouvre dans un nouvel onglet)</span>
</a>
</dd>
</div>
<?php endif; ?>