diff --git a/index.php b/index.php index 581a409..547a1b1 100644 --- a/index.php +++ b/index.php @@ -62,6 +62,7 @@ $session_cl_auth_user = isset($_SESSION['user']) ? (string) $_SESSION['user'] : $session_cl_auth_right = isset($_SESSION['role']) ? (string) $_SESSION['role'] : ''; $is_authenticated = $session_cl_auth_user !== ''; $has_member_access = $is_authenticated && in_array($session_cl_auth_right, ['member', 'admin'], true); +$has_vanilla_db_access = $is_authenticated && in_array($session_cl_auth_right, ['member', 'moderator', 'admin'], true); $scan_reference_rows = []; $scan_reference_max_occurrence = 0; @@ -72,6 +73,18 @@ $ship_preset_error = null; $item_custom_public_rows = []; $item_custom_public_types = []; $item_custom_public_error = null; +$vanilla_db_rows = []; +$vanilla_db_error = null; +$vanilla_db_search = ''; +$vanilla_db_per_page = 10; +$vanilla_db_total_rows = 0; +$vanilla_db_total_pages = 1; +$vanilla_db_current_page = 1; +$vanilla_db_result_start = 0; +$vanilla_db_result_end = 0; +$vanilla_db_base_query = ['open_modal' => 'vanilla-db']; +$vanilla_db_reset_url = 'index.php?open_modal=vanilla-db'; +$should_open_vanilla_db_modal = false; try { $db = db(); @@ -261,6 +274,99 @@ if ($has_member_access) { $item_custom_public_error = 'Impossible de charger les objets Item Custom pour le moment.'; } } + +if ($has_vanilla_db_access) { + $vanilla_db_search = trim((string) ($_GET['vanilla_search'] ?? '')); + $vanilla_db_current_page = max(1, (int) ($_GET['vanilla_page'] ?? 1)); + $should_open_vanilla_db_modal = ( + (isset($_GET['open_modal']) && (string) $_GET['open_modal'] === 'vanilla-db') + || $vanilla_db_search !== '' + || isset($_GET['vanilla_page']) + ); + + $vanilla_db_base_query = ['open_modal' => 'vanilla-db']; + if ($vanilla_db_search !== '') { + $vanilla_db_base_query['vanilla_search'] = $vanilla_db_search; + } + $vanilla_db_reset_url = 'index.php?' . http_build_query(['open_modal' => 'vanilla-db']); + + try { + if (!isset($db) || !($db instanceof PDO)) { + $db = db(); + } + + $vanilla_db_where_sql = ''; + $vanilla_db_bindings = []; + + if ($vanilla_db_search !== '') { + $vanilla_db_where_sql = " + WHERE ( + cl_scobjs_name LIKE :vanilla_search + OR cl_scobjs_type LIKE :vanilla_search + OR cl_scobjs_subtype LIKE :vanilla_search + OR cl_scobjs_uuid LIKE :vanilla_search + OR cl_scobjs_rarity LIKE :vanilla_search + )"; + $vanilla_db_bindings[':vanilla_search'] = '%' . $vanilla_db_search . '%'; + } + + $stmt_vanilla_db_count = $db->prepare( + "SELECT COUNT(*) + FROM tbl_scobjs" . $vanilla_db_where_sql + ); + + foreach ($vanilla_db_bindings as $bindingName => $bindingValue) { + $stmt_vanilla_db_count->bindValue($bindingName, $bindingValue, PDO::PARAM_STR); + } + + $stmt_vanilla_db_count->execute(); + $vanilla_db_total_rows = (int) $stmt_vanilla_db_count->fetchColumn(); + $vanilla_db_total_pages = max(1, (int) ceil($vanilla_db_total_rows / $vanilla_db_per_page)); + $vanilla_db_current_page = min($vanilla_db_current_page, $vanilla_db_total_pages); + $vanilla_db_offset = ($vanilla_db_current_page - 1) * $vanilla_db_per_page; + + $stmt_vanilla_db = $db->prepare( + "SELECT cl_scobjs_id, cl_scobjs_name, cl_scobjs_type, cl_scobjs_subtype, cl_scobjs_uuid, cl_scobjs_rarity + FROM tbl_scobjs" . $vanilla_db_where_sql . " + ORDER BY cl_scobjs_name ASC, cl_scobjs_type ASC, cl_scobjs_subtype ASC, cl_scobjs_id ASC + LIMIT :vanilla_limit OFFSET :vanilla_offset" + ); + + foreach ($vanilla_db_bindings as $bindingName => $bindingValue) { + $stmt_vanilla_db->bindValue($bindingName, $bindingValue, PDO::PARAM_STR); + } + $stmt_vanilla_db->bindValue(':vanilla_limit', $vanilla_db_per_page, PDO::PARAM_INT); + $stmt_vanilla_db->bindValue(':vanilla_offset', $vanilla_db_offset, PDO::PARAM_INT); + $stmt_vanilla_db->execute(); + + foreach ($stmt_vanilla_db->fetchAll() as $row) { + $name = trim((string) ($row['cl_scobjs_name'] ?? '')) ?: 'Objet inconnu'; + $type = trim((string) ($row['cl_scobjs_type'] ?? '')) ?: '—'; + $subtype = trim((string) ($row['cl_scobjs_subtype'] ?? '')) ?: '—'; + $uuid = trim((string) ($row['cl_scobjs_uuid'] ?? '')) ?: '—'; + $rarity = index_scan_normalize_rarity($row['cl_scobjs_rarity'] ?? ''); + + $vanilla_db_rows[] = [ + 'id' => (int) ($row['cl_scobjs_id'] ?? 0), + 'name' => $name, + 'type' => $type, + 'subtype' => $subtype, + 'uuid' => $uuid, + 'image_url' => $uuid !== '—' ? 'https://cstone.space/uifimages/' . rawurlencode($uuid) . '.png' : null, + 'rarity' => $rarity !== '' ? $rarity : '—', + 'rarity_label' => $rarity !== '' ? index_scan_rarity_label($rarity) : 'Non définie', + 'rarity_class' => index_scan_rarity_class($rarity), + ]; + } + + if ($vanilla_db_total_rows > 0) { + $vanilla_db_result_start = $vanilla_db_offset + 1; + $vanilla_db_result_end = $vanilla_db_offset + count($vanilla_db_rows); + } + } catch (Throwable $e) { + $vanilla_db_error = 'Impossible de charger la base des objets pour le moment.'; + } +} ?> @@ -355,6 +461,12 @@ if ($has_member_access) { letter-spacing: 0.06em; text-transform: uppercase; cursor: pointer; + text-decoration: none; + text-align: center; + } + + .vanilla-db-search-btn { + background: rgba(162, 155, 120, 0.2); } .scan-reference-filter-btn:hover, @@ -502,6 +614,12 @@ if ($has_member_access) { min-width: 1040px; } + .modal-vanilla-db { + width: 92%; + max-width: 1440px; + min-width: 980px; + } + .item-custom-dialog { display: flex; flex-direction: column; @@ -1112,18 +1230,296 @@ if ($has_member_access) { display: none; } + .vanilla-db-dialog { + display: flex; + flex-direction: column; + background: linear-gradient(180deg, rgba(18, 22, 31, 0.98), rgba(8, 11, 18, 0.98)); + border: 1px solid rgba(162, 155, 120, 0.35); + box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45); + max-height: min(88vh, 980px); + } + + .vanilla-db-dialog h3 { + font-size: 1.75em; + letter-spacing: 0.08em; + } + + .vanilla-db-dialog > div { + display: flex; + flex-direction: column; + flex: 1 1 auto; + min-height: 0; + overflow: hidden; + padding: 22px 26px 26px; + } + + .vanilla-db-empty, + .vanilla-db-error { + margin: 0 0 18px; + padding: 12px 14px !important; + border-radius: 10px; + font-size: 0.95em; + text-align: left !important; + } + + .vanilla-db-empty { + background: rgba(255, 255, 255, 0.06); + border: 1px solid rgba(255, 255, 255, 0.12); + } + + .vanilla-db-error { + background: rgba(140, 32, 32, 0.18); + border: 1px solid rgba(255, 88, 88, 0.25); + color: #ffbdbd; + } + + .vanilla-db-filter-bar { + display: flex; + align-items: center; + gap: 14px; + margin: 0 0 18px; + padding: 14px 16px; + border-radius: 14px; + background: rgba(255, 255, 255, 0.04); + border: 1px solid rgba(162, 155, 120, 0.18); + flex-wrap: wrap; + } + + .vanilla-db-search-wrap { + display: flex; + align-items: center; + gap: 12px; + flex: 1 1 420px; + min-width: 260px; + } + + .vanilla-db-search-input { + width: 100%; + padding: 10px 14px; + border-radius: 10px; + border: 1px solid rgba(162, 155, 120, 0.3); + background: rgba(10, 14, 21, 0.95); + color: #ffffff; + font-size: 0.92em; + } + + .vanilla-db-search-input:focus-visible { + outline: 2px solid rgba(162, 155, 120, 0.45); + outline-offset: 2px; + } + + .vanilla-db-search-btn, + .vanilla-db-reset-btn { + padding: 10px 14px; + border-radius: 999px; + border: 1px solid rgba(162, 155, 120, 0.34); + background: rgba(162, 155, 120, 0.1); + color: #f6f1dc; + font-size: 0.76em; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + cursor: pointer; + text-decoration: none; + text-align: center; + } + + .vanilla-db-search-btn { + background: rgba(162, 155, 120, 0.2); + } + + .vanilla-db-status { + margin: 0 0 0 auto; + font-size: 0.85em; + color: rgba(255, 255, 255, 0.7); + text-align: right; + flex: 1 1 220px; + } + + .vanilla-db-grid { + display: flex; + flex-direction: column; + flex: 1 1 auto; + gap: 8px; + min-height: clamp(320px, 54vh, 700px); + overflow-y: auto; + padding-right: 4px; + } + + .vanilla-db-card { + grid-template-columns: 56px minmax(0, 1fr); + } + + .vanilla-db-card-main { + display: flex; + flex-direction: column; + justify-content: center; + gap: 4px; + min-width: 0; + } + + .vanilla-db-card-topline { + margin: 0; + color: rgba(255, 255, 255, 0.72); + font-size: 0.82em; + font-weight: 600; + letter-spacing: 0.05em; + text-transform: uppercase; + } + + .vanilla-db-card-meta { + margin: 0; + color: rgba(255, 255, 255, 0.68); + font-size: 0.82em; + line-height: 1.35; + } + + .vanilla-db-card-meta strong { + font-weight: 700; + color: rgba(255, 255, 255, 0.84); + } + + .vanilla-db-card-meta span { + word-break: break-all; + } + + .vanilla-db-card-details { + display: flex; + align-items: center; + justify-content: flex-end; + min-width: 0; + } + + .vanilla-db-muted { + color: rgba(255, 255, 255, 0.45); + } + + .item-custom-card-name.vanilla-db-item-name { + text-shadow: 0 0 10px rgba(255, 255, 255, 0.08); + } + + .item-custom-card-name.vanilla-db-item-name.scan-rarity-L { color: #ff8000; } + .item-custom-card-name.vanilla-db-item-name.scan-rarity-E { color: #a335ee; } + .item-custom-card-name.vanilla-db-item-name.scan-rarity-R { color: #4db2ff; } + .item-custom-card-name.vanilla-db-item-name.scan-rarity-U { color: #1eff00; } + .item-custom-card-name.vanilla-db-item-name.scan-rarity-C { color: #ffffff; } + .item-custom-card-name.vanilla-db-item-name.scan-rarity-none { color: #b5bcc8; } + + .vanilla-db-hover-preview { + position: fixed; + top: 0; + left: 0; + z-index: 10000; + display: none; + width: min(360px, calc(100vw - 32px)); + padding: 6px; + border-radius: 12px; + border: 1px solid rgba(162, 155, 120, 0.42); + background: rgba(9, 13, 19, 0.98); + box-shadow: 0 18px 44px rgba(0, 0, 0, 0.58), 0 0 18px rgba(162, 155, 120, 0.18); + backdrop-filter: blur(14px); + pointer-events: none; + } + + .vanilla-db-hover-preview.is-visible { + display: block; + } + + .vanilla-db-hover-preview img { + display: block; + width: 100%; + height: auto; + max-height: min(360px, calc(100vh - 32px)); + object-fit: contain; + border-radius: 8px; + background: rgba(255, 255, 255, 0.02); + } + + .vanilla-db-pagination { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + margin-top: 16px; + padding: 14px 16px; + border-radius: 14px; + background: rgba(255, 255, 255, 0.04); + border: 1px solid rgba(162, 155, 120, 0.18); + flex-wrap: wrap; + } + + .vanilla-db-pagination-pages { + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; + } + + .vanilla-db-pagination-summary { + margin: 0; + font-size: 0.84em; + color: rgba(255, 255, 255, 0.68); + } + + .vanilla-db-page-link, + .vanilla-db-page-current, + .vanilla-db-page-ellipsis { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 40px; + height: 40px; + padding: 0 12px; + border-radius: 999px; + font-size: 0.82em; + font-weight: 700; + letter-spacing: 0.04em; + } + + .vanilla-db-page-link { + border: 1px solid rgba(162, 155, 120, 0.24); + background: rgba(162, 155, 120, 0.08); + color: #f6f1dc; + text-decoration: none; + } + + .vanilla-db-page-link:hover, + .vanilla-db-page-link:focus-visible { + background: rgba(162, 155, 120, 0.18); + outline: none; + } + + .vanilla-db-page-current { + border: 1px solid rgba(255, 255, 255, 0.18); + background: rgba(255, 255, 255, 0.12); + color: #ffffff; + } + + .vanilla-db-page-ellipsis { + min-width: auto; + height: auto; + padding: 0 2px; + color: rgba(255, 255, 255, 0.45); + } + + .vanilla-db-card.is-hidden-by-search { + display: none; + } + @media (max-width: 1100px) { .modal-scan-reference, .modal-ship-presets, - .modal-item-custom { + .modal-item-custom, + .modal-vanilla-db { width: 96%; min-width: 0; } .scan-reference-dialog h3, .ship-presets-dialog h3, - .item-custom-dialog h3 { + .item-custom-dialog h3, + .vanilla-db-dialog h3 { font-size: 1.2em; } @@ -1140,6 +1536,15 @@ if ($has_member_access) { align-items: stretch; } + .vanilla-db-filter-bar { + align-items: stretch; + } + + .vanilla-db-status { + margin-left: 0; + text-align: left; + } + .ship-presets-filter-status { margin-left: 0; text-align: left; @@ -1164,6 +1569,10 @@ if ($has_member_access) { padding: 7px 10px; } + .vanilla-db-card { + grid-template-columns: 52px minmax(220px, 1fr) minmax(140px, auto); + } + .item-custom-card-preview { left: 62px; } @@ -1188,7 +1597,8 @@ if ($has_member_access) { .item-custom-filter-top, .item-custom-search-wrap, - .item-custom-type-filters { + .item-custom-type-filters, + .vanilla-db-search-wrap { flex-direction: column; align-items: stretch; } @@ -1203,6 +1613,11 @@ if ($has_member_access) { gap: 8px; } + .vanilla-db-card-main, + .vanilla-db-card-details { + grid-column: 1 / -1; + } + .item-custom-card-media { width: 48px !important; height: 48px !important; @@ -1238,11 +1653,18 @@ if ($has_member_access) { - +
- Signatures de minage - Presets de vaisseaux - Objet(s) personnalisé(s) + + Signatures de minage + Presets de vaisseaux + + + Objets Vanilla DB + + + Objet(s) personnalisé(s) +
@@ -1464,6 +1886,120 @@ if ($has_member_access) { + + + +