mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
fix: mark languages as required, add required-field visual indicators on both forms
- checkbox-list.php: support $required prop → adds required + aria-required on fieldset - add.php: languages checkbox now marked required (matches server-side validation) - partage/index.php: same for student form - admin.css: dashed border on required inputs, bold labels, red asterisk via :has(), "Champs obligatoires" note - Both forms now show "* Champs obligatoires" note at top Server-side required fields = titre, auteurice, synopsis, année, orientation, ap, finality, languages (≥1), access_type_id, confirmation_email. All now have required attribute + visual asterisk.
This commit is contained in:
@@ -59,6 +59,7 @@ include APP_ROOT . '/templates/header.php';
|
||||
|
||||
|
||||
|
||||
<p class="required-note"><span class="asterisk">*</span> Champs obligatoires</p>
|
||||
<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"]) ?>">
|
||||
|
||||
@@ -107,7 +108,7 @@ include APP_ROOT . '/templates/header.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 = 'languages'; $label = 'Langue(s) :'; $options = $languages; $checked = $formData['languages'] ?? []; include APP_ROOT . '/templates/partials/form/checkbox-list.php'; ?>
|
||||
<?php $name = 'languages'; $label = 'Langue(s) :'; $options = $languages; $checked = $formData['languages'] ?? []; $required = true; 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 = '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'; ?>
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# CSS Architecture
|
||||
|
||||
## File Structure
|
||||
|
||||
- **variables.css** — all CSS custom properties (single source of truth for every color/token)
|
||||
- **common.css** — reset, header/nav, search bar, accessibility utilities (loaded on all pages)
|
||||
- **main.css** — home page
|
||||
- **search.css** — search/directory page
|
||||
- **tfe.css** — individual thesis page
|
||||
- **apropos.css** — about + licence pages
|
||||
- **system.css** — admin system dashboard
|
||||
- **admin.css** — admin section (loaded alongside `common.css` on every admin page)
|
||||
- **modern-normalize.min.css** — third-party reset (minified, do not edit)
|
||||
|
||||
## Rules
|
||||
|
||||
- Every color value lives in `variables.css` as a CSS custom property.
|
||||
- No hardcoded hex, rgb(), or rgba() in any other file.
|
||||
- All files `@import url("./variables.css")` at the top.
|
||||
- Admin and public share the same token names — no separate admin theme.
|
||||
- No dark-mode media query. System page uses the same light tokens as the rest of the admin section.
|
||||
@@ -147,6 +147,43 @@
|
||||
padding-right: 1.2rem;
|
||||
}
|
||||
|
||||
/* Required-field indicator */
|
||||
.admin-form
|
||||
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(
|
||||
[type="hidden"]
|
||||
):not([type="submit"]):required,
|
||||
.admin-form select:required,
|
||||
.admin-form textarea:required {
|
||||
border-bottom-style: dashed;
|
||||
}
|
||||
|
||||
.admin-form
|
||||
div:has(
|
||||
input:required:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="hidden"])) > label,
|
||||
.admin-form div:has(select:required) > label,
|
||||
.admin-form div:has(textarea:required) > label {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Required-field indicator (student form / generic labels) */
|
||||
label:has(+ input:required:not([type="hidden"]))::after,
|
||||
label:has(+ select:required)::after,
|
||||
label:has(+ textarea:required)::after,
|
||||
label:has(+ div > input:required)::after {
|
||||
content: " *";
|
||||
color: var(--error, #c00);
|
||||
}
|
||||
|
||||
/* Visually-hidden "required fields marked with *" note */
|
||||
.required-note {
|
||||
font-size: var(--step--2);
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: var(--space-xs);
|
||||
}
|
||||
.required-note .asterisk {
|
||||
color: var(--error, #c00);
|
||||
}
|
||||
|
||||
/* File inputs */
|
||||
.admin-file-input {
|
||||
display: flex;
|
||||
|
||||
@@ -308,6 +308,7 @@ function renderShareLinkForm(string $slug, array $link): void
|
||||
<div class="flash-success" role="alert"><?= htmlspecialchars($flashSuccess) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<p class="required-note"><span class="asterisk">*</span> Champs obligatoires</p>
|
||||
<form action="/partage/<?= urlencode($slug) ?>/submit" method="post" enctype="multipart/form-data" class="admin-form">
|
||||
<input type="hidden" name="share_link_token" value="<?= htmlspecialchars($shareCsrfToken) ?>">
|
||||
|
||||
@@ -376,7 +377,7 @@ function renderShareLinkForm(string $slug, array $link): void
|
||||
<?php $name = 'ap'; $label = 'Atelier pluridisciplinaire :'; $options = $apPrograms; $selected = isset($formData['ap']) ? $formData['ap'] : ''; $required = true; $placeholder = ''; include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
|
||||
<?php $name = 'finality'; $label = 'Finalité du master :'; $options = $finalityTypes; $selected = isset($formData['finality']) ? $formData['finality'] : ''; $required = true; $placeholder = ''; 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 = 'languages'; $label = 'Langue(s) :'; $options = $languages; $checked = $formData['languages'] ?? []; $required = true; 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 = 'tag'; $label = 'Mots-clés :'; $value = old($formData, 'tag'); $placeholder = 'sociologie, anthropologie, ...'; $hint = 'Séparez par des virgules. Max 10 mots-clés.'; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
|
||||
@@ -12,13 +12,15 @@
|
||||
* string $label — group label text
|
||||
* array $options — each element must have 'id' and 'name' keys
|
||||
* array $checked — array of 'id' values that are currently checked
|
||||
* bool $required — whether at least one checkbox must be checked; default false
|
||||
*/
|
||||
|
||||
$checked = $checked ?? [];
|
||||
$checked = $checked ?? [];
|
||||
$required = $required ?? false;
|
||||
?>
|
||||
<div>
|
||||
<span class="admin-row-label"><?= htmlspecialchars($label) ?></span>
|
||||
<fieldset class="admin-checkbox-group">
|
||||
<fieldset class="admin-checkbox-group"<?= $required ? ' required aria-required="true"' : '' ?>>
|
||||
<legend class="sr-only"><?= htmlspecialchars($label) ?></legend>
|
||||
<ul>
|
||||
<?php foreach ($options as $opt): ?>
|
||||
|
||||
Reference in New Issue
Block a user