1929 lines
63 KiB
PHP
1929 lines
63 KiB
PHP
<?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',
|
||
};
|
||
}
|
||
|
||
function index_itemcustom_display_value($value): string
|
||
{
|
||
if ($value === null || $value === '') {
|
||
return '0';
|
||
}
|
||
|
||
if (is_numeric($value)) {
|
||
$formatted = number_format((float) $value, 2, '.', '');
|
||
$formatted = rtrim(rtrim($formatted, '0'), '.');
|
||
return $formatted === '' ? '0' : $formatted;
|
||
}
|
||
|
||
return trim((string) $value) !== '' ? trim((string) $value) : '0';
|
||
}
|
||
|
||
function index_itemcustom_stat_preview(?string $sign, $value, ?string $unit): string
|
||
{
|
||
$prefix = $sign === '-' ? '-' : ($sign === '+' ? '+' : '');
|
||
$displayValue = index_itemcustom_display_value($value);
|
||
$displayUnit = trim((string) ($unit ?? ''));
|
||
|
||
return trim($prefix . $displayValue . ($displayUnit !== '' ? ' ' . $displayUnit : ''));
|
||
}
|
||
|
||
auth_start_session();
|
||
auth_bootstrap();
|
||
|
||
$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);
|
||
|
||
$scan_reference_rows = [];
|
||
$scan_reference_max_occurrence = 0;
|
||
$scan_reference_error = null;
|
||
$ship_preset_rows = [];
|
||
$ship_preset_manufacturers = [];
|
||
$ship_preset_error = null;
|
||
$item_custom_public_rows = [];
|
||
$item_custom_public_types = [];
|
||
$item_custom_public_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.';
|
||
}
|
||
|
||
if ($has_member_access) {
|
||
try {
|
||
if (!isset($db) || !($db instanceof PDO)) {
|
||
$db = db();
|
||
}
|
||
|
||
$stmt_ship_presets = $db->query(
|
||
"SELECT cl_scpreset_id, cl_scpreset_name, cl_scpreset_manufacturer, cl_scpreset_description, cl_scpreset_link, cl_scpreset_creator
|
||
FROM tbl_scpreset
|
||
ORDER BY cl_scpreset_manufacturer ASC, cl_scpreset_name ASC"
|
||
);
|
||
|
||
foreach ($stmt_ship_presets->fetchAll() as $row) {
|
||
$ship_name = trim((string) ($row['cl_scpreset_name'] ?? '')) ?: 'Vaisseau inconnu';
|
||
$manufacturer = trim((string) ($row['cl_scpreset_manufacturer'] ?? '')) ?: 'Manufacture inconnue';
|
||
$manufacturer_key = function_exists('mb_strtolower')
|
||
? mb_strtolower($manufacturer, 'UTF-8')
|
||
: strtolower($manufacturer);
|
||
|
||
$ship_preset_manufacturers[$manufacturer_key] = $manufacturer;
|
||
|
||
$ship_preset_rows[] = [
|
||
'id' => (string) ($row['cl_scpreset_id'] ?? ''),
|
||
'name' => $ship_name,
|
||
'manufacturer' => $manufacturer,
|
||
'creator' => trim((string) ($row['cl_scpreset_creator'] ?? '')) ?: 'Inconnu',
|
||
'description' => trim((string) ($row['cl_scpreset_description'] ?? '')) ?: 'Aucune description disponible pour ce preset.',
|
||
'link' => trim((string) ($row['cl_scpreset_link'] ?? '')),
|
||
];
|
||
}
|
||
|
||
natcasesort($ship_preset_manufacturers);
|
||
$ship_preset_manufacturers = array_values($ship_preset_manufacturers);
|
||
} catch (Throwable $e) {
|
||
$ship_preset_error = 'Impossible de charger les presets de vaisseaux pour le moment.';
|
||
}
|
||
}
|
||
|
||
if ($has_member_access) {
|
||
try {
|
||
if (!isset($db) || !($db instanceof PDO)) {
|
||
$db = db();
|
||
}
|
||
|
||
$stmt_item_custom_public = $db->query(
|
||
"SELECT
|
||
c.cl_scitemcustom_id,
|
||
o.cl_scobjs_name,
|
||
o.cl_scobjs_uuid,
|
||
o.cl_scobjs_type,
|
||
o.cl_scobjs_subtype,
|
||
COALESCE(NULLIF(TRIM(a.cl_auth_user), ''), 'Inconnu') AS creator_name,
|
||
cs.cl_scitemcustomstat_id,
|
||
cs.cl_scitemcustomstat_sign,
|
||
cs.cl_scitemcustomstat_value,
|
||
st.cl_scstatsitem_name,
|
||
st.cl_scstatsitem_unit
|
||
FROM tbl_scitemcustom c
|
||
INNER JOIN tbl_scobjs o ON o.cl_scobjs_id = c.cl_scitemcustom_obj_id
|
||
LEFT JOIN tbl_auth a ON a.cl_auth_id = c.cl_scitemcustom_owner_auth_id
|
||
LEFT JOIN tbl_scitemcustomstat cs ON cs.cl_scitemcustomstat_itemcustom_id = c.cl_scitemcustom_id
|
||
LEFT JOIN tbl_scstatsitem st ON st.cl_scstatsitem_id = cs.cl_scitemcustomstat_stat_id
|
||
WHERE c.cl_scitemcustom_owner_auth_id IS NOT NULL
|
||
ORDER BY o.cl_scobjs_name ASC, creator_name ASC, c.cl_scitemcustom_id ASC, st.cl_scstatsitem_name ASC, cs.cl_scitemcustomstat_id ASC"
|
||
);
|
||
|
||
$grouped_item_custom_public = [];
|
||
|
||
foreach ($stmt_item_custom_public->fetchAll() as $row) {
|
||
$item_id = (int) ($row['cl_scitemcustom_id'] ?? 0);
|
||
if ($item_id <= 0) {
|
||
continue;
|
||
}
|
||
|
||
if (!isset($grouped_item_custom_public[$item_id])) {
|
||
$name = trim((string) ($row['cl_scobjs_name'] ?? '')) ?: 'Objet inconnu';
|
||
$creator = trim((string) ($row['creator_name'] ?? '')) ?: 'Inconnu';
|
||
$type = trim((string) ($row['cl_scobjs_type'] ?? ''));
|
||
$subtype = trim((string) ($row['cl_scobjs_subtype'] ?? ''));
|
||
$uuid = trim((string) ($row['cl_scobjs_uuid'] ?? ''));
|
||
|
||
$grouped_item_custom_public[$item_id] = [
|
||
'id' => $item_id,
|
||
'name' => $name,
|
||
'creator' => $creator,
|
||
'type' => $type,
|
||
'subtype' => $subtype,
|
||
'uuid' => $uuid,
|
||
'stats' => [],
|
||
'search_parts' => [$name, $creator, $type, $subtype, $uuid],
|
||
];
|
||
}
|
||
|
||
if (!empty($row['cl_scitemcustomstat_id'])) {
|
||
$stat_name = trim((string) ($row['cl_scstatsitem_name'] ?? '')) ?: 'Stat inconnue';
|
||
$stat_sign = trim((string) ($row['cl_scitemcustomstat_sign'] ?? ''));
|
||
$stat_value_raw = $row['cl_scitemcustomstat_value'] ?? 0;
|
||
$stat_unit = trim((string) ($row['cl_scstatsitem_unit'] ?? ''));
|
||
$stat_preview = index_itemcustom_stat_preview($stat_sign, $stat_value_raw, $stat_unit);
|
||
|
||
$grouped_item_custom_public[$item_id]['stats'][] = [
|
||
'name' => $stat_name,
|
||
'preview' => $stat_preview,
|
||
];
|
||
|
||
$grouped_item_custom_public[$item_id]['search_parts'][] = $stat_name;
|
||
$grouped_item_custom_public[$item_id]['search_parts'][] = $stat_preview;
|
||
}
|
||
}
|
||
|
||
$item_custom_public_types_lookup = [];
|
||
|
||
foreach ($grouped_item_custom_public as $item_custom_public_row) {
|
||
$item_custom_public_row['search'] = trim(implode(' ', array_filter($item_custom_public_row['search_parts'], static function ($value) {
|
||
return trim((string) $value) !== '';
|
||
})));
|
||
unset($item_custom_public_row['search_parts']);
|
||
$item_custom_public_rows[] = $item_custom_public_row;
|
||
|
||
$item_custom_public_type_label = $item_custom_public_row['type'] !== '' ? $item_custom_public_row['type'] : 'Type inconnu';
|
||
$item_custom_public_type_key = strtolower($item_custom_public_type_label);
|
||
if (!isset($item_custom_public_types_lookup[$item_custom_public_type_key])) {
|
||
$item_custom_public_types_lookup[$item_custom_public_type_key] = $item_custom_public_type_label;
|
||
}
|
||
}
|
||
|
||
natcasesort($item_custom_public_types_lookup);
|
||
$item_custom_public_types = array_values($item_custom_public_types_lookup);
|
||
} catch (Throwable $e) {
|
||
$item_custom_public_error = 'Impossible de charger les objets Item Custom pour le moment.';
|
||
}
|
||
}
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="keywords" content="BlackOps Agency, Star Citizen, Advocacy, UEE, Sécurité, Exploration, Renseignement, Patrouilles, Chasses de primes, Investigation, Neutralisation de menaces, Assistance humanitaire, Abordages, Réseaux anti-toxicité, Formation tactique, Entraînements, Coopération, Zones UEE, Systèmes inexplorés, Lore Star Citizen, Missions multi-joueurs, Protocole Arkange, Protocole Vigilance, Respect des lois impériales, Justice interstellaire, Criminalité galactique, Piraterie, XenoThreat, Vanduul, Sécurité spatiale, Leadership BlackOps, Collaboration stratégique, Combat spatial, Star Citizen gameplay, Exploration stratégique, Missions BlackOps Agency, Réputation UEE, Gestion des conflits, BlackOps, Agency, Recrutement Star Citizen, Zones de guerre, Star Citizen immersion.">
|
||
|
||
<title>Rapid Emergency & Action Combat Team / Star Citizen</title>
|
||
|
||
<link rel="stylesheet" type="text/css" href="css/styles.css">
|
||
<link rel="stylesheet" type="text/css" href="css/default.css" />
|
||
<link rel="stylesheet" type="text/css" href="css/component.css" />
|
||
<link rel="stylesheet" type="text/css" href="css/switch.css" />
|
||
<link rel="stylesheet" type="text/css" href="css/styles-modal.css" />
|
||
<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.60em;
|
||
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;
|
||
}
|
||
|
||
.modal-ship-presets {
|
||
width: 92%;
|
||
max-width: 1320px;
|
||
min-width: 940px;
|
||
}
|
||
|
||
.modal-item-custom {
|
||
width: 94%;
|
||
max-width: 1500px;
|
||
min-width: 1040px;
|
||
}
|
||
|
||
.item-custom-dialog {
|
||
display: flex;
|
||
flex-direction: column;
|
||
background: linear-gradient(180deg, rgba(15, 20, 29, 0.98), rgba(7, 10, 16, 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);
|
||
}
|
||
|
||
.item-custom-dialog h3 {
|
||
font-size: 1.75em;
|
||
letter-spacing: 0.08em;
|
||
}
|
||
|
||
.item-custom-dialog > div {
|
||
display: flex;
|
||
flex-direction: column;
|
||
flex: 1 1 auto;
|
||
min-height: 0;
|
||
overflow: hidden;
|
||
padding: 22px 26px 26px;
|
||
}
|
||
|
||
.item-custom-empty,
|
||
.item-custom-error {
|
||
margin: 0 0 18px;
|
||
padding: 12px 14px !important;
|
||
border-radius: 10px;
|
||
font-size: 0.95em;
|
||
text-align: left !important;
|
||
}
|
||
|
||
|
||
.item-custom-empty {
|
||
background: rgba(255, 255, 255, 0.06);
|
||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||
}
|
||
|
||
.item-custom-error {
|
||
background: rgba(140, 32, 32, 0.18);
|
||
border: 1px solid rgba(255, 88, 88, 0.25);
|
||
color: #ffbdbd;
|
||
}
|
||
|
||
.item-custom-filter-bar {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
gap: 10px;
|
||
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);
|
||
}
|
||
|
||
.item-custom-filter-top {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 14px;
|
||
width: 100%;
|
||
}
|
||
|
||
.item-custom-search-wrap {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
}
|
||
|
||
.item-custom-type-filters {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 8px;
|
||
width: 100%;
|
||
}
|
||
|
||
.item-custom-type-label {
|
||
font-size: 0.64em;
|
||
font-weight: 700;
|
||
letter-spacing: 0.08em;
|
||
text-transform: uppercase;
|
||
color: rgba(255, 255, 255, 0.62);
|
||
}
|
||
|
||
.item-custom-type-options {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.item-custom-type-chip {
|
||
position: relative;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.item-custom-type-chip input {
|
||
position: absolute;
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.item-custom-type-chip span {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
padding: 4px 9px;
|
||
min-height: 24px;
|
||
border-radius: 999px;
|
||
border: 1px solid rgba(162, 155, 120, 0.22);
|
||
background: rgba(255, 255, 255, 0.028);
|
||
color: rgba(255, 255, 255, 0.76);
|
||
font-size: 0.62em;
|
||
font-weight: 400;
|
||
letter-spacing: 0.03em;
|
||
line-height: 1;
|
||
transition: border-color 0.18s ease, background 0.18s ease, color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
|
||
}
|
||
|
||
.item-custom-type-chip input:checked + span {
|
||
border-color: rgba(162, 155, 120, 0.72);
|
||
background: rgba(162, 155, 120, 0.18);
|
||
color: #fff7dd;
|
||
box-shadow: inset 0 0 0 1px rgba(162, 155, 120, 0.18);
|
||
}
|
||
|
||
.item-custom-type-chip input:focus-visible + span {
|
||
outline: 2px solid rgba(162, 155, 120, 0.45);
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
.item-custom-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;
|
||
}
|
||
|
||
.item-custom-search-input:focus-visible {
|
||
outline: 2px solid rgba(162, 155, 120, 0.45);
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
.item-custom-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;
|
||
}
|
||
|
||
.item-custom-filter-status {
|
||
margin: 0;
|
||
flex: 0 0 auto;
|
||
font-size: 0.85em;
|
||
color: rgba(255, 255, 255, 0.7);
|
||
text-align: right;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.item-custom-grid {
|
||
display: flex;
|
||
flex-direction: column;
|
||
flex: 1 1 auto;
|
||
gap: 8px;
|
||
min-height: clamp(320px, 52vh, 620px);
|
||
max-height: none;
|
||
overflow-y: auto;
|
||
padding-right: 4px;
|
||
}
|
||
|
||
.item-custom-card {
|
||
display: grid;
|
||
grid-template-columns: 56px minmax(0, 430px) minmax(320px, 1.65fr);
|
||
gap: 14px;
|
||
align-items: center;
|
||
padding: 7px 14px 8px;
|
||
border-radius: 12px;
|
||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.022));
|
||
border: 1px solid rgba(162, 155, 120, 0.2);
|
||
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.18);
|
||
}
|
||
|
||
.item-custom-card-media {
|
||
position: relative;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 52px !important;
|
||
height: 52px !important;
|
||
min-width: 52px;
|
||
min-height: 52px;
|
||
aspect-ratio: 1 / 1;
|
||
overflow: hidden;
|
||
border-radius: 10px;
|
||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||
background: rgba(255, 255, 255, 0.04);
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
|
||
cursor: zoom-in;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.item-custom-card-media.is-image-missing {
|
||
cursor: default;
|
||
}
|
||
|
||
.item-custom-card-media.is-image-missing::after {
|
||
content: 'N/A';
|
||
position: absolute;
|
||
inset: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 0.62em;
|
||
font-weight: 700;
|
||
letter-spacing: 0.12em;
|
||
color: rgba(255, 255, 255, 0.45);
|
||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.01));
|
||
}
|
||
|
||
.item-custom-card-main {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
gap: 1px;
|
||
min-width: 0;
|
||
padding-top: 0;
|
||
}
|
||
|
||
.item-custom-card-stats {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
min-width: 0;
|
||
}
|
||
|
||
.item-custom-card-stats-header {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
align-items: center;
|
||
}
|
||
|
||
.item-custom-card-thumb {
|
||
width: 100% !important;
|
||
height: 100% !important;
|
||
min-width: 100%;
|
||
max-width: none;
|
||
border-radius: 0;
|
||
object-fit: cover;
|
||
background: transparent;
|
||
border: 0;
|
||
box-shadow: none;
|
||
display: block;
|
||
flex: 1 0 auto;
|
||
}
|
||
|
||
.item-custom-card-media.is-image-missing .item-custom-card-thumb,
|
||
.item-custom-card-media.is-image-missing .item-custom-card-preview {
|
||
display: none !important;
|
||
}
|
||
|
||
.item-custom-card-preview {
|
||
visibility: hidden;
|
||
opacity: 0;
|
||
position: absolute;
|
||
top: -10px;
|
||
left: 68px;
|
||
z-index: 1000;
|
||
padding: 5px;
|
||
background: rgba(11, 15, 22, 0.97);
|
||
border: 1px solid rgba(162, 155, 120, 0.5);
|
||
border-radius: 10px;
|
||
box-shadow: 0 14px 40px rgba(0, 0, 0, 0.55), 0 0 20px rgba(162, 155, 120, 0.2);
|
||
backdrop-filter: blur(12px);
|
||
transition: opacity 0.18s ease, visibility 0.18s ease;
|
||
pointer-events: none;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.item-custom-card-preview img {
|
||
width: 320px;
|
||
height: 320px;
|
||
object-fit: contain;
|
||
display: block;
|
||
border-radius: 6px;
|
||
background: rgba(255, 255, 255, 0.02);
|
||
}
|
||
|
||
.item-custom-card-media:hover .item-custom-card-preview,
|
||
.item-custom-card-media:focus-within .item-custom-card-preview {
|
||
visibility: visible;
|
||
opacity: 1;
|
||
}
|
||
|
||
.item-custom-card-type {
|
||
margin: 0;
|
||
font-size: 0.65em;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.115em;
|
||
line-height: 1.08;
|
||
color: rgba(162, 155, 120, 0.95);
|
||
}
|
||
|
||
.item-custom-card-name {
|
||
margin: 0;
|
||
font-size: 0.97em;
|
||
line-height: 1.08;
|
||
color: #ffffff;
|
||
word-break: normal;
|
||
overflow-wrap: normal;
|
||
hyphens: none;
|
||
}
|
||
|
||
.item-custom-card-meta {
|
||
margin: 0;
|
||
font-size: 0.73em;
|
||
line-height: 1.08;
|
||
color: rgba(255, 255, 255, 0.68);
|
||
}
|
||
|
||
.item-custom-card-count {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 3px 9px;
|
||
border-radius: 999px;
|
||
background: rgba(162, 155, 120, 0.12);
|
||
border: 1px solid rgba(162, 155, 120, 0.22);
|
||
color: #f6f1dc;
|
||
font-size: 0.6em;
|
||
font-weight: 700;
|
||
letter-spacing: 0.075em;
|
||
text-transform: uppercase;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.item-custom-stats-list {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 5px 6px;
|
||
margin: 0;
|
||
padding: 0;
|
||
list-style: none;
|
||
}
|
||
|
||
.item-custom-stat-chip {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
flex-wrap: nowrap;
|
||
gap: 10px;
|
||
padding: 6px 18px 7px !important;
|
||
padding-left: 18px !important;
|
||
padding-right: 18px !important;
|
||
border-radius: 11px;
|
||
background: rgba(255, 255, 255, 0.05);
|
||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||
min-height: 30px;
|
||
max-width: 100%;
|
||
box-sizing: border-box;
|
||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);
|
||
}
|
||
|
||
.item-custom-stat-name {
|
||
font-size: 0.72em;
|
||
color: rgba(255, 255, 255, 0.76);
|
||
white-space: nowrap;
|
||
line-height: 1.05;
|
||
}
|
||
|
||
.item-custom-stat-value {
|
||
font-size: 0.79em;
|
||
font-weight: 700;
|
||
color: #ffffff;
|
||
word-break: keep-all;
|
||
white-space: nowrap;
|
||
padding: 0 2px;
|
||
}
|
||
|
||
.item-custom-stat-chip.sign-plus {
|
||
border-color: rgba(127, 255, 185, 0.24);
|
||
background: rgba(0, 255, 136, 0.1);
|
||
}
|
||
|
||
.item-custom-stat-chip.sign-plus .item-custom-stat-value {
|
||
color: #7fffb9;
|
||
}
|
||
|
||
.item-custom-stat-chip.sign-minus {
|
||
border-color: rgba(255, 120, 120, 0.22);
|
||
background: rgba(255, 77, 77, 0.1);
|
||
}
|
||
|
||
.item-custom-stat-chip.sign-minus .item-custom-stat-value {
|
||
color: #ffb0b0;
|
||
}
|
||
|
||
.item-custom-stat-chip.sign-neutral {
|
||
background: rgba(255, 255, 255, 0.045);
|
||
}
|
||
|
||
.item-custom-stat-chip.sign-neutral .item-custom-stat-value {
|
||
color: #f1f1f1;
|
||
}
|
||
|
||
.item-custom-card-empty {
|
||
margin: 0;
|
||
padding: 12px 14px;
|
||
border-radius: 12px;
|
||
background: rgba(255, 255, 255, 0.04);
|
||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||
color: rgba(255, 255, 255, 0.72);
|
||
font-size: 0.88em;
|
||
}
|
||
|
||
.item-custom-card.is-hidden-by-search,
|
||
.item-custom-card.is-hidden-by-type {
|
||
display: none;
|
||
}
|
||
|
||
.ship-presets-dialog {
|
||
background: linear-gradient(180deg, rgba(17, 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);
|
||
}
|
||
|
||
.ship-presets-dialog h3 {
|
||
font-size: 1.75em;
|
||
letter-spacing: 0.08em;
|
||
}
|
||
|
||
.ship-presets-dialog > div {
|
||
padding: 22px 26px 26px;
|
||
}
|
||
|
||
.ship-presets-empty,
|
||
.ship-presets-error {
|
||
margin: 0 0 18px;
|
||
padding: 12px 14px !important;
|
||
border-radius: 10px;
|
||
font-size: 0.95em;
|
||
text-align: left !important;
|
||
}
|
||
|
||
|
||
.ship-presets-empty {
|
||
background: rgba(255, 255, 255, 0.06);
|
||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||
}
|
||
|
||
.ship-presets-error {
|
||
background: rgba(140, 32, 32, 0.18);
|
||
border: 1px solid rgba(255, 88, 88, 0.25);
|
||
color: #ffbdbd;
|
||
}
|
||
|
||
.ship-presets-filter-bar {
|
||
display: flex;
|
||
align-items: flex-end;
|
||
gap: 16px;
|
||
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;
|
||
}
|
||
|
||
.ship-presets-filter-group {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
min-width: 240px;
|
||
flex: 1 1 240px;
|
||
}
|
||
|
||
.ship-presets-filter-label {
|
||
margin: 0;
|
||
font-size: 0.8em;
|
||
font-weight: 700;
|
||
letter-spacing: 0.08em;
|
||
text-transform: uppercase;
|
||
color: rgba(255, 255, 255, 0.88);
|
||
}
|
||
|
||
.ship-presets-filter-select {
|
||
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;
|
||
}
|
||
|
||
.ship-presets-filter-select:disabled {
|
||
opacity: 0.55;
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
.ship-presets-filter-select:focus-visible {
|
||
outline: 2px solid rgba(162, 155, 120, 0.45);
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
.ship-presets-filter-status {
|
||
margin: 0 0 0 auto;
|
||
font-size: 0.85em;
|
||
color: rgba(255, 255, 255, 0.7);
|
||
flex: 1 1 220px;
|
||
text-align: right;
|
||
align-self: center;
|
||
}
|
||
|
||
.ship-presets-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||
gap: 18px;
|
||
max-height: 68vh;
|
||
overflow-y: auto;
|
||
padding-right: 4px;
|
||
}
|
||
|
||
.ship-preset-card {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
min-height: 290px;
|
||
padding: 18px;
|
||
border-radius: 16px;
|
||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.025));
|
||
border: 1px solid rgba(162, 155, 120, 0.22);
|
||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.22);
|
||
gap: 14px;
|
||
}
|
||
|
||
.ship-preset-card-header {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
.ship-preset-card-manufacturer {
|
||
margin: 0;
|
||
font-size: 0.74em;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.14em;
|
||
color: rgba(162, 155, 120, 0.95);
|
||
}
|
||
|
||
.ship-preset-card-name {
|
||
margin: 0;
|
||
font-size: 1.35em;
|
||
line-height: 1.2;
|
||
color: #ffffff;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.ship-preset-card-meta {
|
||
margin: 0;
|
||
font-size: 0.78em;
|
||
color: rgba(255, 255, 255, 0.68);
|
||
}
|
||
|
||
.ship-preset-card-description {
|
||
margin: 0;
|
||
font-size: 0.88em;
|
||
line-height: 1.6;
|
||
color: rgba(255, 255, 255, 0.82);
|
||
flex: 1;
|
||
}
|
||
|
||
.ship-preset-card-link {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 10px 14px;
|
||
border-radius: 999px;
|
||
border: 1px solid rgba(162, 155, 120, 0.4);
|
||
background: rgba(162, 155, 120, 0.12);
|
||
color: #f6f1dc;
|
||
font-size: 0.76em;
|
||
font-weight: 700;
|
||
letter-spacing: 0.08em;
|
||
text-transform: uppercase;
|
||
text-decoration: none;
|
||
transition: background 0.18s ease, transform 0.18s ease;
|
||
}
|
||
|
||
.ship-preset-card-link:hover,
|
||
.ship-preset-card-link:focus-visible {
|
||
background: rgba(162, 155, 120, 0.22);
|
||
transform: translateY(-1px);
|
||
outline: none;
|
||
}
|
||
|
||
.ship-preset-card.is-hidden-by-ship-filter {
|
||
display: none;
|
||
}
|
||
|
||
|
||
@media (max-width: 1100px) {
|
||
.modal-scan-reference,
|
||
.modal-ship-presets,
|
||
.modal-item-custom {
|
||
width: 96%;
|
||
min-width: 0;
|
||
}
|
||
|
||
.scan-reference-dialog h3,
|
||
.ship-presets-dialog h3,
|
||
.item-custom-dialog h3 {
|
||
font-size: 1.2em;
|
||
}
|
||
|
||
.scan-reference-filter-bar {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
}
|
||
|
||
.scan-reference-filter-status {
|
||
text-align: left;
|
||
}
|
||
|
||
.ship-presets-filter-bar {
|
||
align-items: stretch;
|
||
}
|
||
|
||
.ship-presets-filter-status {
|
||
margin-left: 0;
|
||
text-align: left;
|
||
}
|
||
|
||
.ship-presets-grid {
|
||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||
}
|
||
|
||
.item-custom-filter-top {
|
||
align-items: stretch;
|
||
}
|
||
|
||
.item-custom-filter-status {
|
||
text-align: left;
|
||
white-space: normal;
|
||
}
|
||
|
||
.item-custom-card {
|
||
grid-template-columns: 52px minmax(280px, 1.9fr) minmax(220px, 1.3fr);
|
||
gap: 10px;
|
||
padding: 7px 10px;
|
||
}
|
||
|
||
.item-custom-card-preview {
|
||
left: 62px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 720px) {
|
||
.item-custom-dialog {
|
||
max-height: 92vh;
|
||
}
|
||
|
||
.item-custom-grid {
|
||
min-height: min(42vh, 340px);
|
||
}
|
||
|
||
.ship-presets-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.ship-preset-card {
|
||
min-height: 0;
|
||
}
|
||
|
||
.item-custom-filter-top,
|
||
.item-custom-search-wrap,
|
||
.item-custom-type-filters {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
}
|
||
|
||
.item-custom-filter-status {
|
||
text-align: left;
|
||
}
|
||
|
||
.item-custom-card {
|
||
grid-template-columns: 52px minmax(0, 1fr);
|
||
padding: 8px;
|
||
gap: 8px;
|
||
}
|
||
|
||
.item-custom-card-media {
|
||
width: 48px !important;
|
||
height: 48px !important;
|
||
min-width: 48px;
|
||
min-height: 48px;
|
||
}
|
||
|
||
.item-custom-card-stats {
|
||
grid-column: 1 / -1;
|
||
}
|
||
|
||
.item-custom-card-stats-header {
|
||
justify-content: flex-start;
|
||
}
|
||
|
||
.item-custom-card-preview {
|
||
display: none;
|
||
}
|
||
|
||
.item-custom-stat-chip {
|
||
width: 100%;
|
||
justify-content: space-between;
|
||
padding: 6px 14px !important;
|
||
padding-left: 14px !important;
|
||
padding-right: 14px !important;
|
||
}
|
||
|
||
.item-custom-stat-name {
|
||
white-space: normal;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
<?php if ($has_member_access): ?>
|
||
<div class="assets-div-menu">
|
||
<a href="#" class="md-trigger" data-modal="modal-ScanReference">Signatures de minage</a>
|
||
<a href="#" class="md-trigger" data-modal="modal-ShipPresets">Presets de vaisseaux</a>
|
||
<a href="#" class="md-trigger" data-modal="modal-ItemCustom">Objet(s) personnalisé(s)</a>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div class="connexion-div-menu <?php echo $is_authenticated ? 'is-authenticated' : 'md-trigger'; ?>" data-login-label="Connexion" <?php echo $is_authenticated ? '' : 'data-modal="modal-Login"'; ?> id="accountPanel">
|
||
<span id="accountLabel"><?php echo htmlspecialchars($is_authenticated ? $session_cl_auth_user : 'Connexion', ENT_QUOTES, 'UTF-8'); ?></span>
|
||
<span class="connexion-actions" id="accountActions" <?php echo $is_authenticated ? '' : 'hidden'; ?>>
|
||
<a id="adminLink" href="admin.php" <?php echo $has_member_access ? '' : 'hidden'; ?>>Admin</a>
|
||
<a id="logoutLink" href="logout.php">Déconnexion</a>
|
||
</span>
|
||
</div>
|
||
|
||
<div class="se-switch switch-center" role="group" aria-label="Choix entre FR et EN">
|
||
<a class="se-switch__btn is-active" href="index.php" data-site="se1" aria-current="page">🇫🇷</a>
|
||
<a class="se-switch__btn" href="index-en.php" data-site="se2">🇬🇧</a>
|
||
</div>
|
||
|
||
<div class="md-modal md-effect-1" id="modal-Login">
|
||
<div class="md-content">
|
||
<h3>
|
||
<img class="float-left" src="img/icon_bops.png" width="48" height="48" alt="" />
|
||
INTERFACE DE CONNEXION
|
||
<a class="frame-icon-close md-close float-right" href="#"><img src="img/icon_close.png" width="48" height="48" alt="" /></a>
|
||
</h3>
|
||
<div>
|
||
<p class="txt-center">Entrer vos identifiants pour acceder à l'espace sécurisé.*</p>
|
||
<form class="js-login-form" method="post" action="login.php">
|
||
<div>
|
||
<p class="txt-center"><input class="connexion-champ" id="idr" type="text" name="cl_auth_user" placeholder="RID" required /></p>
|
||
<p class="txt-center"><input class="connexion-champ" id="pwr" type="password" name="cl_auth_pass" placeholder="MOT DE PASSE" required /></p>
|
||
</div>
|
||
<div>
|
||
<p class="txt-center"><input class="connexion-bouton" type="submit" value="S'authentifier" /></p>
|
||
<p class="txt-center login-status" id="loginStatus" aria-live="polite"></p>
|
||
</div>
|
||
</form>
|
||
<p class="txt-center txt-s10">* Accès sous haute surveillance. En confirmant vos identifiants, vous acceptez les protocoles de sécurité de l'initiative R.E.A.C.T. Toute infraction aux protocoles est passible de sanctions.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="md-modal md-effect-1" id="modal-About">
|
||
<div class="md-content">
|
||
<h3>
|
||
<img class="float-left" src="img/icon_bops.png" width="48" height="48" alt="" />
|
||
EN SAVOIR PLUS
|
||
<a class="frame-icon-close md-close float-right" href="#"><img src="img/icon_close.png" width="48" height="48" alt="" /></a>
|
||
</h3>
|
||
<div>
|
||
<img class="float-left" src="img/fl_security.png" width="300" height="460" alt="" />
|
||
<p>La sécurité et la protection des intérêts impériaux sont des priorités absolues pour l’agence.</p>
|
||
<p>En tant que garante de l’ordre dans les zones sous juridiction de l’UEE, l’agence BOPS s'engage à prévenir, neutraliser et répondre efficacement à toutes les formes de menaces, qu'elles soient internes ou externes aux territoires de l'Empire.</p>
|
||
<p>Cette mission repose sur une approche combinant vigilance, réactivité et expertise tactique, afin d’assurer la stabilité, la sécurité des citoyens et le respect des lois impériales.</p>
|
||
<p>Chaque opération est conçue pour inspirer confiance aux populations locales tout en projetant une image de force et de discipline au sein de l’univers connu.</p>
|
||
<p class="ul-style">
|
||
— Surveillance active des secteurs critiques pour dissuader les menaces potentielles.</br>
|
||
— Protection rapprochée de convois, personnalités importantes ou cargaisons sensibles.</br>
|
||
— Neutralisation de vaisseaux hostiles ou suspects, avec récupération d’actifs stratégiques.</br>
|
||
— Ciblage et capture ou élimination de fugitifs dangereux, conformément aux lois impériales.</br>
|
||
— Protection des civils en détresse et aide aux infrastructures endommagées.</br>
|
||
— Collecte et analyse d’informations sur des activités suspectes, incidents ou organisations hostiles.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<?php if ($has_member_access): ?>
|
||
<div class="md-modal md-effect-1 modal-ship-presets" id="modal-ShipPresets">
|
||
<div class="md-content ship-presets-dialog">
|
||
<h3>
|
||
<img class="float-left" src="img/icon_bops.png" width="48" height="48" alt="" />
|
||
PRESETS DE VAISSEAUX
|
||
<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 ($ship_preset_error !== null): ?>
|
||
<p class="ship-presets-error"><?php echo htmlspecialchars($ship_preset_error, ENT_QUOTES, 'UTF-8'); ?></p>
|
||
<?php elseif ($ship_preset_rows === []): ?>
|
||
<p class="ship-presets-empty">Aucun preset de vaisseau n'est enregistré pour le moment.</p>
|
||
<?php else: ?>
|
||
<div class="ship-presets-filter-bar">
|
||
<div class="ship-presets-filter-group">
|
||
<label class="ship-presets-filter-label" for="shipPresetManufacturerFilter">Filtrer par manufacture</label>
|
||
<select id="shipPresetManufacturerFilter" class="ship-presets-filter-select">
|
||
<option value="">Toutes les manufactures</option>
|
||
<?php foreach ($ship_preset_manufacturers as $ship_preset_manufacturer): ?>
|
||
<option value="<?php echo htmlspecialchars($ship_preset_manufacturer, ENT_QUOTES, 'UTF-8'); ?>"><?php echo htmlspecialchars($ship_preset_manufacturer, ENT_QUOTES, 'UTF-8'); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
<div class="ship-presets-filter-group">
|
||
<label class="ship-presets-filter-label" for="shipPresetShipFilter">Filtrer par vaisseau</label>
|
||
<select id="shipPresetShipFilter" class="ship-presets-filter-select" disabled>
|
||
<option value="">Choisis d'abord une manufacture</option>
|
||
</select>
|
||
</div>
|
||
<p class="ship-presets-filter-status" id="shipPresetFilterStatus"></p>
|
||
</div>
|
||
<div class="ship-presets-grid" id="shipPresetsGrid">
|
||
<?php foreach ($ship_preset_rows as $ship_preset_row): ?>
|
||
<article class="ship-preset-card" data-manufacturer="<?php echo htmlspecialchars($ship_preset_row['manufacturer'], ENT_QUOTES, 'UTF-8'); ?>" data-ship-name="<?php echo htmlspecialchars($ship_preset_row['name'], ENT_QUOTES, 'UTF-8'); ?>">
|
||
<div class="ship-preset-card-header">
|
||
<p class="ship-preset-card-manufacturer"><?php echo htmlspecialchars($ship_preset_row['manufacturer'], ENT_QUOTES, 'UTF-8'); ?></p>
|
||
<h4 class="ship-preset-card-name"><?php echo htmlspecialchars($ship_preset_row['name'], ENT_QUOTES, 'UTF-8'); ?></h4>
|
||
<p class="ship-preset-card-meta">Créé par <?php echo htmlspecialchars($ship_preset_row['creator'], ENT_QUOTES, 'UTF-8'); ?></p>
|
||
</div>
|
||
<p class="ship-preset-card-description"><?php echo htmlspecialchars($ship_preset_row['description'], ENT_QUOTES, 'UTF-8'); ?></p>
|
||
<a href="<?php echo htmlspecialchars($ship_preset_row['link'], ENT_QUOTES, 'UTF-8'); ?>" target="_blank" rel="noopener noreferrer" class="ship-preset-card-link">Voir la configuration</a>
|
||
</article>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<?php endif; ?>
|
||
|
||
|
||
<?php if ($has_member_access): ?>
|
||
<div class="md-modal md-effect-1 modal-item-custom" id="modal-ItemCustom">
|
||
<div class="md-content item-custom-dialog">
|
||
<h3>
|
||
<img class="float-left" src="img/icon_bops.png" width="48" height="48" alt="" />
|
||
OBJET(S) PERSONNALISÉ(S)
|
||
<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 ($item_custom_public_error !== null): ?>
|
||
<p class="item-custom-error"><?php echo htmlspecialchars($item_custom_public_error, ENT_QUOTES, 'UTF-8'); ?></p>
|
||
<?php elseif ($item_custom_public_rows === []): ?>
|
||
<p class="item-custom-empty">Aucun objet Item Custom n'est disponible pour le moment.</p>
|
||
<?php else: ?>
|
||
<div class="item-custom-filter-bar">
|
||
<div class="item-custom-filter-top">
|
||
<div class="item-custom-search-wrap">
|
||
<input type="search" id="itemCustomSearch" class="item-custom-search-input" placeholder="Rechercher un objet, un créateur ou une statistique..." autocomplete="off">
|
||
<button type="button" id="itemCustomSearchReset" class="item-custom-reset-btn">Réinitialiser</button>
|
||
</div>
|
||
<p class="item-custom-filter-status" id="itemCustomSearchStatus"></p>
|
||
</div>
|
||
<?php if ($item_custom_public_types !== []): ?>
|
||
<div class="item-custom-type-filters" id="itemCustomTypeFilters">
|
||
<span class="item-custom-type-label">Filtrer par type</span>
|
||
<div class="item-custom-type-options">
|
||
<?php foreach ($item_custom_public_types as $item_custom_public_type): ?>
|
||
<label class="item-custom-type-chip">
|
||
<input type="checkbox" class="item-custom-type-checkbox" value="<?php echo htmlspecialchars($item_custom_public_type, ENT_QUOTES, 'UTF-8'); ?>">
|
||
<span><?php echo htmlspecialchars($item_custom_public_type, ENT_QUOTES, 'UTF-8'); ?></span>
|
||
</label>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
<div class="item-custom-grid" id="itemCustomGrid">
|
||
<?php foreach ($item_custom_public_rows as $item_custom_public_row): ?>
|
||
<?php $item_custom_stat_count = count($item_custom_public_row['stats']); ?>
|
||
<article class="item-custom-card" data-item-search="<?php echo htmlspecialchars($item_custom_public_row['search'], ENT_QUOTES, 'UTF-8'); ?>" data-item-type="<?php echo htmlspecialchars($item_custom_public_row['type'] !== '' ? $item_custom_public_row['type'] : 'Type inconnu', ENT_QUOTES, 'UTF-8'); ?>">
|
||
<div class="item-custom-card-media">
|
||
<img src="https://cstone.space/uifimages/<?php echo htmlspecialchars($item_custom_public_row['uuid'], ENT_QUOTES, 'UTF-8'); ?>.png" class="item-custom-card-thumb" alt="Aperçu de <?php echo htmlspecialchars($item_custom_public_row['name'], ENT_QUOTES, 'UTF-8'); ?>" loading="lazy" onerror="this.closest('.item-custom-card-media').classList.add('is-image-missing'); this.remove();">
|
||
<div class="item-custom-card-preview" aria-hidden="true">
|
||
<img src="https://cstone.space/uifimages/<?php echo htmlspecialchars($item_custom_public_row['uuid'], ENT_QUOTES, 'UTF-8'); ?>.png" alt="" onerror="this.closest('.item-custom-card-media').classList.add('is-image-missing'); this.closest('.item-custom-card-preview').remove();">
|
||
</div>
|
||
</div>
|
||
<div class="item-custom-card-main">
|
||
<p class="item-custom-card-type"><?php echo htmlspecialchars(trim(($item_custom_public_row['type'] !== '' ? $item_custom_public_row['type'] : 'Type inconnu') . ($item_custom_public_row['subtype'] !== '' ? ' / ' . $item_custom_public_row['subtype'] : '')), ENT_QUOTES, 'UTF-8'); ?></p>
|
||
<h4 class="item-custom-card-name"><?php echo htmlspecialchars($item_custom_public_row['name'], ENT_QUOTES, 'UTF-8'); ?></h4>
|
||
<p class="item-custom-card-meta">Créé par <?php echo htmlspecialchars($item_custom_public_row['creator'], ENT_QUOTES, 'UTF-8'); ?></p>
|
||
</div>
|
||
<div class="item-custom-card-stats">
|
||
<div class="item-custom-card-stats-header">
|
||
<span class="item-custom-card-count"><?php echo $item_custom_stat_count; ?> stat<?php echo $item_custom_stat_count > 1 ? 's' : ''; ?></span>
|
||
</div>
|
||
<?php if ($item_custom_stat_count === 0): ?>
|
||
<p class="item-custom-card-empty">Aucune statistique personnalisée n'a encore été enregistrée pour cet objet.</p>
|
||
<?php else: ?>
|
||
<ul class="item-custom-stats-list">
|
||
<?php foreach ($item_custom_public_row['stats'] as $item_custom_stat): ?>
|
||
<?php
|
||
$item_custom_stat_preview = trim((string) ($item_custom_stat['preview'] ?? ''));
|
||
$item_custom_stat_sign_class = 'sign-neutral';
|
||
if ($item_custom_stat_preview !== '') {
|
||
if (strpos($item_custom_stat_preview, '+') === 0) {
|
||
$item_custom_stat_sign_class = 'sign-plus';
|
||
} elseif (strpos($item_custom_stat_preview, '-') === 0) {
|
||
$item_custom_stat_sign_class = 'sign-minus';
|
||
}
|
||
}
|
||
?>
|
||
<li class="item-custom-stat-chip <?php echo $item_custom_stat_sign_class; ?>">
|
||
<span class="item-custom-stat-name"><?php echo htmlspecialchars($item_custom_stat['name'], ENT_QUOTES, 'UTF-8'); ?></span>
|
||
<span class="item-custom-stat-value"><?php echo htmlspecialchars($item_custom_stat['preview'], ENT_QUOTES, 'UTF-8'); ?></span>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
<?php endif; ?>
|
||
</div>
|
||
</article>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<?php endif; ?>
|
||
|
||
<?php if ($has_member_access): ?>
|
||
<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>
|
||
<?php endif; ?>
|
||
|
||
<div class="center-page-bops"></div>
|
||
|
||
<div class="center-div-menu">
|
||
<div class="padding50">
|
||
|
||
<p class="txt-center txt-bold txt-s40 small-caps padding25 txt-or">Rapid Emergency & Action Combat Team</p>
|
||
<!-- <p class="txt-center txt-bold txt-italic txt-s20 padding15 txt-or"><span class="padding5">SÉCURITÉ</span> —— <span class="padding5">INTELLIGENCE</span> —— <span class="padding5">SAUVETAGE</span></p> -->
|
||
<p class="txt-justify padding5">Fondée pour combattre la criminalité extrême à travers l’Univers, la R.E.A.C.T. est un label opérationnel indépendant. Nous unissons des pilotes dévoués de tous horizons pour neutraliser les menaces là où la loi fait défaut.</p>
|
||
<p class="txt-center txt-bold txt-s22 padding25 txt-or">—————— La R.E.A.C.T. n’est pas une organisation, mais un standard tactique ——————</p>
|
||
<p class="txt-justify padding5">C’est une initiative inter-organisations conçue pour les joueurs qui partagent la même vision : protéger les citoyens et les PNJs des entités hostiles. Porter l’insigne R.E.A.C.T. ne signifie pas quitter votre organisation ; cela signifie rejoindre un réseau d'intervention rapide.</p>
|
||
</div>
|
||
<div class="center-div-menu-flex txt-bold">
|
||
<div class="menu-item md-trigger" data-modal="modal-About"><a href="#">> EN SAVOIR PLUS <</a></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="black-filter"></div>
|
||
|
||
<!-- Vidéo de fond -->
|
||
<div class="video-container" aria-hidden="true">
|
||
<iframe
|
||
id="react-video"
|
||
src="https://www.youtube-nocookie.com/embed/tFDqWOqm1G8?controls=0&autoplay=1&mute=1&playsinline=1&loop=1&playlist=tFDqWOqm1G8&cc_load_policy=0&iv_load_policy=3&modestbranding=1&rel=0&enablejsapi=1"
|
||
title="Présentation R.E.A.C.T — YouTube"
|
||
loading="lazy"
|
||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; fullscreen"
|
||
allowfullscreen
|
||
referrerpolicy="strict-origin-when-cross-origin">
|
||
</iframe>
|
||
</div>
|
||
|
||
<div class="md-overlay"></div><!-- the overlay element -->
|
||
|
||
<!-- classie.js by @desandro: https://github.com/desandro/classie -->
|
||
<script src="js/classie.js"></script>
|
||
<script src="js/modalEffects.js"></script>
|
||
<script src="js/auth.js"></script>
|
||
|
||
<!-- for the blur effect -->
|
||
<!-- by @derSchepp https://github.com/Schepp/CSS-Filters-Polyfill -->
|
||
<script>
|
||
// this is important for IEs
|
||
var polyfilter_scriptpath = '/js/';
|
||
</script>
|
||
<script src="js/cssParser.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 n’afficher 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();
|
||
}
|
||
|
||
function clearSelection() {
|
||
selectedIds.clear();
|
||
rows.forEach((row) => row.classList.remove('is-selected'));
|
||
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);
|
||
clearSelection();
|
||
});
|
||
|
||
clearButton.addEventListener('click', function () {
|
||
saveFilter([]);
|
||
applyFilter([]);
|
||
});
|
||
|
||
|
||
applyFilter(loadFilter());
|
||
})();
|
||
</script>
|
||
|
||
|
||
<script>
|
||
(function initItemCustomSearch() {
|
||
const searchInput = document.getElementById('itemCustomSearch');
|
||
const resetButton = document.getElementById('itemCustomSearchReset');
|
||
const status = document.getElementById('itemCustomSearchStatus');
|
||
const grid = document.getElementById('itemCustomGrid');
|
||
const typeCheckboxes = Array.from(document.querySelectorAll('.item-custom-type-checkbox'));
|
||
|
||
if (!searchInput || !resetButton || !status || !grid) {
|
||
return;
|
||
}
|
||
|
||
const cards = Array.from(grid.querySelectorAll('.item-custom-card'));
|
||
|
||
function normalizeValue(value) {
|
||
return String(value || '')
|
||
.toLowerCase()
|
||
.normalize('NFD')
|
||
.replace(/[̀-ͯ]/g, '')
|
||
.trim();
|
||
}
|
||
|
||
function getSelectedTypes() {
|
||
return typeCheckboxes
|
||
.filter((checkbox) => checkbox.checked)
|
||
.map((checkbox) => ({
|
||
label: checkbox.value,
|
||
value: normalizeValue(checkbox.value)
|
||
}));
|
||
}
|
||
|
||
function applyFilter() {
|
||
const query = normalizeValue(searchInput.value);
|
||
const selectedTypes = getSelectedTypes();
|
||
const selectedTypeSet = new Set(selectedTypes.map((type) => type.value));
|
||
let visibleCount = 0;
|
||
|
||
cards.forEach((card) => {
|
||
const haystack = normalizeValue(card.dataset.itemSearch || '');
|
||
const itemType = normalizeValue(card.dataset.itemType || '');
|
||
const matchesQuery = query === '' || haystack.includes(query);
|
||
const matchesType = selectedTypeSet.size === 0 || selectedTypeSet.has(itemType);
|
||
const isVisible = matchesQuery && matchesType;
|
||
card.classList.toggle('is-hidden-by-search', !matchesQuery);
|
||
card.classList.toggle('is-hidden-by-type', matchesQuery && !matchesType);
|
||
if (isVisible) {
|
||
visibleCount += 1;
|
||
}
|
||
});
|
||
|
||
if (query === '' && selectedTypeSet.size === 0) {
|
||
status.textContent = visibleCount + ' objet(s) affiché(s) sur ' + cards.length + '.';
|
||
return;
|
||
}
|
||
|
||
const activeFilters = [];
|
||
if (query !== '') {
|
||
activeFilters.push('la recherche « ' + searchInput.value.trim() + ' »');
|
||
}
|
||
if (selectedTypes.length > 0) {
|
||
activeFilters.push((selectedTypes.length > 1 ? 'les types ' : 'le type ') + selectedTypes.map((type) => '« ' + type.label + ' »').join(', '));
|
||
}
|
||
|
||
status.textContent = visibleCount + ' objet(s) correspondent à ' + activeFilters.join(' + ') + '.';
|
||
}
|
||
|
||
searchInput.addEventListener('input', applyFilter);
|
||
typeCheckboxes.forEach((checkbox) => {
|
||
checkbox.addEventListener('change', applyFilter);
|
||
});
|
||
resetButton.addEventListener('click', function () {
|
||
searchInput.value = '';
|
||
typeCheckboxes.forEach((checkbox) => {
|
||
checkbox.checked = false;
|
||
});
|
||
applyFilter();
|
||
searchInput.focus();
|
||
});
|
||
|
||
applyFilter();
|
||
})();
|
||
</script>
|
||
|
||
<script>
|
||
(function initShipPresetFilter() {
|
||
const manufacturerSelect = document.getElementById('shipPresetManufacturerFilter');
|
||
const shipSelect = document.getElementById('shipPresetShipFilter');
|
||
const status = document.getElementById('shipPresetFilterStatus');
|
||
const grid = document.getElementById('shipPresetsGrid');
|
||
|
||
if (!manufacturerSelect || !shipSelect || !status || !grid) {
|
||
return;
|
||
}
|
||
|
||
const cards = Array.from(grid.querySelectorAll('.ship-preset-card'));
|
||
const manufacturerToShips = new Map();
|
||
|
||
cards.forEach((card) => {
|
||
const manufacturer = String(card.dataset.manufacturer || '').trim();
|
||
const shipName = String(card.dataset.shipName || '').trim();
|
||
|
||
if (!manufacturerToShips.has(manufacturer)) {
|
||
manufacturerToShips.set(manufacturer, new Set());
|
||
}
|
||
|
||
if (shipName !== '') {
|
||
manufacturerToShips.get(manufacturer).add(shipName);
|
||
}
|
||
});
|
||
|
||
function setShipOptions(manufacturer) {
|
||
const previousValue = shipSelect.value;
|
||
shipSelect.innerHTML = '';
|
||
|
||
if (manufacturer === '') {
|
||
shipSelect.disabled = true;
|
||
shipSelect.append(new Option("Choisis d'abord une manufacture", ''));
|
||
shipSelect.value = '';
|
||
return;
|
||
}
|
||
|
||
shipSelect.disabled = false;
|
||
shipSelect.append(new Option('Tous les vaisseaux de cette manufacture', ''));
|
||
|
||
const ships = Array.from(manufacturerToShips.get(manufacturer) || []);
|
||
ships.sort((a, b) => a.localeCompare(b, 'fr', { sensitivity: 'base' }));
|
||
|
||
ships.forEach((shipName) => {
|
||
shipSelect.append(new Option(shipName, shipName));
|
||
});
|
||
|
||
shipSelect.value = ships.includes(previousValue) ? previousValue : '';
|
||
}
|
||
|
||
function refreshStatus() {
|
||
const visibleCards = cards.filter((card) => !card.classList.contains('is-hidden-by-ship-filter'));
|
||
const visibleShips = new Set(
|
||
visibleCards
|
||
.map((card) => String(card.dataset.shipName || '').trim())
|
||
.filter(Boolean)
|
||
);
|
||
const selectedManufacturer = manufacturerSelect.value;
|
||
const selectedShip = shipSelect.value;
|
||
|
||
if (selectedManufacturer !== '' && selectedShip !== '') {
|
||
status.textContent = visibleCards.length + ' preset(s) affiché(s) pour ' + selectedShip + ' chez ' + selectedManufacturer + '.';
|
||
return;
|
||
}
|
||
|
||
if (selectedManufacturer !== '') {
|
||
status.textContent = visibleCards.length + ' preset(s) affiché(s) pour ' + visibleShips.size + ' vaisseau(x) chez ' + selectedManufacturer + '.';
|
||
return;
|
||
}
|
||
|
||
status.textContent = visibleCards.length + ' preset(s) affiché(s) sur ' + cards.length + ' pour ' + visibleShips.size + ' vaisseau(x).';
|
||
}
|
||
|
||
function applyFilter() {
|
||
const selectedManufacturer = manufacturerSelect.value;
|
||
const selectedShip = shipSelect.value;
|
||
|
||
cards.forEach((card) => {
|
||
const manufacturer = String(card.dataset.manufacturer || '').trim();
|
||
const shipName = String(card.dataset.shipName || '').trim();
|
||
const hideByManufacturer = selectedManufacturer !== '' && manufacturer !== selectedManufacturer;
|
||
const hideByShip = selectedShip !== '' && shipName !== selectedShip;
|
||
card.classList.toggle('is-hidden-by-ship-filter', hideByManufacturer || hideByShip);
|
||
});
|
||
|
||
refreshStatus();
|
||
}
|
||
|
||
manufacturerSelect.addEventListener('change', function () {
|
||
setShipOptions(manufacturerSelect.value);
|
||
applyFilter();
|
||
});
|
||
|
||
shipSelect.addEventListener('change', applyFilter);
|
||
setShipOptions(manufacturerSelect.value);
|
||
applyFilter();
|
||
})();
|
||
</script>
|
||
|
||
<script>
|
||
// On ajoute dynamiquement l'origine à l'URL de l'iframe (recommandé par l'API YouTube)
|
||
(function attachOrigin(){
|
||
const iframe = document.getElementById('react-video');
|
||
const url = new URL(iframe.src);
|
||
if (!url.searchParams.has('origin')) {
|
||
url.searchParams.set('origin', window.location.origin);
|
||
iframe.src = url.toString();
|
||
}
|
||
})();
|
||
|
||
// Utilitaires pour parler au lecteur via postMessage (API YouTube)
|
||
function ytCommand(func, args = []) {
|
||
const iframe = document.getElementById('react-video');
|
||
if (!iframe || !iframe.contentWindow) return;
|
||
iframe.contentWindow.postMessage(JSON.stringify({ event: 'command', func, args }), '*');
|
||
}
|
||
|
||
// Au premier geste utilisateur : on remet le son et on met le volume à 50 %
|
||
function enableSoundOnce() {
|
||
ytCommand('unMute');
|
||
ytCommand('setVolume', [50]);
|
||
|
||
// Masquer le bouton
|
||
const btn = document.getElementById('unmute-btn');
|
||
if (btn) btn.style.display = 'none';
|
||
|
||
// Retirer les écouteurs pour ne pas répéter l’action
|
||
window.removeEventListener('pointerdown', enableSoundOnce);
|
||
window.removeEventListener('keydown', enableSoundOnce);
|
||
window.removeEventListener('touchstart', enableSoundOnce, { passive: true });
|
||
}
|
||
|
||
// Bouton dédié
|
||
// document.getElementById('unmute-btn').addEventListener('click', enableSoundOnce);
|
||
|
||
// …ou n’importe quel premier geste sur la page
|
||
//window.addEventListener('pointerdown', enableSoundOnce, { once: true });
|
||
//window.addEventListener('keydown', enableSoundOnce, { once: true });
|
||
//window.addEventListener('touchstart', enableSoundOnce, { once: true, passive: true });
|
||
</script>
|
||
<div class="footer txt-s12 txt-center">
|
||
<p>
|
||
<a href="https://robertsspaceindustries.com/en/orgs/REACT" target="_blank" title="Notre page RSI"><img src="img/icon09b.png" width="48" height="48" alt="" /></a>
|
||
<a href="https://discord.gg/dAvST8E7Mq" target="_blank" title="Notre Discord"><img src="img/icon08b.png" width="48" height="48" alt="" /></a>
|
||
<a href="https://robertsspaceindustries.com" target="_blank" title="RSI"><img src="img/icon10.png" width="48" height="48" alt="" /></a>
|
||
</p>
|
||
<p>Copyright © 2025-<?php echo date('Y'); ?> | www.react-sc.fr | Tous droits réservés.</p>
|
||
</div>
|
||
</body>
|
||
|
||
</html>
|