From 3b20de71b5a4c5b5e45449c7be4225a761d71a56 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Wed, 6 May 2026 23:34:35 +0000 Subject: [PATCH] Autosave: 20260506-233434 --- db/scitemcustom.php | 8 +--- db/scmanutention.php | 34 ++++++++++++++ scitemcustom.php | 100 ++++++++++++++++++++++++++++++++++------ scmanutention.php | 106 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 223 insertions(+), 25 deletions(-) diff --git a/db/scitemcustom.php b/db/scitemcustom.php index 4e3d04c..49302a1 100644 --- a/db/scitemcustom.php +++ b/db/scitemcustom.php @@ -59,7 +59,6 @@ function scitemcustom_bootstrap(): void cl_scitemcustom_obj_id INT(10) UNSIGNED NOT NULL, cl_scitemcustom_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (cl_scitemcustom_id), - UNIQUE KEY uq_scitemcustom_owner_obj (cl_scitemcustom_owner_auth_id, cl_scitemcustom_obj_id), KEY idx_scitemcustom_owner (cl_scitemcustom_owner_auth_id), KEY idx_scitemcustom_obj (cl_scitemcustom_obj_id), CONSTRAINT fk_scitemcustom_owner_auth FOREIGN KEY (cl_scitemcustom_owner_auth_id) @@ -91,11 +90,8 @@ function scitemcustom_bootstrap(): void ); } - if (!scitemcustom_index_exists($db, 'tbl_scitemcustom', 'uq_scitemcustom_owner_obj')) { - $db->exec( - 'ALTER TABLE tbl_scitemcustom - ADD UNIQUE KEY uq_scitemcustom_owner_obj (cl_scitemcustom_owner_auth_id, cl_scitemcustom_obj_id)' - ); + if (scitemcustom_index_exists($db, 'tbl_scitemcustom', 'uq_scitemcustom_owner_obj')) { + $db->exec('ALTER TABLE tbl_scitemcustom DROP INDEX uq_scitemcustom_owner_obj'); } if (!scitemcustom_foreign_key_exists($db, 'tbl_scitemcustom', 'fk_scitemcustom_owner_auth')) { diff --git a/db/scmanutention.php b/db/scmanutention.php index 3b33803..e0ce0a9 100644 --- a/db/scmanutention.php +++ b/db/scmanutention.php @@ -760,3 +760,37 @@ function scmanutention_fetch_custom_stats_map(PDO $db, array $item_rows): array return $stats_map; } + +function scmanutention_fetch_custom_stats_preview_map(PDO $db, array $custom_ids): array +{ + $custom_ids = array_values(array_unique(array_map('intval', array_filter($custom_ids)))); + if ($custom_ids === []) { + return []; + } + + $placeholders = implode(',', array_fill(0, count($custom_ids), '?')); + $stmt = $db->prepare( + "SELECT + cs.cl_scitemcustomstat_itemcustom_id, + st.cl_scstatsitem_name, + st.cl_scstatsitem_unit, + cs.cl_scitemcustomstat_sign, + cs.cl_scitemcustomstat_value + FROM tbl_scitemcustomstat cs + INNER JOIN tbl_scstatsitem st ON st.cl_scstatsitem_id = cs.cl_scitemcustomstat_stat_id + WHERE cs.cl_scitemcustomstat_itemcustom_id IN ({$placeholders}) + ORDER BY st.cl_scstatsitem_name ASC, cs.cl_scitemcustomstat_id ASC" + ); + $stmt->execute($custom_ids); + + $stats_map = []; + foreach ($stmt->fetchAll() as $row) { + $itemcustom_id = (int) $row['cl_scitemcustomstat_itemcustom_id']; + if (!isset($stats_map[$itemcustom_id])) { + $stats_map[$itemcustom_id] = []; + } + $stats_map[$itemcustom_id][] = $row; + } + + return $stats_map; +} diff --git a/scitemcustom.php b/scitemcustom.php index 77ac88d..e1f7f79 100644 --- a/scitemcustom.php +++ b/scitemcustom.php @@ -55,6 +55,35 @@ function scitemcustom_escape_like(string $value): string ]); } +function scitemcustom_normalize_rarity(?string $rarity): string +{ + return strtoupper(trim((string) $rarity)); +} + +function scitemcustom_rarity_class(?string $rarity): string +{ + return match (scitemcustom_normalize_rarity($rarity)) { + 'L' => 'rarity-L', + 'E' => 'rarity-E', + 'R' => 'rarity-R', + 'U' => 'rarity-U', + 'C' => 'rarity-C', + default => '', + }; +} + +function scitemcustom_rarity_label(?string $rarity): string +{ + return match (scitemcustom_normalize_rarity($rarity)) { + 'L' => 'Légendaire', + 'E' => 'Épique', + 'R' => 'Rare', + 'U' => 'Peu commun', + 'C' => 'Commun', + default => '', + }; +} + function scitemcustom_search_available_items(PDO $db, int $ownerAuthId, string $query, ?int $limit = null): array { $query = trim($query); @@ -71,14 +100,9 @@ function scitemcustom_search_available_items(PDO $db, int $ownerAuthId, string $ $limitClause = ' LIMIT ' . (int) $limit; } - $sql = "SELECT cl_scobjs_id, cl_scobjs_name, cl_scobjs_uuid, cl_scobjs_type, cl_scobjs_subtype + $sql = "SELECT cl_scobjs_id, cl_scobjs_name, cl_scobjs_uuid, cl_scobjs_type, cl_scobjs_subtype, cl_scobjs_rarity FROM tbl_scobjs - WHERE cl_scobjs_id NOT IN ( - SELECT cl_scitemcustom_obj_id - FROM tbl_scitemcustom - WHERE cl_scitemcustom_owner_auth_id = :owner_auth_id - ) - AND ( + WHERE ( cl_scobjs_name LIKE :contains_name OR cl_scobjs_type LIKE :contains_type OR cl_scobjs_subtype LIKE :contains_subtype @@ -101,7 +125,6 @@ function scitemcustom_search_available_items(PDO $db, int $ownerAuthId, string $ $stmt = $db->prepare($sql); $stmt->execute([ - 'owner_auth_id' => $ownerAuthId, 'contains_name' => $contains, 'contains_type' => $contains, 'contains_subtype' => $contains, @@ -379,12 +402,17 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET' && (string) ($_GET['ajax'] ?? '') === ' if (mb_strlen($query) >= 3) { $items = array_map(static function (array $row): array { + $rarity = (string) ($row['cl_scobjs_rarity'] ?? ''); + return [ 'id' => (int) $row['cl_scobjs_id'], 'name' => (string) $row['cl_scobjs_name'], 'uuid' => (string) $row['cl_scobjs_uuid'], 'type' => (string) $row['cl_scobjs_type'], 'subtype' => (string) ($row['cl_scobjs_subtype'] ?? ''), + 'rarity' => scitemcustom_normalize_rarity($rarity), + 'rarity_class' => scitemcustom_rarity_class($rarity), + 'rarity_label' => scitemcustom_rarity_label($rarity), ]; }, scitemcustom_search_available_items($db, $current_owner_auth_id, $query)); } @@ -452,6 +480,11 @@ $current_session_user = $_SESSION['user'] ?? ''; --border-glow: rgba(162, 155, 120, 0.25); --danger: #ff4d4d; --success: #00ff88; + --rarity-L: #ff8000; + --rarity-E: #a335ee; + --rarity-R: #0070dd; + --rarity-U: #1eff00; + --rarity-C: #ffffff; } @font-face { @@ -850,6 +883,12 @@ $current_session_user = $_SESSION['user'] ?? ''; font-size: 0.92rem; } + .rarity-L { color: var(--rarity-L); text-shadow: 0 0 12px rgba(255, 128, 0, 0.28); } + .rarity-E { color: var(--rarity-E); text-shadow: 0 0 12px rgba(163, 53, 238, 0.28); } + .rarity-R { color: var(--rarity-R); text-shadow: 0 0 12px rgba(0, 112, 221, 0.28); } + .rarity-U { color: var(--rarity-U); text-shadow: 0 0 12px rgba(30, 255, 0, 0.28); } + .rarity-C { color: var(--rarity-C); } + .item-submeta { color: #96a0b5; font-size: 0.78rem; @@ -1227,7 +1266,8 @@ $current_session_user = $_SESSION['user'] ?? '';
- + +
/ @@ -1303,10 +1343,13 @@ $current_session_user = $_SESSION['user'] ?? '';
- + + +
- /
+ / + — Rareté :
UUID:
@@ -1476,6 +1519,7 @@ $current_session_user = $_SESSION['user'] ?? ''; var addSubmit = document.getElementById('item-add-submit'); var addReset = document.getElementById('item-add-reset'); var addClear = document.getElementById('item-add-clear'); + var pickerRarityClasses = ['rarity-L', 'rarity-E', 'rarity-R', 'rarity-U', 'rarity-C']; var pickerRequestTimer = null; var pickerRequestToken = 0; var selectedItem = null; @@ -1524,6 +1568,20 @@ $current_session_user = $_SESSION['user'] ?? ''; setPickerExpanded(true); } + function applyRarityClass(element, rarityClass) { + if (!element) { + return; + } + + pickerRarityClasses.forEach(function (className) { + element.classList.remove(className); + }); + + if (rarityClass && pickerRarityClasses.indexOf(rarityClass) !== -1) { + element.classList.add(rarityClass); + } + } + function updateSelectedItem(item) { selectedItem = item || null; @@ -1537,6 +1595,7 @@ $current_session_user = $_SESSION['user'] ?? ''; addSelection.classList.add('hidden-by-filter'); addSelectionName.textContent = ''; addSelectionMeta.textContent = ''; + applyRarityClass(addSelectionName, ''); addSelectionImage.classList.add('hidden-by-filter'); addSelectionImage.setAttribute('src', ''); addSelectionImage.setAttribute('alt', ''); @@ -1547,6 +1606,7 @@ $current_session_user = $_SESSION['user'] ?? ''; addSubmit.disabled = !addSelectedIdInput.value; addSelection.classList.remove('hidden-by-filter'); addSelectionName.textContent = selectedItem.name || ''; + applyRarityClass(addSelectionName, selectedItem.rarityClass || ''); var meta = selectedItem.type || ''; if (selectedItem.subtype) { @@ -1555,6 +1615,9 @@ $current_session_user = $_SESSION['user'] ?? ''; if (selectedItem.uuid) { meta += (meta ? ' — ' : '') + selectedItem.uuid; } + if (selectedItem.rarityLabel) { + meta += (meta ? ' — ' : '') + 'Rareté : ' + selectedItem.rarityLabel; + } addSelectionMeta.textContent = meta; if (selectedItem.uuid) { @@ -1585,10 +1648,16 @@ $current_session_user = $_SESSION['user'] ?? ''; meta += (meta ? ' / ' : '') + escapeHtml(item.subtype); } + var rarityClass = item.rarity_class || ''; + var rarityLabel = item.rarity_label || ''; + if (rarityLabel) { + meta += (meta ? ' — ' : '') + 'Rareté : ' + escapeHtml(rarityLabel); + } + return '' + - ''; @@ -1683,7 +1752,10 @@ $current_session_user = $_SESSION['user'] ?? ''; name: option.getAttribute('data-item-name') || '', type: option.getAttribute('data-item-type') || '', subtype: option.getAttribute('data-item-subtype') || '', - uuid: option.getAttribute('data-item-uuid') || '' + uuid: option.getAttribute('data-item-uuid') || '', + rarity: option.getAttribute('data-item-rarity') || '', + rarityClass: option.getAttribute('data-item-rarity-class') || '', + rarityLabel: option.getAttribute('data-item-rarity-label') || '' }; addSearchInput.value = item.name || ''; diff --git a/scmanutention.php b/scmanutention.php index 2216a13..3f2d349 100644 --- a/scmanutention.php +++ b/scmanutention.php @@ -133,20 +133,37 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET' && (string) ($_GET['ajax'] ?? '') === ' header('Content-Type: application/json; charset=utf-8'); $query = trim((string) ($_GET['q'] ?? '')); - $items = array_map(static function (array $row): array { + $suggestion_rows = scmanutention_search_available_items($db, $current_owner_auth_id, $query, 14); + $suggestion_custom_ids = []; + + foreach ($suggestion_rows as $row) { + if (((string) ($row['result_source'] ?? '')) === 'custom' && !empty($row['result_scitemcustom_id'])) { + $suggestion_custom_ids[] = (int) $row['result_scitemcustom_id']; + } + } + + $suggestion_stats_map = scmanutention_fetch_custom_stats_preview_map($db, $suggestion_custom_ids); + + $items = array_map(static function (array $row) use ($suggestion_stats_map): array { + $custom_id = (int) ($row['result_scitemcustom_id'] ?? 0); + $custom_stats = $custom_id > 0 ? ($suggestion_stats_map[$custom_id] ?? []) : []; + $stats_preview = array_map('scmanutention_format_stat_preview', array_slice($custom_stats, 0, 4)); + return [ 'key' => (string) $row['result_key'], 'source' => (string) $row['result_source'], 'sourceLabel' => ((string) $row['result_source']) === 'custom' ? 'Objet perso' : 'Base d\'objets', 'scobjs_id' => (int) ($row['result_scobjs_id'] ?? 0), - 'scitemcustom_id' => (int) ($row['result_scitemcustom_id'] ?? 0), + 'scitemcustom_id' => $custom_id, 'name' => (string) ($row['result_name'] ?? ''), 'type' => (string) ($row['result_type'] ?? ''), 'subtype' => (string) ($row['result_subtype'] ?? ''), 'uuid' => (string) ($row['result_uuid'] ?? ''), 'rarity' => (string) ($row['result_rarity'] ?? ''), + 'statsPreview' => $stats_preview, + 'statsPreviewMore' => max(0, count($custom_stats) - count($stats_preview)), ]; - }, scmanutention_search_available_items($db, $current_owner_auth_id, $query, 14)); + }, $suggestion_rows); echo json_encode(['items' => $items], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; @@ -813,6 +830,56 @@ $page_access_widget = auth_render_page_access_widget('scmanutention.php', 'Manut cursor: pointer; } + .picker-option-row { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 0.8rem; + align-items: start; + } + + .picker-option-main { + min-width: 0; + display: grid; + gap: 0.3rem; + } + + .picker-option-stats { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + align-items: flex-start; + gap: 0.35rem; + max-width: min(48%, 420px); + } + + .picker-option-stats .stat-pill { + min-height: 26px; + padding: 0.28rem 0.55rem; + font-size: 0.74rem; + white-space: nowrap; + } + + .picker-option-stats-empty { + align-self: center; + color: var(--text-soft); + font-size: 0.82rem; + white-space: nowrap; + } + + .picker-option-more { + display: inline-flex; + align-items: center; + min-height: 26px; + padding: 0.28rem 0.55rem; + border-radius: 12px; + background: rgba(255,255,255,0.08); + border: 1px solid rgba(255,255,255,0.14); + color: var(--text-soft); + font-size: 0.74rem; + font-weight: 700; + white-space: nowrap; + } + .picker-option:hover, .picker-option.is-active { background: rgba(255, 255, 255, 0.07); @@ -975,6 +1042,15 @@ $page_access_widget = auth_render_page_access_widget('scmanutention.php', 'Manut grid-template-columns: 1fr; } + .picker-option-row { + grid-template-columns: 1fr; + } + + .picker-option-stats { + justify-content: flex-start; + max-width: 100%; + } + .picker-selection, .item-head, .hero-title-row, @@ -1527,6 +1603,21 @@ $page_access_widget = auth_render_page_access_widget('scmanutention.php', 'Manut meta.push(escapeHtml(item.sourceLabel)); } + var statsPreview = Array.isArray(item.statsPreview) ? item.statsPreview : []; + var statsHtml = ''; + if ((item.source || '') === 'custom') { + if (statsPreview.length > 0) { + statsHtml = '
' + + statsPreview.map(function (statText) { + return '' + escapeHtml(statText) + ''; + }).join('') + + ((item.statsPreviewMore || 0) > 0 ? '+' + escapeHtml(item.statsPreviewMore) + '' : '') + + '
'; + } else { + statsHtml = '
Aucune stat
'; + } + } + return '' + ''; }).join(''); showDropdown();