diff --git a/scitemcustom.php b/scitemcustom.php index 996fcff..8375929 100644 --- a/scitemcustom.php +++ b/scitemcustom.php @@ -71,6 +71,17 @@ function scitemcustom_current_owner_auth_id(PDO $db): int return (int) $stmt_owner->fetchColumn(); } +function scitemcustom_redirect(?int $itemcustom_id = null): void +{ + $location = 'scitemcustom.php'; + if ($itemcustom_id !== null && $itemcustom_id > 0) { + $location .= '#itemcustom-' . $itemcustom_id; + } + + header('Location: ' . $location); + exit; +} + $flash = auth_flash_get(); $flash_type = $flash['type'] ?? ''; $flash_message = $flash['message'] ?? ''; @@ -91,14 +102,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $submitted_csrf = $_POST['csrf_token'] ?? ''; if (!auth_validate_csrf($submitted_csrf)) { auth_flash_set('error', 'Jeton CSRF invalide.'); - header('Location: scitemcustom.php'); - exit; + scitemcustom_redirect(); } $action = $_POST['action'] ?? ''; if ($action === 'add_custom_item') { $obj_id = (int) ($_POST['obj_id'] ?? 0); + $redirect_itemcustom_id = null; if ($obj_id <= 0) { auth_flash_set('error', 'Objet invalide.'); } else { @@ -116,6 +127,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { 'owner_auth_id' => $current_owner_auth_id, 'obj_id' => $obj_id, ]); + $redirect_itemcustom_id = (int) $db->lastInsertId(); auth_flash_set('success', 'Objet ajouté dans Item Custom.'); } } catch (PDOException $e) { @@ -127,8 +139,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } } - header('Location: scitemcustom.php'); - exit; + scitemcustom_redirect($redirect_itemcustom_id); } if ($action === 'delete_custom_item') { @@ -155,8 +166,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } } - header('Location: scitemcustom.php'); - exit; + scitemcustom_redirect(); } if ($action === 'add_custom_stat') { @@ -210,12 +220,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } } - header('Location: scitemcustom.php'); - exit; + scitemcustom_redirect($itemcustom_id); } if ($action === 'update_custom_stat') { $custom_stat_id = (int) ($_POST['custom_stat_id'] ?? 0); + $itemcustom_id = (int) ($_POST['itemcustom_id'] ?? 0); $stat_id = (int) ($_POST['stat_id'] ?? 0); $sign = scitemcustom_normalize_sign($_POST['sign'] ?? '+'); $value = scitemcustom_normalize_value($_POST['value'] ?? ''); @@ -256,12 +266,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } } - header('Location: scitemcustom.php'); - exit; + scitemcustom_redirect($itemcustom_id); } if ($action === 'delete_custom_stat') { $custom_stat_id = (int) ($_POST['custom_stat_id'] ?? 0); + $itemcustom_id = (int) ($_POST['itemcustom_id'] ?? 0); if ($custom_stat_id > 0) { try { $stmt_delete = $db->prepare( @@ -286,8 +296,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } } - header('Location: scitemcustom.php'); - exit; + scitemcustom_redirect($itemcustom_id); } } @@ -672,6 +681,92 @@ $current_session_user = $_SESSION['user'] ?? ''; gap: 1rem; align-items: center; flex-wrap: wrap; + flex: 1; + min-width: 0; + } + + .custom-item-summary { + display: flex; + justify-content: space-between; + gap: 1rem; + align-items: center; + flex-wrap: wrap; + } + + .custom-item-summary-actions { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 0.75rem; + flex-wrap: wrap; + margin-left: auto; + } + + .custom-item-stats-count { + flex-shrink: 0; + } + + .item-toggle-btn { + display: inline-flex; + align-items: center; + gap: 0.55rem; + padding: 0.6rem 0.9rem; + border-radius: 999px; + border: 1px solid rgba(162, 155, 120, 0.25); + background: rgba(162, 155, 120, 0.08); + color: #fff; + font-family: 'Electrolize', sans-serif; + cursor: pointer; + transition: background 0.2s ease, border-color 0.2s ease, transform 0.2s ease; + } + + .item-toggle-btn:hover { + background: rgba(162, 155, 120, 0.14); + border-color: rgba(162, 155, 120, 0.45); + } + + .item-toggle-btn:focus-visible { + outline: none; + box-shadow: 0 0 0 3px rgba(162, 155, 120, 0.18); + } + + .item-toggle-label { + color: var(--primary); + font-size: 0.78rem; + text-transform: uppercase; + letter-spacing: 1px; + line-height: 1; + } + + .item-toggle-icon { + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 0.95rem; + line-height: 1; + transition: transform 0.2s ease; + } + + .item-toggle-btn[aria-expanded="true"] .item-toggle-icon { + transform: rotate(180deg); + } + + .custom-item-card { + scroll-margin-top: 1.5rem; + } + + .custom-item-card.is-open { + border-color: rgba(162, 155, 120, 0.35); + box-shadow: 0 0 0 1px rgba(162, 155, 120, 0.12); + } + + .custom-item-body { + display: grid; + gap: 1.25rem; + } + + .custom-item-body[hidden] { + display: none !important; } .inline-form { @@ -816,6 +911,20 @@ $current_session_user = $_SESSION['user'] ?? ''; .actions-row { justify-content: stretch; } + + .custom-item-summary { + align-items: stretch; + } + + .custom-item-summary-actions { + width: 100%; + justify-content: space-between; + } + + .item-toggle-btn { + flex: 1; + justify-content: center; + } } @@ -931,6 +1040,7 @@ $current_session_user = $_SESSION['user'] ?? ''; +
-
-
- -
- -
- - /
- UUID: +
+
+
+ +
+ +
+ + /
+ UUID: +
+ stat 1 ? 's' : ''; ?>
-
- - - - -
-
- -
-

Ajouter un bonus / malus

- -
Aucune statistique disponible. Crée d'abord des entrées dans l'onglet Stats Item.
- -
+
+ + - + - -
- - -
- -
- - -
- -
- - -
- - + - +
-
- - - - - - - - - - - - - +
StatistiqueSigneValeurUnitéAperçuActions
+ - + + + + + + - - + + + - - - - - - + - - - -
Aucune statistique configurée pour cet objet.StatistiqueSigneValeurUnitéAperçuActions
-
- - - - -
- - - - - - - - -
- - -
- - - - -
-
-
Aucune statistique configurée pour cet objet.
+ + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+
+ + + + + + +
@@ -1085,7 +1215,7 @@ $current_session_user = $_SESSION['user'] ?? ''; var emptyState = document.getElementById('item-custom-no-results'); var itemCards = Array.prototype.slice.call(document.querySelectorAll('#item-custom-list .custom-item-card')); - if (!filterInput || !resetButton || !visibleCount || !emptyState || itemCards.length === 0) { + if (itemCards.length === 0) { return; } @@ -1098,6 +1228,99 @@ $current_session_user = $_SESSION['user'] ?? ''; .trim(); } + function setCardState(card, isOpen) { + var body = card.querySelector('.custom-item-body'); + var toggleButton = card.querySelector('.item-toggle-btn'); + var toggleLabel = toggleButton ? toggleButton.querySelector('.item-toggle-label') : null; + if (!body || !toggleButton) { + return; + } + + card.classList.toggle('is-open', isOpen); + body.hidden = !isOpen; + toggleButton.setAttribute('aria-expanded', isOpen ? 'true' : 'false'); + + if (toggleLabel) { + toggleLabel.textContent = isOpen + ? (toggleButton.getAttribute('data-toggle-label-open') || 'Replier') + : (toggleButton.getAttribute('data-toggle-label-closed') || 'Déplier'); + } + } + + function closeAllCards() { + itemCards.forEach(function (card) { + setCardState(card, false); + }); + } + + function getCurrentUrlWithoutHash() { + return window.location.pathname + window.location.search; + } + + function openCard(card, options) { + var settings = options || {}; + itemCards.forEach(function (otherCard) { + setCardState(otherCard, otherCard === card); + }); + + if (settings.syncHash !== false) { + window.history.replaceState(null, '', '#' + card.id); + } + + if (settings.scrollIntoView) { + card.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + } + + function closeCard(card, options) { + var settings = options || {}; + setCardState(card, false); + + if (settings.syncHash !== false && window.location.hash === '#' + card.id) { + window.history.replaceState(null, '', getCurrentUrlWithoutHash()); + } + } + + function syncFromHash() { + var hash = window.location.hash || ''; + if (hash.indexOf('#itemcustom-') !== 0) { + closeAllCards(); + return; + } + + var targetCard = document.querySelector(hash + '.custom-item-card'); + if (!targetCard) { + closeAllCards(); + return; + } + + openCard(targetCard, { syncHash: false }); + } + + itemCards.forEach(function (card) { + var toggleButton = card.querySelector('.item-toggle-btn'); + if (!toggleButton) { + return; + } + + setCardState(card, false); + toggleButton.addEventListener('click', function () { + var isOpen = toggleButton.getAttribute('aria-expanded') === 'true'; + if (isOpen) { + closeCard(card); + } else { + openCard(card, { scrollIntoView: true }); + } + }); + }); + + syncFromHash(); + window.addEventListener('hashchange', syncFromHash); + + if (!filterInput || !resetButton || !visibleCount || !emptyState) { + return; + } + function applyFilter() { var query = normalizeValue(filterInput.value); var matches = 0;