mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-26 00:29:18 +02:00
Refactor apropos/charte/licence pages: shared layout, TOC anchors, and UI polish
Unify the three public pages (à propos, charte, licence) onto a single grid layout (.page-content) with sticky TOC sidebar, replacing the old separate / / markup. - Merge about.php, charte.php, licence.php templates into shared .page-content / .content-section structure - Add CommonMark HeadingPermalinkExtension for stable heading anchors - Use SlugNormalizer for TOC links so they match rendered heading IDs - Standardize link styling across content blocks: bold black, accent on hover (consistent with global link style) - Fix code block wrapping: use pre-wrap instead of pre, constrain grid columns with min-width:0, auto scrollbar - Fix apropos page grid placement: force content-section into column 2 so contacts and credits stay in the content area, not the sidebar Also includes accumulated WIP changes: - Header gradient: hardcoded purple-to-green (replaces CSS variables) - Search placeholder font - Duration field: replace minutes/sec/heures with h:m:s time inputs - TFE file optional for formats 1,4,6 with client-side JS toggle - Licence form: em-dash to hyphen, details/summary classes - Pill search: block Enter key form submission when no results - Draft autosave: remove CSRF rotation (broke concurrent FilePond uploads) - Language pill: clear hints for excluded main languages - Search results: gradient placeholder cards for items without covers - TFE display: format durée values as XhYm instead of decimal
This commit is contained in:
@@ -418,37 +418,71 @@ if ($filesMode === 'add'): ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- ═══════════════════ Durée ═══════════════════ -->
|
||||
<fieldset>
|
||||
<?php
|
||||
$_durRaw = $durationValue ?? ($formData['duration_value'] ?? null);
|
||||
$_durUnit = $durationUnit ?? ($formData['duration_unit'] ?? 'pages');
|
||||
$_durFloat = $_durRaw !== null && $_durRaw !== '' ? (float)$_durRaw : null;
|
||||
// Pre-split stored hours into h/m/s for the time-input fields
|
||||
$_durH = '';
|
||||
$_durM = '';
|
||||
$_durS = '';
|
||||
if ($_durFloat !== null && $_durUnit === 'durée') {
|
||||
$_durH = (int)floor($_durFloat);
|
||||
$_remaining = round(($_durFloat - $_durH) * 3600);
|
||||
$_durM = (int)floor($_remaining / 60);
|
||||
$_durS = $_remaining % 60;
|
||||
$_durH = (string)$_durH;
|
||||
$_durM = (string)$_durM;
|
||||
$_durS = (string)$_durS;
|
||||
}
|
||||
?>
|
||||
<fieldset id="duration-fieldset">
|
||||
<legend>Durée</legend>
|
||||
<div class="admin-form-group admin-form-group--inline">
|
||||
<div class="admin-form-group">
|
||||
<div>
|
||||
<label for="duration_unit">Unité :</label>
|
||||
<select id="duration_unit" name="duration_unit">
|
||||
<?php
|
||||
$_currentUnit = $durationUnit ?? ($formData['duration_unit'] ?? 'pages');
|
||||
$_units = [
|
||||
'pages' => 'pages',
|
||||
'minutes' => 'minutes',
|
||||
'sec' => 'secondes',
|
||||
'heures' => 'heures',
|
||||
'mo' => 'Mo',
|
||||
'durée' => 'durée (h:m:s)',
|
||||
];
|
||||
foreach ($_units as $_val => $_label): ?>
|
||||
<option value="<?= $_val ?>" <?= $_currentUnit === $_val ? 'selected' : '' ?>><?= htmlspecialchars($_label) ?></option>
|
||||
<?php endforeach; unset($_units, $_currentUnit, $_val, $_label); ?>
|
||||
<option value="<?= $_val ?>" <?= $_durUnit === $_val ? 'selected' : '' ?>><?= htmlspecialchars($_label) ?></option>
|
||||
<?php endforeach; unset($_units, $_val, $_label); ?>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="duration_value">Valeur :</label>
|
||||
<input type="number" id="duration_value" name="duration_value"
|
||||
value="<?= htmlspecialchars((string)($durationValue ?? ($formData['duration_value'] ?? ''))) ?>"
|
||||
step="0.1" min="0" placeholder="0"
|
||||
<!-- Integer input for pages / Mo -->
|
||||
<div id="duration-value-integer"<?= $_durUnit === 'durée' ? ' style="display:none"' : '' ?>>
|
||||
<label for="duration_value_int">Valeur :</label>
|
||||
<input type="number" id="duration_value_int"
|
||||
value="<?= htmlspecialchars($_durUnit !== 'durée' ? (string)($_durFloat ?? '') : '') ?>"
|
||||
step="1" min="0" placeholder="0"
|
||||
style="width: 8ch;">
|
||||
</div>
|
||||
<!-- Time inputs for durée -->
|
||||
<div id="duration-value-time" class="duration-time-inputs"<?= $_durUnit !== 'durée' ? ' style="display:none"' : '' ?>>
|
||||
<label>Durée :</label>
|
||||
<span class="duration-time-fields">
|
||||
<input type="number" id="duration_h" value="<?= htmlspecialchars($_durH) ?>"
|
||||
step="1" min="0" placeholder="0" style="width: 5ch;" aria-label="Heures">
|
||||
<span>h</span>
|
||||
<input type="number" id="duration_m" value="<?= htmlspecialchars($_durM) ?>"
|
||||
step="1" min="0" max="59" placeholder="0" style="width: 5ch;" aria-label="Minutes">
|
||||
<span>m</span>
|
||||
<input type="number" id="duration_s" value="<?= htmlspecialchars($_durS) ?>"
|
||||
step="1" min="0" max="59" placeholder="0" style="width: 5ch;" aria-label="Secondes">
|
||||
<span>s</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<small>Optionnel. Exemples : 88 pages, 32 minutes, 1.5 heures, 120 Mo.</small>
|
||||
</div>
|
||||
<!-- Hidden field: always submitted, populated by JS on unit change / submit -->
|
||||
<input type="hidden" id="duration_value" name="duration_value"
|
||||
value="<?= htmlspecialchars((string)($_durFloat ?? '')) ?>">
|
||||
<small>Optionnel. Exemples : 88 pages, 120 Mo, 1h30.</small>
|
||||
</fieldset>
|
||||
<?php unset($_durRaw, $_durUnit, $_durFloat, $_durH, $_durM, $_durS, $_remaining); ?>
|
||||
|
||||
<!-- ═══════════════════ Degrés d'ouverture et licences ═══════════════════ -->
|
||||
<?php
|
||||
@@ -607,3 +641,47 @@ if ($filesMode === 'add'): ?>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var unit = document.getElementById('duration_unit');
|
||||
var hidden = document.getElementById('duration_value');
|
||||
var intWrap = document.getElementById('duration-value-integer');
|
||||
var intInput = document.getElementById('duration_value_int');
|
||||
var timeWrap = document.getElementById('duration-value-time');
|
||||
var hInput = document.getElementById('duration_h');
|
||||
var mInput = document.getElementById('duration_m');
|
||||
var sInput = document.getElementById('duration_s');
|
||||
if (!unit || !hidden) return;
|
||||
|
||||
function updateHidden() {
|
||||
if (unit.value === 'durée') {
|
||||
var h = parseInt(hInput.value, 10) || 0;
|
||||
var m = parseInt(mInput.value, 10) || 0;
|
||||
var s = parseInt(sInput.value, 10) || 0;
|
||||
var total = h + m / 60 + s / 3600;
|
||||
hidden.value = total > 0 ? total.toFixed(6) : '';
|
||||
} else {
|
||||
hidden.value = intInput.value;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleFields() {
|
||||
if (unit.value === 'durée') {
|
||||
intWrap.style.display = 'none';
|
||||
timeWrap.style.display = '';
|
||||
} else {
|
||||
timeWrap.style.display = 'none';
|
||||
intWrap.style.display = '';
|
||||
}
|
||||
updateHidden();
|
||||
}
|
||||
|
||||
unit.addEventListener('change', toggleFields);
|
||||
if (intInput) intInput.addEventListener('input', updateHidden);
|
||||
if (hInput) hInput.addEventListener('input', updateHidden);
|
||||
if (mInput) mInput.addEventListener('input', updateHidden);
|
||||
if (sInput) sInput.addEventListener('input', updateHidden);
|
||||
toggleFields();
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user