Autosave: 20260409-112334

This commit is contained in:
Flatlogic Bot 2026-04-09 11:23:34 +00:00
parent cab604778c
commit 033e89484e
2 changed files with 506 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

507
index.php
View File

@ -1,5 +1,35 @@
<?php <?php
require_once __DIR__ . '/db/auth.php'; require_once __DIR__ . '/db/auth.php';
require_once __DIR__ . '/db/config.php';
function index_scan_normalize_rarity(?string $rarity): string
{
return strtoupper(trim((string) $rarity));
}
function index_scan_rarity_class(?string $rarity): string
{
return match (index_scan_normalize_rarity($rarity)) {
'L' => 'scan-rarity-L',
'E' => 'scan-rarity-E',
'R' => 'scan-rarity-R',
'U' => 'scan-rarity-U',
'C' => 'scan-rarity-C',
default => 'scan-rarity-none',
};
}
function index_scan_rarity_label(?string $rarity): string
{
return match (index_scan_normalize_rarity($rarity)) {
'L' => 'Légendaire',
'E' => 'Épique',
'R' => 'Rare',
'U' => 'Peu commun',
'C' => 'Commun',
default => 'Non définie',
};
}
auth_start_session(); auth_start_session();
auth_bootstrap(); auth_bootstrap();
@ -7,6 +37,66 @@ auth_bootstrap();
$session_cl_auth_user = isset($_SESSION['user']) ? (string) $_SESSION['user'] : ''; $session_cl_auth_user = isset($_SESSION['user']) ? (string) $_SESSION['user'] : '';
$session_cl_auth_right = isset($_SESSION['role']) ? (string) $_SESSION['role'] : ''; $session_cl_auth_right = isset($_SESSION['role']) ? (string) $_SESSION['role'] : '';
$is_authenticated = $session_cl_auth_user !== ''; $is_authenticated = $session_cl_auth_user !== '';
$scan_reference_rows = [];
$scan_reference_max_occurrence = 0;
$scan_reference_error = null;
try {
$db = db();
$stmt_scan_reference = $db->query(
"SELECT o.cl_scobjs_id, o.cl_scobjs_name, o.cl_scobjs_rarity, m.cl_scmining_scan_value, m.cl_scmining_max_occurrence,
m.cl_scmining_can_manual, m.cl_scmining_can_land, m.cl_scmining_can_space
FROM tbl_scmining m
INNER JOIN tbl_scobjs o ON o.cl_scobjs_id = m.cl_scmining_obj_id
ORDER BY
CASE UPPER(COALESCE(o.cl_scobjs_rarity, ''))
WHEN 'L' THEN 1
WHEN 'E' THEN 2
WHEN 'R' THEN 3
WHEN 'U' THEN 4
WHEN 'C' THEN 5
ELSE 6
END,
o.cl_scobjs_name ASC"
);
foreach ($stmt_scan_reference->fetchAll() as $row) {
$occurrence_count = max(1, (int) ($row['cl_scmining_max_occurrence'] ?? 1));
$scan_value = (int) ($row['cl_scmining_scan_value'] ?? 0);
$recovery_modes = [];
if (!empty($row['cl_scmining_can_manual'])) {
$recovery_modes[] = 'Manuel';
}
if (!empty($row['cl_scmining_can_land'])) {
$recovery_modes[] = 'Terrestre';
}
if (!empty($row['cl_scmining_can_space'])) {
$recovery_modes[] = 'Spatial';
}
$scan_steps = [];
for ($i = 1; $i <= $occurrence_count; $i++) {
$scan_steps[] = $scan_value * $i;
}
$scan_reference_rows[] = [
'id' => (string) ($row['cl_scobjs_id'] ?? ''),
'name' => (string) ($row['cl_scobjs_name'] ?? ''),
'rarity' => index_scan_normalize_rarity($row['cl_scobjs_rarity'] ?? ''),
'rarity_label' => index_scan_rarity_label($row['cl_scobjs_rarity'] ?? ''),
'rarity_class' => index_scan_rarity_class($row['cl_scobjs_rarity'] ?? ''),
'recovery_modes' => $recovery_modes,
'scan_steps' => $scan_steps,
'max_occurrence' => $occurrence_count,
];
$scan_reference_max_occurrence = max($scan_reference_max_occurrence, $occurrence_count);
}
} catch (Throwable $e) {
$scan_reference_error = 'Impossible de charger le tableau des signatures de scan pour le moment.';
}
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="fr"> <html lang="fr">
@ -24,10 +114,242 @@ $is_authenticated = $session_cl_auth_user !== '';
<link rel="stylesheet" type="text/css" href="css/switch.css" /> <link rel="stylesheet" type="text/css" href="css/switch.css" />
<link rel="stylesheet" type="text/css" href="css/styles-modal.css" /> <link rel="stylesheet" type="text/css" href="css/styles-modal.css" />
<script src="js/modernizr.custom.js"></script> <script src="js/modernizr.custom.js"></script>
<style>
.modal-scan-reference {
width: 92%;
max-width: 1400px;
min-width: 960px;
}
.scan-reference-dialog {
background: linear-gradient(180deg, rgba(24, 28, 37, 0.98), rgba(11, 14, 20, 0.98));
border: 1px solid rgba(162, 155, 120, 0.35);
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
}
.scan-reference-dialog h3 {
font-size: 1.8em;
letter-spacing: 0.08em;
}
.scan-reference-dialog > div {
padding: 22px 26px 26px;
}
.scan-reference-intro,
.scan-reference-empty,
.scan-reference-error {
margin: 0 0 18px;
padding: 12px 14px !important;
border-radius: 10px;
font-size: 0.95em;
text-align: left !important;
}
.scan-reference-intro {
background: rgba(162, 155, 120, 0.12);
border: 1px solid rgba(162, 155, 120, 0.18);
}
.scan-reference-empty {
background: rgba(255, 255, 255, 0.06);
border: 1px solid rgba(255, 255, 255, 0.12);
}
.scan-reference-error {
background: rgba(140, 32, 32, 0.18);
border: 1px solid rgba(255, 88, 88, 0.25);
color: #ffbdbd;
}
.scan-reference-filter-bar {
display: flex;
justify-content: space-between;
align-items: center;
gap: 14px;
margin: 0 0 14px;
padding: 10px 12px;
border: 1px solid rgba(162, 155, 120, 0.18);
border-radius: 10px;
background: rgba(162, 155, 120, 0.07);
}
.scan-reference-filter-actions {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.scan-reference-filter-btn {
padding: 7px 12px;
border: 1px solid rgba(162, 155, 120, 0.35);
border-radius: 999px;
background: rgba(162, 155, 120, 0.14);
color: #f2eed9;
font-size: 0.72em;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
cursor: pointer;
}
.scan-reference-filter-btn:hover,
.scan-reference-filter-btn:focus-visible {
background: rgba(162, 155, 120, 0.22);
outline: none;
}
.scan-reference-filter-btn.is-disabled {
opacity: 0.45;
cursor: not-allowed;
}
.scan-reference-filter-status {
margin: 0;
font-size: 0.74em;
color: rgba(255, 255, 255, 0.72);
text-align: right;
}
.scan-reference-table-wrapper {
max-height: 65vh;
overflow: auto;
border: 1px solid rgba(162, 155, 120, 0.22);
border-radius: 12px;
background: rgba(6, 9, 14, 0.65);
}
.scan-reference-table {
width: 100%;
border-collapse: collapse;
min-width: 880px;
font-size: 0.84em;
}
.scan-reference-table th,
.scan-reference-table td {
padding: 9px 11px;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
vertical-align: middle;
text-align: left;
}
.scan-reference-table th {
position: sticky;
top: 0;
z-index: 2;
background: rgba(18, 22, 30, 0.96);
text-transform: uppercase;
font-size: 0.74em;
letter-spacing: 0.08em;
color: #d7cfac;
}
.scan-reference-table tbody tr {
cursor: pointer;
transition: background 0.18s ease, box-shadow 0.18s ease, opacity 0.18s ease;
}
.scan-reference-table tbody tr:hover {
background: rgba(162, 155, 120, 0.08);
}
.scan-reference-table tbody tr.is-selected {
background: rgba(162, 155, 120, 0.16);
box-shadow: inset 0 0 0 1px rgba(162, 155, 120, 0.35);
}
.scan-reference-table tbody tr.is-hidden-by-filter {
display: none;
}
.scan-reference-name span {
display: block;
font-weight: 700;
font-size: 0.94em;
}
.scan-reference-recovery {
min-width: 180px;
}
.scan-reference-pill {
display: inline-block;
margin: 0 5px 5px 0;
padding: 4px 8px;
border-radius: 999px;
background: rgba(162, 155, 120, 0.16);
border: 1px solid rgba(162, 155, 120, 0.24);
font-size: 0.72em;
white-space: nowrap;
}
.scan-reference-value {
text-align: center;
font-variant-numeric: tabular-nums;
font-weight: 700;
font-size: 0.92em;
white-space: nowrap;
}
.scan-reference-muted {
color: rgba(255, 255, 255, 0.35);
}
.scan-rarity-L .scan-reference-name span,
.scan-rarity-L .scan-reference-value {
color: #ff8000;
}
.scan-rarity-E .scan-reference-name span,
.scan-rarity-E .scan-reference-value {
color: #a335ee;
}
.scan-rarity-R .scan-reference-name span,
.scan-rarity-R .scan-reference-value {
color: #4db2ff;
}
.scan-rarity-U .scan-reference-name span,
.scan-rarity-U .scan-reference-value {
color: #1eff00;
}
.scan-rarity-C .scan-reference-name span,
.scan-rarity-C .scan-reference-value {
color: #ffffff;
}
.scan-rarity-none .scan-reference-name span,
.scan-rarity-none .scan-reference-value {
color: #b5bcc8;
}
@media (max-width: 1100px) {
.modal-scan-reference {
width: 96%;
min-width: 0;
}
.scan-reference-dialog h3 {
font-size: 1.2em;
}
.scan-reference-filter-bar {
flex-direction: column;
align-items: stretch;
}
.scan-reference-filter-status {
text-align: left;
}
}
</style>
</head> </head>
<body> <body>
<div class="assets-div-menu"> <div class="assets-div-menu md-trigger" data-modal="modal-ScanReference">
<a href="#">Contenu à venir</a> <a href="#">Contenu à venir</a>
</div> </div>
@ -92,6 +414,68 @@ $is_authenticated = $session_cl_auth_user !== '';
</div> </div>
</div> </div>
</div> </div>
<div class="md-modal md-effect-1 modal-scan-reference" id="modal-ScanReference">
<div class="md-content scan-reference-dialog">
<h3>
<img class="float-left" src="img/icon_bops.png" width="48" height="48" alt="" />
TABLEAU DES SIGNATURES DE SCAN
<a class="frame-icon-close md-close float-right" href="#"><img src="img/icon_close.png" width="48" height="48" alt="" /></a>
</h3>
<div>
<?php if ($scan_reference_error !== null): ?>
<p class="scan-reference-error"><?php echo htmlspecialchars($scan_reference_error, ENT_QUOTES, 'UTF-8'); ?></p>
<?php elseif ($scan_reference_rows === []): ?>
<p class="scan-reference-empty">Aucune donnée de scan n'est configurée pour le moment.</p>
<?php else: ?>
<div class="scan-reference-filter-bar">
<div class="scan-reference-filter-actions">
<button type="button" class="scan-reference-filter-btn" id="scanReferenceIsolateBtn">Isoler</button>
<button type="button" class="scan-reference-filter-btn" id="scanReferenceClearBtn">Supprimer le filtrage</button>
</div>
<p class="scan-reference-filter-status" id="scanReferenceFilterStatus">Clique sur les lignes à conserver puis sur « Isoler ».</p>
</div>
<div class="scan-reference-table-wrapper">
<table class="scan-reference-table" id="scanReferenceTable">
<thead>
<tr>
<th>Ressource</th>
<th>Récupérations</th>
<?php for ($occurrence = 1; $occurrence <= $scan_reference_max_occurrence; $occurrence++): ?>
<th>x <?php echo $occurrence; ?></th>
<?php endfor; ?>
</tr>
</thead>
<tbody>
<?php foreach ($scan_reference_rows as $scan_reference_row): ?>
<tr class="scan-reference-row <?php echo htmlspecialchars($scan_reference_row['rarity_class'], ENT_QUOTES, 'UTF-8'); ?>" data-resource-id="<?php echo htmlspecialchars($scan_reference_row['id'], ENT_QUOTES, 'UTF-8'); ?>" data-resource-name="<?php echo htmlspecialchars($scan_reference_row['name'], ENT_QUOTES, 'UTF-8'); ?>">
<td class="scan-reference-name">
<span><?php echo htmlspecialchars($scan_reference_row['name'], ENT_QUOTES, 'UTF-8'); ?></span>
</td>
<td class="scan-reference-recovery">
<?php if ($scan_reference_row['recovery_modes'] !== []): ?>
<?php foreach ($scan_reference_row['recovery_modes'] as $recovery_mode): ?>
<span class="scan-reference-pill"><?php echo htmlspecialchars($recovery_mode, ENT_QUOTES, 'UTF-8'); ?></span>
<?php endforeach; ?>
<?php else: ?>
<span class="scan-reference-muted"></span>
<?php endif; ?>
</td>
<?php for ($occurrence = 1; $occurrence <= $scan_reference_max_occurrence; $occurrence++): ?>
<td class="scan-reference-value">
<?php echo array_key_exists($occurrence - 1, $scan_reference_row['scan_steps']) ? number_format((int) $scan_reference_row['scan_steps'][$occurrence - 1], 0, ',', ' ') : '<span class="scan-reference-muted">—</span>'; ?>
</td>
<?php endfor; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
<div class="center-page-bops"></div> <div class="center-page-bops"></div>
@ -140,6 +524,127 @@ $is_authenticated = $session_cl_auth_user !== '';
<script src="js/cssParser.js"></script> <script src="js/cssParser.js"></script>
<script src="js/css-filters-polyfill.js"></script> <script src="js/css-filters-polyfill.js"></script>
<script>
(function initScanReferenceFilter() {
const storageKey = 'scanReferenceIsolatedResources.v1';
const table = document.getElementById('scanReferenceTable');
const status = document.getElementById('scanReferenceFilterStatus');
const isolateButton = document.getElementById('scanReferenceIsolateBtn');
const clearButton = document.getElementById('scanReferenceClearBtn');
if (!table || !status || !isolateButton || !clearButton) {
return;
}
const rows = Array.from(table.querySelectorAll('.scan-reference-row'));
const selectedIds = new Set();
let activeFilterIds = [];
function saveFilter(ids) {
if (!Array.isArray(ids) || ids.length === 0) {
window.localStorage.removeItem(storageKey);
return;
}
window.localStorage.setItem(storageKey, JSON.stringify(ids));
}
function loadFilter() {
try {
const raw = window.localStorage.getItem(storageKey);
if (!raw) {
return [];
}
const parsed = JSON.parse(raw);
return Array.isArray(parsed) ? parsed.map(String).filter(Boolean) : [];
} catch (error) {
window.localStorage.removeItem(storageKey);
return [];
}
}
function getVisibleCount() {
return rows.filter((row) => !row.classList.contains('is-hidden-by-filter')).length;
}
function refreshStatus() {
const selectedCount = selectedIds.size;
const visibleCount = getVisibleCount();
const totalCount = rows.length;
const filterIsActive = activeFilterIds.length > 0;
isolateButton.classList.toggle('is-disabled', selectedCount === 0);
isolateButton.disabled = selectedCount === 0;
clearButton.classList.toggle('is-disabled', !filterIsActive);
clearButton.disabled = !filterIsActive;
if (filterIsActive) {
status.textContent = 'Filtre actif : ' + visibleCount + ' ressource(s) affichée(s) sur ' + totalCount + '.';
return;
}
if (selectedCount > 0) {
status.textContent = selectedCount + ' ressource(s) sélectionnée(s). Clique sur « Isoler » pour nafficher que celles-ci.';
return;
}
status.textContent = 'Clique sur les lignes à conserver puis sur « Isoler ».';
}
function applyFilter(ids) {
activeFilterIds = Array.isArray(ids) ? ids.map(String).filter(Boolean) : [];
const filterSet = new Set(activeFilterIds);
rows.forEach((row) => {
const rowId = String(row.dataset.resourceId || '');
const shouldHide = filterSet.size > 0 && !filterSet.has(rowId);
row.classList.toggle('is-hidden-by-filter', shouldHide);
});
refreshStatus();
}
rows.forEach((row) => {
row.addEventListener('click', function () {
const rowId = String(row.dataset.resourceId || '');
if (!rowId) {
return;
}
if (selectedIds.has(rowId)) {
selectedIds.delete(rowId);
row.classList.remove('is-selected');
} else {
selectedIds.add(rowId);
row.classList.add('is-selected');
}
refreshStatus();
});
});
isolateButton.addEventListener('click', function () {
if (selectedIds.size === 0) {
refreshStatus();
return;
}
const ids = Array.from(selectedIds);
saveFilter(ids);
applyFilter(ids);
});
clearButton.addEventListener('click', function () {
saveFilter([]);
applyFilter([]);
});
applyFilter(loadFilter());
})();
</script>
<script> <script>
// On ajoute dynamiquement l'origine à l'URL de l'iframe (recommandé par l'API YouTube) // On ajoute dynamiquement l'origine à l'URL de l'iframe (recommandé par l'API YouTube)
(function attachOrigin(){ (function attachOrigin(){