1154 lines
63 KiB
PHP
1154 lines
63 KiB
PHP
<?php
|
||
require_once 'db/config.php';
|
||
session_start();
|
||
$db = db();
|
||
|
||
// Auth Check: Must be logged in and be admin
|
||
if (!isset($_SESSION['user_id'])) {
|
||
header("Location: auth.php?page=login");
|
||
exit;
|
||
}
|
||
|
||
$user_id = $_SESSION['user_id'];
|
||
$user_stmt = $db->prepare("SELECT role FROM users WHERE id = ?");
|
||
$user_stmt->execute([$user_id]);
|
||
$current_user = $user_stmt->fetch();
|
||
|
||
if (!$current_user || $current_user['role'] !== 'admin') {
|
||
die("Accès refusé. Cette console est réservée aux Administrateurs.");
|
||
}
|
||
|
||
$tab = isset($_GET['tab']) ? $_GET['tab'] : 'users';
|
||
|
||
// --- HANDLERS ---
|
||
|
||
// Handle User Role Update
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_user_role') {
|
||
$target_user_id = (int)$_POST['target_user_id'];
|
||
$new_role = $_POST['new_role'];
|
||
if (in_array($new_role, ['user', 'gm', 'admin'])) {
|
||
$stmt = $db->prepare("UPDATE users SET role = ? WHERE id = ?");
|
||
$stmt->execute([$new_role, $target_user_id]);
|
||
}
|
||
header("Location: admin.php?tab=users&success=1");
|
||
exit;
|
||
}
|
||
|
||
// Handle Celestial Object Type CRUD
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_object_type') {
|
||
$id = (int)$_POST['id'];
|
||
$name = $_POST['name'];
|
||
$slug = $_POST['slug'];
|
||
$icon = $_POST['icon'];
|
||
$description = $_POST['description'];
|
||
$modifier_ids = isset($_POST['modifiers']) ? $_POST['modifiers'] : [];
|
||
|
||
$image_url = null;
|
||
if ($id > 0) {
|
||
$stmt_img = $db->prepare("SELECT image_url FROM celestial_object_types WHERE id = ?");
|
||
$stmt_img->execute([$id]);
|
||
$image_url = $stmt_img->fetchColumn();
|
||
}
|
||
|
||
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
|
||
$ext = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
|
||
$filename = $slug . "_" . time() . "." . $ext;
|
||
$target = "assets/images/celestial/" . $filename;
|
||
if (move_uploaded_file($_FILES['image']['tmp_name'], $target)) {
|
||
$image_url = $target;
|
||
}
|
||
}
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE celestial_object_types SET name = ?, slug = ?, icon = ?, description = ?, image_url = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $icon, $description, $image_url, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO celestial_object_types (name, slug, icon, description, image_url) VALUES (?, ?, ?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $icon, $description, $image_url]);
|
||
$id = $db->lastInsertId();
|
||
}
|
||
|
||
// Sync modifiers
|
||
$db->prepare("DELETE FROM celestial_object_type_modifiers WHERE celestial_object_type_id = ?")->execute([$id]);
|
||
if (!empty($modifier_ids)) {
|
||
$ins = $db->prepare("INSERT INTO celestial_object_type_modifiers (celestial_object_type_id, modifier_id) VALUES (?, ?)");
|
||
foreach ($modifier_ids as $mid) {
|
||
$ins->execute([$id, (int)$mid]);
|
||
}
|
||
}
|
||
|
||
header("Location: admin.php?tab=objects&success=1");
|
||
exit;
|
||
}
|
||
|
||
if (isset($_GET['delete_object'])) {
|
||
$id = (int)$_GET['delete_object'];
|
||
$db->prepare("DELETE FROM celestial_object_types WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=objects&success=1");
|
||
exit;
|
||
}
|
||
|
||
// Handle Status CRUD
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_status') {
|
||
$id = (int)$_POST['id'];
|
||
$name = $_POST['name'];
|
||
$slug = $_POST['slug'];
|
||
$color = $_POST['color'];
|
||
$description = $_POST['description'];
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE celestial_object_statuses SET name = ?, slug = ?, color = ?, description = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $color, $description, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO celestial_object_statuses (name, slug, color, description) VALUES (?, ?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $color, $description]);
|
||
}
|
||
header("Location: admin.php?tab=statuses&success=1");
|
||
exit;
|
||
}
|
||
|
||
if (isset($_GET['delete_status'])) {
|
||
$id = (int)$_GET['delete_status'];
|
||
$db->prepare("DELETE FROM celestial_object_statuses WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=statuses&success=1");
|
||
exit;
|
||
}
|
||
|
||
// Handle Settlement Type CRUD
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_settlement_type') {
|
||
$id = (int)$_POST['id'];
|
||
$name = $_POST['name'];
|
||
$slug = $_POST['slug'];
|
||
$description = $_POST['description'];
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE settlement_types SET name = ?, slug = ?, description = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $description, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO settlement_types (name, slug, description) VALUES (?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $description]);
|
||
}
|
||
header("Location: admin.php?tab=settlement_types&success=1");
|
||
exit;
|
||
}
|
||
|
||
if (isset($_GET['delete_settlement_type'])) {
|
||
$id = (int)$_GET['delete_settlement_type'];
|
||
$db->prepare("DELETE FROM settlement_types WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=settlement_types&success=1");
|
||
exit;
|
||
}
|
||
|
||
// Handle Modifiers CRUD
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_modifier') {
|
||
$id = (int)$_POST['id'];
|
||
$name = $_POST['name'];
|
||
$slug = $_POST['slug'];
|
||
$type = $_POST['type'];
|
||
$description = $_POST['description'];
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE modifiers SET name = ?, slug = ?, type = ?, description = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $type, $description, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO modifiers (name, slug, type, description) VALUES (?, ?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $type, $description]);
|
||
}
|
||
header("Location: admin.php?tab=modifiers&success=1");
|
||
exit;
|
||
}
|
||
|
||
if (isset($_GET['delete_modifier'])) {
|
||
$id = (int)$_GET['delete_modifier'];
|
||
$db->prepare("DELETE FROM modifiers WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=modifiers&success=1");
|
||
exit;
|
||
}
|
||
|
||
// Handle Faction CRUD
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_faction') {
|
||
$id = (int)$_POST['id'];
|
||
$name = $_POST['name'];
|
||
$slug = $_POST['slug'];
|
||
$fa_icon = $_POST['fa_icon'];
|
||
$color = $_POST['color'];
|
||
$image_url = null;
|
||
if ($id > 0) {
|
||
$stmt_img = $db->prepare("SELECT image_url FROM factions WHERE id = ?");
|
||
$stmt_img->execute([$id]);
|
||
$image_url = $stmt_img->fetchColumn();
|
||
}
|
||
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
|
||
$ext = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
|
||
$filename = "faction_" . time() . "." . $ext;
|
||
$target = "assets/images/factions/" . $filename;
|
||
if (move_uploaded_file($_FILES['image']['tmp_name'], $target)) {
|
||
$image_url = $target;
|
||
}
|
||
}
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE factions SET name = ?, slug = ?, image_url = ?, fa_icon = ?, color = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $image_url, $fa_icon, $color, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO factions (name, slug, image_url, fa_icon, color) VALUES (?, ?, ?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $image_url, $fa_icon, $color]);
|
||
}
|
||
header("Location: admin.php?tab=factions&success=1");
|
||
exit;
|
||
}
|
||
|
||
if (isset($_GET['delete_faction'])) {
|
||
$id = (int)$_GET['delete_faction'];
|
||
$db->prepare("DELETE FROM factions WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=factions&success=1");
|
||
exit;
|
||
}
|
||
|
||
// Handle Resource CRUD
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_resource') {
|
||
$id = (int)$_POST['id'];
|
||
$name = $_POST['name'];
|
||
$slug = $_POST['slug'];
|
||
$icon = $_POST['icon'];
|
||
$description = $_POST['description'];
|
||
$show_in_header = isset($_POST["show_in_header"]) ? 1 : 0;
|
||
|
||
$image_url = null;
|
||
if ($id > 0) {
|
||
$stmt_img = $db->prepare("SELECT image_url FROM game_resources WHERE id = ?");
|
||
$stmt_img->execute([$id]);
|
||
$image_url = $stmt_img->fetchColumn();
|
||
}
|
||
|
||
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
|
||
$ext = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
|
||
$filename = "res_" . $slug . "_" . time() . "." . $ext;
|
||
if (!is_dir("assets/images/resources")) {
|
||
mkdir("assets/images/resources", 0775, true);
|
||
}
|
||
$target = "assets/images/resources/" . $filename;
|
||
if (move_uploaded_file($_FILES['image']['tmp_name'], $target)) {
|
||
$image_url = $target;
|
||
}
|
||
}
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE game_resources SET name = ?, slug = ?, icon = ?, description = ?, image_url = ?, show_in_header = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $icon, $description, $image_url, $show_in_header, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO game_resources (name, slug, icon, description, image_url, show_in_header) VALUES (?, ?, ?, ?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $icon, $description, $image_url, $show_in_header]);
|
||
}
|
||
|
||
header("Location: admin.php?tab=resources&success=1");
|
||
exit;
|
||
}
|
||
|
||
if (isset($_GET['delete_resource'])) {
|
||
$id = (int)$_GET['delete_resource'];
|
||
$db->prepare("DELETE FROM game_resources WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=resources&success=1");
|
||
exit;
|
||
}
|
||
|
||
// Handle Lootbox CRUD
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_lootbox') {
|
||
$id = (int)$_POST['id'];
|
||
$name = $_POST['name'];
|
||
$slug = $_POST['slug'];
|
||
$description = $_POST['description'];
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE lootboxes SET name = ?, slug = ?, description = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $description, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO lootboxes (name, slug, description) VALUES (?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $description]);
|
||
$id = $db->lastInsertId();
|
||
}
|
||
|
||
// Handle Rolls
|
||
$db->prepare("DELETE FROM lootbox_rolls WHERE lootbox_id = ?")->execute([$id]);
|
||
if (isset($_POST['rolls_count']) && is_array($_POST['rolls_count'])) {
|
||
$ins_roll = $db->prepare("INSERT INTO lootbox_rolls (lootbox_id, roll_count, probability) VALUES (?, ?, ?)");
|
||
foreach ($_POST['rolls_count'] as $idx => $rc) {
|
||
$prob = (float)$_POST['rolls_prob'][$idx];
|
||
if ($prob > 0) {
|
||
$ins_roll->execute([$id, (int)$rc, $prob]);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Handle Items
|
||
$db->prepare("DELETE FROM lootbox_items WHERE lootbox_id = ?")->execute([$id]);
|
||
if (isset($_POST['item_slug']) && is_array($_POST['item_slug'])) {
|
||
$ins_item = $db->prepare("INSERT INTO lootbox_items (lootbox_id, resource_slug, probability, quantity_min, quantity_max, is_guaranteed) VALUES (?, ?, ?, ?, ?, ?)");
|
||
foreach ($_POST['item_slug'] as $idx => $islug) {
|
||
$is_guaranteed = isset($_POST['item_is_guaranteed'][$idx]) ? (int)$_POST['item_is_guaranteed'][$idx] : 0;
|
||
$iprob = $is_guaranteed ? 100.00 : (float)$_POST['item_prob'][$idx];
|
||
|
||
if ($is_guaranteed || $iprob > 0) {
|
||
$qmin = (int)$_POST['item_qmin'][$idx];
|
||
$qmax = (int)$_POST['item_qmax'][$idx];
|
||
$ins_item->execute([$id, $islug ?: null, $iprob, $qmin, $qmax, $is_guaranteed]);
|
||
}
|
||
}
|
||
}
|
||
|
||
header("Location: admin.php?tab=lootboxes&success=1");
|
||
exit;
|
||
}
|
||
|
||
if (isset($_GET['delete_lootbox'])) {
|
||
$id = (int)$_GET['delete_lootbox'];
|
||
$db->prepare("DELETE FROM lootboxes WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=lootboxes&success=1");
|
||
exit;
|
||
}
|
||
|
||
// --- DATA FETCHING ---
|
||
$users_list = [];
|
||
$objects_list = [];
|
||
$statuses_list = [];
|
||
$settlement_types_list = [];
|
||
$modifiers_list = [];
|
||
$factions_list = [];
|
||
$resources_list = [];
|
||
$lootboxes_list = [];
|
||
|
||
if ($tab === 'users') {
|
||
$users_list = $db->query("SELECT id, username, email, role FROM users ORDER BY username ASC")->fetchAll();
|
||
} elseif ($tab === 'objects') {
|
||
$objects_list = $db->query("SELECT * FROM celestial_object_types ORDER BY name ASC")->fetchAll();
|
||
foreach ($objects_list as &$obj) {
|
||
$stmt = $db->prepare("SELECT modifier_id FROM celestial_object_type_modifiers WHERE celestial_object_type_id = ?");
|
||
$stmt->execute([$obj['id']]);
|
||
$obj['modifier_ids'] = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||
}
|
||
$modifiers_list = $db->query("SELECT * FROM modifiers ORDER BY type, name ASC")->fetchAll();
|
||
} elseif ($tab === 'statuses') {
|
||
$statuses_list = $db->query("SELECT * FROM celestial_object_statuses ORDER BY name ASC")->fetchAll();
|
||
} elseif ($tab === 'settlement_types') {
|
||
$settlement_types_list = $db->query("SELECT * FROM settlement_types ORDER BY name ASC")->fetchAll();
|
||
} elseif ($tab === 'modifiers') {
|
||
$modifiers_list = $db->query("SELECT * FROM modifiers ORDER BY type, name ASC")->fetchAll();
|
||
} elseif ($tab === 'factions') {
|
||
$factions_list = $db->query("SELECT * FROM factions ORDER BY name ASC")->fetchAll();
|
||
} elseif ($tab === 'resources') {
|
||
$resources_list = $db->query("SELECT * FROM game_resources ORDER BY name ASC")->fetchAll();
|
||
} elseif ($tab === 'lootboxes') {
|
||
$lootboxes_list = $db->query("SELECT * FROM lootboxes ORDER BY name ASC")->fetchAll();
|
||
$resources_list = $db->query("SELECT name, slug FROM game_resources ORDER BY name ASC")->fetchAll();
|
||
foreach ($lootboxes_list as &$lb) {
|
||
$stmt_r = $db->prepare("SELECT * FROM lootbox_rolls WHERE lootbox_id = ?");
|
||
$stmt_r->execute([$lb['id']]);
|
||
$lb['rolls'] = $stmt_r->fetchAll();
|
||
|
||
$stmt_i = $db->prepare("SELECT * FROM lootbox_items WHERE lootbox_id = ?");
|
||
$stmt_i->execute([$lb['id']]);
|
||
$lb['items'] = $stmt_i->fetchAll();
|
||
}
|
||
}
|
||
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Console Admin - Nexus</title>
|
||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
|
||
<link href="assets/css/custom.css?v=<?php echo time(); ?>" rel="stylesheet">
|
||
<style>
|
||
body { background: #000; color: #fff; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; }
|
||
header { background: #1a202c; padding: 10px 20px; border-bottom: 2px solid #2d3545; display: flex; justify-content: space-between; align-items: center; }
|
||
.nav-links a { color: #88c0d0; text-decoration: none; margin-right: 20px; font-weight: bold; font-size: 14px; }
|
||
.nav-links a:hover { color: #fff; }
|
||
.container { padding: 40px; max-width: 1400px; margin: 0 auto; }
|
||
|
||
.tabs { display: flex; gap: 5px; margin-bottom: 20px; border-bottom: 2px solid #2d3545; flex-wrap: wrap; }
|
||
.tab-link { padding: 10px 20px; text-decoration: none; color: #8c92a3; background: #0a0f1d; border: 1px solid #2d3545; border-bottom: none; font-weight: bold; font-size: 14px; }
|
||
.tab-link.active { background: #1a202c; color: #88c0d0; border-bottom: 2px solid #88c0d0; }
|
||
|
||
table { width: 100%; border-collapse: collapse; background: #0a0f1d; margin-top: 20px; }
|
||
th, td { border: 1px solid #2d3545; padding: 12px; text-align: left; }
|
||
th { background: #1a202c; color: #88c0d0; font-size: 13px; text-transform: uppercase; }
|
||
|
||
.form-card { background: #1e293b; padding: 20px; border: 1px solid #334155; margin-bottom: 30px; }
|
||
.form-group { margin-bottom: 15px; }
|
||
.form-group label { display: block; font-size: 12px; color: #8c92a3; margin-bottom: 5px; }
|
||
.form-group input, .form-group select, .form-group textarea { width: 100%; background: #0f172a; border: 1px solid #334155; color: #fff; padding: 8px; box-sizing: border-box; }
|
||
|
||
.btn { border: none; padding: 8px 15px; cursor: pointer; font-weight: bold; border-radius: 4px; font-size: 12px; }
|
||
.btn-add { background: #a3be8c; color: #000; }
|
||
.btn-edit { background: #ebcb8b; color: #000; }
|
||
.btn-del { background: #bf616a; color: #fff; text-decoration: none; }
|
||
.btn-ok { background: #88c0d0; color: #000; }
|
||
|
||
.success-msg { background: #a3be8c; color: #000; padding: 10px; margin-bottom: 20px; border-radius: 4px; font-weight: bold; }
|
||
|
||
.modifier-tag { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 10px; font-weight: bold; margin-right: 5px; margin-bottom: 5px; }
|
||
.tag-bonus { background: #a3be8c; color: #000; }
|
||
.tag-malus { background: #bf616a; color: #fff; }
|
||
|
||
.sub-form-row { display: flex; gap: 8px; margin-bottom: 5px; align-items: center; }
|
||
.sub-form-row .btn-del-row { flex: 0 0 30px; background: #bf616a; color: #fff; padding: 5px; border-radius: 4px; text-align: center; cursor: pointer; }
|
||
|
||
.sub-form-header { display: flex; gap: 8px; margin-bottom: 5px; font-size: 10px; color: #8c92a3; text-transform: uppercase; font-weight: bold; }
|
||
.sub-form-header .btn-del-row-placeholder { flex: 0 0 30px; }
|
||
|
||
/* Custom toggle switch */
|
||
.toggle-container { display: flex; align-items: center; gap: 5px; font-size: 9px; color: #8c92a3; flex: 0 0 100px; }
|
||
.switch { position: relative; display: inline-block; width: 40px; height: 20px; flex-shrink: 0; }
|
||
.switch input { opacity: 0; width: 0; height: 0; }
|
||
.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #334155; transition: .4s; border-radius: 20px; }
|
||
.slider:before { position: absolute; content: ""; height: 14px; width: 14px; left: 3px; bottom: 3px; background-color: white; transition: .4s; border-radius: 50%; }
|
||
input:checked + .slider { background-color: #a3be8c; }
|
||
input:checked + .slider:before { transform: translateX(20px); }
|
||
|
||
/* Color picker custom style */
|
||
.color-group { display: flex; gap: 5px; }
|
||
.color-picker-input { width: 45px !important; height: 34px !important; padding: 2px !important; border: 1px solid #334155 !important; background: #0f172a !important; cursor: pointer; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<header>
|
||
<div style="display: flex; align-items: center; gap: 20px;">
|
||
<h2 style="margin: 0; color: #bf616a;"><i class="fa-solid fa-shield-halved"></i> CONSOLE ADMIN</h2>
|
||
<nav class="nav-links">
|
||
<a href="index.php"><i class="fa-solid fa-eye"></i> Vue Joueur</a>
|
||
<a href="gm_console.php"><i class="fa-solid fa-headset"></i> Console MJ</a>
|
||
</nav>
|
||
</div>
|
||
<div>
|
||
<span style="font-weight: bold; color: #88c0d0;"><?php echo htmlspecialchars($_SESSION['username']); ?></span>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="container">
|
||
<?php if (isset($_GET['success'])): ?>
|
||
<div class="success-msg"><i class="fa-solid fa-check-circle"></i> Opération effectuée avec succès.</div>
|
||
<?php endif; ?>
|
||
|
||
<div class="tabs">
|
||
<a href="?tab=users" class="tab-link <?php echo $tab === 'users' ? 'active' : ''; ?>"><i class="fa-solid fa-users"></i> Utilisateurs</a>
|
||
<a href="?tab=objects" class="tab-link <?php echo $tab === 'objects' ? 'active' : ''; ?>"><i class="fa-solid fa-earth-europe"></i> Objets Célestes</a>
|
||
<a href="?tab=modifiers" class="tab-link <?php echo $tab === 'modifiers' ? 'active' : ''; ?>"><i class="fa-solid fa-bolt"></i> Bonus & Malus</a>
|
||
<a href="?tab=statuses" class="tab-link <?php echo $tab === 'statuses' ? 'active' : ''; ?>"><i class="fa-solid fa-signal"></i> Statuts / États</a>
|
||
<a href="?tab=settlement_types" class="tab-link <?php echo $tab === 'settlement_types' ? 'active' : ''; ?>"><i class="fa-solid fa-city"></i> Types d'Établissements</a>
|
||
<a href="?tab=factions" class="tab-link <?php echo $tab === 'factions' ? 'active' : ''; ?>"><i class="fa-solid fa-flag"></i> Factions</a>
|
||
<a href="?tab=resources" class="tab-link <?php echo $tab === 'resources' ? 'active' : ''; ?>"><i class="fa-solid fa-gem"></i> Ressources</a>
|
||
<a href="?tab=lootboxes" class="tab-link <?php echo $tab === 'lootboxes' ? 'active' : ''; ?>"><i class="fa-solid fa-box-open"></i> Lootboxes</a>
|
||
</div>
|
||
|
||
<?php if ($tab === 'users'): ?>
|
||
<h3 style="color: #88c0d0;">Gestion des Rôles</h3>
|
||
<table>
|
||
<thead>
|
||
<tr><th>Utilisateur</th><th>Email</th><th>Rôle Actuel</th><th>Nouveau Rôle</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($users_list as $u): ?>
|
||
<tr>
|
||
<td><strong><?php echo htmlspecialchars($u['username']); ?></strong></td>
|
||
<td><?php echo htmlspecialchars($u['email']); ?></td>
|
||
<td>
|
||
<span style="background: <?php echo $u['role'] === 'admin' ? '#bf616a' : ($u['role'] === 'gm' ? '#ebcb8b' : '#4c566a'); ?>; padding: 2px 8px; border-radius: 10px; font-size: 11px; color: #000; font-weight: bold;">
|
||
<?php echo strtoupper($u['role']); ?>
|
||
</span>
|
||
</td>
|
||
<td>
|
||
<form method="POST" style="display: flex; gap: 10px;">
|
||
<input type="hidden" name="action" value="update_user_role">
|
||
<input type="hidden" name="target_user_id" value="<?php echo $u['id']; ?>">
|
||
<select name="new_role">
|
||
<option value="user" <?php echo $u['role'] === 'user' ? 'selected' : ''; ?>>Utilisateur</option>
|
||
<option value="gm" <?php echo $u['role'] === 'gm' ? 'selected' : ''; ?>>Maître du Jeu (MJ)</option>
|
||
<option value="admin" <?php echo $u['role'] === 'admin' ? 'selected' : ''; ?>>Administrateur</option>
|
||
</select>
|
||
<button type="submit" class="btn btn-ok">Modifier</button>
|
||
</form>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<?php elseif ($tab === 'objects'): ?>
|
||
<h3 style="color: #88c0d0;">Objets Célestes</h3>
|
||
<div class="form-card">
|
||
<h4>Ajouter / Modifier un Objet</h4>
|
||
<form method="POST" id="objectForm" enctype="multipart/form-data">
|
||
<input type="hidden" name="action" value="upsert_object_type">
|
||
<input type="hidden" name="id" id="obj_id" value="0">
|
||
<div style="display: flex; gap: 20px;">
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Nom (Affichage)</label>
|
||
<input type="text" name="name" id="obj_name" required placeholder="Ex: Planète">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Slug (Identifiant technique)</label>
|
||
<input type="text" name="slug" id="obj_slug" required placeholder="Ex: planet">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Icône (FontAwesome)</label>
|
||
<input type="text" name="icon" id="obj_icon" required placeholder="Ex: fa-earth-europe">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Image (PNG/JPG) - Optionnel</label>
|
||
<input type="file" name="image" accept="image/*">
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 20px;">
|
||
<div style="flex: 1;">
|
||
<label style="font-size: 12px; color: #8c92a3;">Bonus / Malus attribués</label>
|
||
<div style="background: #0f172a; border: 1px solid #334155; padding: 10px; max-height: 150px; overflow-y: auto; display: flex; flex-wrap: wrap; gap: 10px; margin-top: 5px;">
|
||
<?php foreach ($modifiers_list as $m): ?>
|
||
<label style="font-size: 11px; display: flex; align-items: center; gap: 5px; cursor: pointer;">
|
||
<input type="checkbox" name="modifiers[]" value="<?php echo $m['id']; ?>" class="modifier-checkbox" data-id="<?php echo $m['id']; ?>">
|
||
<span class="modifier-tag <?php echo $m['type'] === 'bonus' ? 'tag-bonus' : 'tag-malus'; ?>">
|
||
<?php echo htmlspecialchars($m['name']); ?>
|
||
</span>
|
||
</label>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-top: 15px;">
|
||
<label>Description</label>
|
||
<textarea name="description" id="obj_desc" rows="2"></textarea>
|
||
</div>
|
||
<button type="submit" class="btn btn-add">ENREGISTRER L'OBJET</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetObjectForm()">ANNULER</button>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead><tr><th>Visuel</th><th>Nom</th><th>Bonus/Malus</th><th>Slug</th><th>Actions</th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($objects_list as $o): ?>
|
||
<tr>
|
||
<td style="text-align: center;">
|
||
<?php if (!empty($o['image_url'])): ?>
|
||
<img src="<?php echo htmlspecialchars($o['image_url']); ?>?v=<?php echo time(); ?>" style="max-width: 40px; max-height: 40px; display: block; margin: 0 auto;">
|
||
<?php else: ?>
|
||
<i class="fa-solid <?php echo htmlspecialchars($o['icon']); ?> fa-lg"></i>
|
||
<?php endif; ?>
|
||
</td>
|
||
<td><strong><?php echo htmlspecialchars($o['name']); ?></strong></td>
|
||
<td>
|
||
<?php
|
||
$stmt = $db->prepare("SELECT m.name, m.type FROM modifiers m JOIN celestial_object_type_modifiers cotm ON m.id = cotm.modifier_id WHERE cotm.celestial_object_type_id = ?");
|
||
$stmt->execute([$o['id']]);
|
||
$m_list = $stmt->fetchAll();
|
||
foreach ($m_list as $ml): ?>
|
||
<span class="modifier-tag <?php echo $ml['type'] === 'bonus' ? 'tag-bonus' : 'tag-malus'; ?>">
|
||
<?php echo htmlspecialchars($ml['name']); ?>
|
||
</span>
|
||
<?php endforeach; ?>
|
||
</td>
|
||
<td><code><?php echo htmlspecialchars($o['slug']); ?></code></td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editObject(<?php echo json_encode($o, JSON_HEX_APOS); ?>)'>Editer</button>
|
||
<a href="?tab=objects&delete_object=<?php echo $o['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cet objet ?')">Suppr</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<?php elseif ($tab === 'modifiers'): ?>
|
||
<h3 style="color: #88c0d0;">Gestion des Bonus & Malus</h3>
|
||
<div class="form-card">
|
||
<h4>Ajouter / Modifier un Modificateur</h4>
|
||
<form method="POST" id="modifierForm">
|
||
<input type="hidden" name="action" value="upsert_modifier">
|
||
<input type="hidden" name="id" id="mod_id" value="0">
|
||
<div style="display: flex; gap: 20px;">
|
||
<div class="form-group" style="flex: 2;">
|
||
<label>Nom du Bonus/Malus</label>
|
||
<input type="text" name="name" id="mod_name" required placeholder="Ex: Chaleur Extrême">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Slug</label>
|
||
<input type="text" name="slug" id="mod_slug" required placeholder="Ex: chaleur_extreme">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Type</label>
|
||
<select name="type" id="mod_type">
|
||
<option value="bonus">Bonus</option>
|
||
<option value="malus">Malus</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Description (Effet en jeu)</label>
|
||
<textarea name="description" id="mod_desc" rows="2" placeholder="Ex: Vitesse de déplacement divisée par 2"></textarea>
|
||
</div>
|
||
<button type="submit" class="btn btn-add">ENREGISTRER</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetModifierForm()">ANNULER</button>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead><tr><th>Type</th><th>Nom</th><th>Description</th><th>Slug</th><th>Actions</th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($modifiers_list as $m): ?>
|
||
<tr>
|
||
<td>
|
||
<span class="modifier-tag <?php echo $m['type'] === 'bonus' ? 'tag-bonus' : 'tag-malus'; ?>">
|
||
<?php echo strtoupper($m['type']); ?>
|
||
</span>
|
||
</td>
|
||
<td><strong><?php echo htmlspecialchars($m['name']); ?></strong></td>
|
||
<td><small><?php echo htmlspecialchars($m['description']); ?></small></td>
|
||
<td><code><?php echo htmlspecialchars($m['slug']); ?></code></td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editModifier(<?php echo json_encode($m, JSON_HEX_APOS); ?>)'>Editer</button>
|
||
<a href="?tab=modifiers&delete_modifier=<?php echo $m['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce modificateur ?')">Suppr</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<?php elseif ($tab === 'statuses'): ?>
|
||
<h3 style="color: #88c0d0;">Statuts / États</h3>
|
||
<div class="form-card">
|
||
<h4>Ajouter / Modifier un Statut</h4>
|
||
<form method="POST" id="statusForm">
|
||
<input type="hidden" name="action" value="upsert_status">
|
||
<input type="hidden" name="id" id="st_id" value="0">
|
||
<div style="display: flex; gap: 20px;">
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Nom du Statut</label>
|
||
<input type="text" name="name" id="st_name" required>
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Slug</label>
|
||
<input type="text" name="slug" id="st_slug" required>
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Couleur</label>
|
||
<div class="color-group">
|
||
<input type="color" id="st_color_picker" class="color-picker-input" oninput="document.getElementById('st_color').value = this.value">
|
||
<input type="text" name="color" id="st_color" required placeholder="#ef4444" oninput="document.getElementById('st_color_picker').value = this.value">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Description</label>
|
||
<textarea name="description" id="st_desc" rows="2"></textarea>
|
||
</div>
|
||
<button type="submit" class="btn btn-add">ENREGISTRER LE STATUT</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetStatusForm()">ANNULER</button>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead><tr><th>Couleur</th><th>Nom</th><th>Slug</th><th>Actions</th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($statuses_list as $s): ?>
|
||
<tr>
|
||
<td><div style="width: 20px; height: 20px; background: <?php echo $s['color']; ?>; border: 1px solid #fff;"></div></td>
|
||
<td><strong><?php echo htmlspecialchars($s['name']); ?></strong></td>
|
||
<td><code><?php echo htmlspecialchars($s['slug']); ?></code></td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editStatus(<?php echo json_encode($s, JSON_HEX_APOS); ?>)'>Editer</button>
|
||
<a href="?tab=statuses&delete_status=<?php echo $s['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce statut ?')">Suppr</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<?php elseif ($tab === 'settlement_types'): ?>
|
||
<h3 style="color: #88c0d0;">Types d'Établissements</h3>
|
||
<div class="form-card">
|
||
<h4>Ajouter / Modifier un Type d'Établissement</h4>
|
||
<form method="POST" id="settlementTypeForm">
|
||
<input type="hidden" name="action" value="upsert_settlement_type">
|
||
<input type="hidden" name="id" id="set_t_id" value="0">
|
||
<div style="display: flex; gap: 20px;">
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Nom</label>
|
||
<input type="text" name="name" id="set_t_name" required placeholder="Ex: Ville, Avant-poste...">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Slug</label>
|
||
<input type="text" name="slug" id="set_t_slug" required placeholder="Ex: ville, avant_poste...">
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Description</label>
|
||
<textarea name="description" id="set_t_desc" rows="2"></textarea>
|
||
</div>
|
||
<button type="submit" class="btn btn-add">ENREGISTRER</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetSettlementTypeForm()">ANNULER</button>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead><tr><th>Nom</th><th>Slug</th><th>Description</th><th>Actions</th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($settlement_types_list as $st): ?>
|
||
<tr>
|
||
<td><strong><?php echo htmlspecialchars($st['name']); ?></strong></td>
|
||
<td><code><?php echo htmlspecialchars($st['slug']); ?></code></td>
|
||
<td><small><?php echo htmlspecialchars($st['description']); ?></small></td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editSettlementType(<?php echo json_encode($st, JSON_HEX_APOS); ?>)'>Editer</button>
|
||
<a href="?tab=settlement_types&delete_settlement_type=<?php echo $st['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce type ?')">Suppr</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<?php elseif ($tab === 'factions'): ?>
|
||
<h3 style="color: #88c0d0;">Gestion des Factions</h3>
|
||
<div class="form-card">
|
||
<h4>Ajouter / Modifier une Faction</h4>
|
||
<form method="POST" id="factionForm" enctype="multipart/form-data">
|
||
<input type="hidden" name="action" value="upsert_faction">
|
||
<input type="hidden" name="id" id="fac_id" value="0">
|
||
<div style="display: flex; gap: 20px;">
|
||
<div class="form-group" style="flex: 2;">
|
||
<label>Nom de la Faction</label>
|
||
<input type="text" name="name" id="fac_name" required placeholder="Ex: Fédération, Empire...">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Slug</label>
|
||
<input type="text" name="slug" id="fac_slug" required placeholder="Ex: federation, empire...">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Couleur</label>
|
||
<div class="color-group">
|
||
<input type="color" id="fac_color_picker" class="color-picker-input" oninput="document.getElementById('fac_color').value = this.value">
|
||
<input type="text" name="color" id="fac_color" required placeholder="#808080" oninput="document.getElementById('fac_color_picker').value = this.value">
|
||
</div>
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Icône (FontAwesome)</label>
|
||
<input type="text" name="fa_icon" id="fac_fa_icon" placeholder="Ex: fa-users">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>PNG (Prioritaire)</label>
|
||
<input type="file" name="image" accept="image/png">
|
||
</div>
|
||
</div>
|
||
<button type="submit" class="btn btn-add">ENREGISTRER LA FACTION</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetFactionForm()">ANNULER</button>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead><tr><th>Couleur</th><th>Visuel</th><th>Nom</th><th>Slug</th><th>Actions</th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($factions_list as $f): ?>
|
||
<tr>
|
||
<td><div style="width: 25px; height: 25px; border-radius: 50%; background: <?php echo htmlspecialchars($f['color'] ?? '#808080'); ?>; border: 1px solid #334155;"></div></td>
|
||
<td style="text-align: center;">
|
||
<?php if (!empty($f['image_url'])): ?>
|
||
<img src="<?php echo htmlspecialchars($f['image_url']); ?>?v=<?php echo time(); ?>" style="max-width: 40px; max-height: 40px;">
|
||
<?php elseif (!empty($f['fa_icon'])): ?>
|
||
<i class="fa-solid <?php echo htmlspecialchars($f['fa_icon']); ?> fa-lg" style="color: <?php echo htmlspecialchars($f['color'] ?? '#fff'); ?>;"></i>
|
||
<?php else: ?>
|
||
<i class="fa-solid fa-flag fa-lg" style="color: <?php echo htmlspecialchars($f['color'] ?? '#4c566a'); ?>;"></i>
|
||
<?php endif; ?>
|
||
</td>
|
||
<td><strong><?php echo htmlspecialchars($f['name']); ?></strong></td>
|
||
<td><code><?php echo htmlspecialchars($f['slug']); ?></code></td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editFaction(<?php echo json_encode($f, JSON_HEX_APOS); ?>)'>Editer</button>
|
||
<?php if ($f['name'] !== 'Aucune'): ?>
|
||
<a href="?tab=factions&delete_faction=<?php echo $f['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cette faction ?')">Suppr</a>
|
||
<?php endif; ?>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<?php elseif ($tab === 'resources'): ?>
|
||
<h3 style="color: #88c0d0;">Gestion des Ressources</h3>
|
||
<div class="form-card">
|
||
<h4>Ajouter / Modifier une Ressource</h4>
|
||
<form method="POST" id="resourceForm" enctype="multipart/form-data">
|
||
<input type="hidden" name="action" value="upsert_resource">
|
||
<input type="hidden" name="id" id="res_id" value="0">
|
||
<div style="display: flex; gap: 20px;">
|
||
<div class="form-group" style="flex: 2;">
|
||
<label>Nom de la Ressource</label>
|
||
<input type="text" name="name" id="res_name" required placeholder="Ex: Métal, Carburant, Crédits...">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Slug (Identifiant technique)</label>
|
||
<input type="text" name="slug" id="res_slug" required placeholder="Ex: metal, fuel, credits...">
|
||
</div>
|
||
</div>
|
||
<div style="display: flex; gap: 20px;">
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Icône (FontAwesome)</label>
|
||
<input type="text" name="icon" id="res_icon" placeholder="Ex: fa-gem">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Image (PNG/JPG) - Optionnel</label>
|
||
<input type="file" name="image" accept="image/*">
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Description</label>
|
||
<textarea name="description" id="res_desc" rows="2"></textarea>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="switch-label" style="display: flex; align-items: center; gap: 10px; cursor: pointer;">
|
||
<input type="checkbox" name="show_in_header" id="res_show" value="1" style="width: 20px; height: 20px;">
|
||
<span>Afficher dans la barre du header des joueurs</span>
|
||
</label>
|
||
</div>
|
||
<button type="submit" class="btn btn-add">ENREGISTRER LA RESSOURCE</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetResourceForm()">ANNULER</button>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead><tr><th>Visuel</th><th>Nom</th><th>Slug</th><th>Header?</th><th>Actions</th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($resources_list as $r): ?>
|
||
<tr>
|
||
<td style="text-align: center;">
|
||
<?php if (!empty($r['image_url'])): ?>
|
||
<img src="<?php echo htmlspecialchars($r['image_url']); ?>?v=<?php echo time(); ?>" style="max-width: 40px; max-height: 40px;">
|
||
<?php elseif (!empty($r['icon'])): ?>
|
||
<i class="fa-solid <?php echo htmlspecialchars($r['icon']); ?> fa-lg"></i>
|
||
<?php else: ?>
|
||
<i class="fa-solid fa-gem fa-lg" style="color: #4c566a;"></i>
|
||
<?php endif; ?>
|
||
</td>
|
||
<td><strong><?php echo htmlspecialchars($r['name']); ?></strong></td>
|
||
<td><code><?php echo htmlspecialchars($r['slug']); ?></code></td>
|
||
<td style="text-align: center;">
|
||
<?php if ($r['show_in_header']): ?>
|
||
<i class="fa-solid fa-check-circle" style="color: #a3be8c;"></i>
|
||
<?php else: ?>
|
||
<i class="fa-solid fa-times-circle" style="color: #bf616a;"></i>
|
||
<?php endif; ?>
|
||
</td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editResource(<?php echo json_encode($r, JSON_HEX_APOS); ?>)'>Editer</button>
|
||
<a href="?tab=resources&delete_resource=<?php echo $r['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cette ressource ?')">Suppr</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<?php elseif ($tab === 'lootboxes'): ?>
|
||
<h3 style="color: #88c0d0;">Système de Lootboxes</h3>
|
||
<div class="form-card">
|
||
<h4>Créer / Modifier une Lootbox</h4>
|
||
<form method="POST" id="lootboxForm">
|
||
<input type="hidden" name="action" value="upsert_lootbox">
|
||
<input type="hidden" name="id" id="lb_id" value="0">
|
||
<div style="display: flex; gap: 20px;">
|
||
<div class="form-group" style="flex: 2;">
|
||
<label>Nom de la Lootbox</label>
|
||
<input type="text" name="name" id="lb_name" required placeholder="Ex: Coffre Mystère">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Slug</label>
|
||
<input type="text" name="slug" id="lb_slug" required placeholder="Ex: coffre_mystere">
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Description</label>
|
||
<textarea name="description" id="lb_desc" rows="2"></textarea>
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 20px; margin-top: 20px;">
|
||
<!-- ROLLS SECTION -->
|
||
<div style="flex: 0 0 350px; border: 1px solid #2d3545; padding: 15px; border-radius: 8px; background: #0f172a;">
|
||
<label style="color: #88c0d0; font-weight: bold; font-size: 14px; margin-bottom: 15px; display: block; border-bottom: 1px solid #2d3545; padding-bottom: 5px;">
|
||
Probabilité du nombre total d'objets
|
||
</label>
|
||
|
||
<div class="sub-form-header">
|
||
<div style="flex: 1;">Nb Total</div>
|
||
<div style="flex: 1;">Chance (%)</div>
|
||
<div class="btn-del-row-placeholder"></div>
|
||
</div>
|
||
|
||
<div id="rolls_container">
|
||
<!-- Dynamic rows for rolls -->
|
||
</div>
|
||
<button type="button" class="btn btn-ok" style="margin-top: 10px; width: 100%;" onclick="addRollRow()">+ Ajouter un palier</button>
|
||
</div>
|
||
|
||
<!-- ITEMS SECTION -->
|
||
<div style="flex: 1; border: 1px solid #2d3545; padding: 15px; border-radius: 8px; background: #0f172a;">
|
||
<label style="color: #88c0d0; font-weight: bold; font-size: 14px; margin-bottom: 15px; display: block; border-bottom: 1px solid #2d3545; padding-bottom: 5px;">
|
||
Objets en poule (Attribution direct ou pool aléatoire)
|
||
</label>
|
||
|
||
<div class="sub-form-header">
|
||
<div style="flex: 0 0 100px;">Type</div>
|
||
<div style="flex: 2;">Ressource / Objet</div>
|
||
<div style="flex: 1;" class="chance-header">Chance (%)</div>
|
||
<div style="flex: 0 0 70px;">Qté Min</div>
|
||
<div style="flex: 0 0 70px;">Qté Max</div>
|
||
<div class="btn-del-row-placeholder"></div>
|
||
</div>
|
||
|
||
<div id="items_container">
|
||
<!-- Dynamic rows for items -->
|
||
</div>
|
||
<button type="button" class="btn btn-ok" style="margin-top: 10px; width: 100%;" onclick="addItemRow()">+ Ajouter un objet</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="margin-top: 30px; text-align: right;">
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff; margin-right: 10px;" onclick="resetLootboxForm()">ANNULER TOUT</button>
|
||
<button type="submit" class="btn btn-add" style="padding: 12px 30px;">ENREGISTRER LA CONFIGURATION</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead><tr><th>Nom</th><th>Slug</th><th>Objets Directs (100%)</th><th>Nb Total (%)</th><th>Pool Aléatoire (%)</th><th>Actions</th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($lootboxes_list as $lb): ?>
|
||
<tr>
|
||
<td><strong><?php echo htmlspecialchars($lb['name']); ?></strong></td>
|
||
<td><code><?php echo htmlspecialchars($lb['slug']); ?></code></td>
|
||
<td>
|
||
<small>
|
||
<?php
|
||
$directs = array_filter($lb['items'], fn($i) => $i['is_guaranteed']);
|
||
foreach ($directs as $d): ?>
|
||
<div style="margin-bottom: 2px; color: #a3be8c;">
|
||
<i class="fa-solid fa-bolt"></i> <?php echo htmlspecialchars($d['resource_slug']); ?>
|
||
<span style="color: #8c92a3;">(Qté: <?php echo $d['quantity_min']; ?>-<?php echo $d['quantity_max']; ?>)</span>
|
||
</div>
|
||
<?php endforeach; if(empty($directs)) echo "<em>Aucun</em>"; ?>
|
||
</small>
|
||
</td>
|
||
<td>
|
||
<small>
|
||
<?php foreach ($lb['rolls'] as $r): ?>
|
||
<div style="margin-bottom: 2px;">
|
||
<span style="color: #88c0d0;"><?php echo $r['roll_count']; ?> objet(s)</span>:
|
||
<strong><?php echo $r['probability']; ?>%</strong>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</small>
|
||
</td>
|
||
<td>
|
||
<small>
|
||
<?php
|
||
$pool = array_filter($lb['items'], fn($i) => !$i['is_guaranteed']);
|
||
foreach ($pool as $i): ?>
|
||
<div style="margin-bottom: 2px;">
|
||
<?php echo $i['resource_slug'] ?: '<em style="color:#bf616a">(Rien)</em>'; ?>:
|
||
<strong><?php echo $i['probability']; ?>%</strong>
|
||
<span style="color: #8c92a3;">(Qté: <?php echo $i['quantity_min']; ?>-<?php echo $i['quantity_max']; ?>)</span>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</small>
|
||
</td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editLootbox(<?php echo json_encode($lb, JSON_HEX_APOS); ?>)'>Editer</button>
|
||
<a href="?tab=lootboxes&delete_lootbox=<?php echo $lb['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cette lootbox ?')">Suppr</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<script>
|
||
// --- SHARED RESOURCES ---
|
||
const resourcesList = <?php echo json_encode($resources_list); ?>;
|
||
|
||
function editObject(data) {
|
||
document.getElementById('obj_id').value = data.id;
|
||
document.getElementById('obj_name').value = data.name;
|
||
document.getElementById('obj_slug').value = data.slug;
|
||
document.getElementById('obj_icon').value = data.icon;
|
||
document.getElementById('obj_desc').value = data.description;
|
||
document.querySelectorAll('.modifier-checkbox').forEach(cb => cb.checked = false);
|
||
if (data.modifier_ids) {
|
||
data.modifier_ids.forEach(mid => {
|
||
const cb = document.querySelector(`.modifier-checkbox[value="${mid}"]`);
|
||
if (cb) cb.checked = true;
|
||
});
|
||
}
|
||
window.scrollTo(0,0);
|
||
}
|
||
function resetObjectForm() { document.getElementById('objectForm').reset(); document.getElementById('obj_id').value = 0; document.querySelectorAll('.modifier-checkbox').forEach(cb => cb.checked = false); }
|
||
|
||
function editStatus(data) {
|
||
document.getElementById('st_id').value = data.id;
|
||
document.getElementById('st_name').value = data.name;
|
||
document.getElementById('st_slug').value = data.slug;
|
||
document.getElementById('st_color').value = data.color;
|
||
if (document.getElementById('st_color_picker')) {
|
||
document.getElementById('st_color_picker').value = data.color.startsWith('#') ? data.color : '#000000';
|
||
}
|
||
document.getElementById('st_desc').value = data.description;
|
||
window.scrollTo(0,0);
|
||
}
|
||
function resetStatusForm() {
|
||
document.getElementById('statusForm').reset();
|
||
document.getElementById('st_id').value = 0;
|
||
document.getElementById('st_color_picker').value = '#000000';
|
||
}
|
||
|
||
function editSettlementType(data) {
|
||
document.getElementById('set_t_id').value = data.id;
|
||
document.getElementById('set_t_name').value = data.name;
|
||
document.getElementById('set_t_slug').value = data.slug;
|
||
document.getElementById('set_t_desc').value = data.description;
|
||
window.scrollTo(0,0);
|
||
}
|
||
function resetSettlementTypeForm() { document.getElementById('settlementTypeForm').reset(); document.getElementById('set_t_id').value = 0; }
|
||
|
||
function editModifier(data) {
|
||
document.getElementById('mod_id').value = data.id;
|
||
document.getElementById('mod_name').value = data.name;
|
||
document.getElementById('mod_slug').value = data.slug || '';
|
||
document.getElementById('mod_type').value = data.type;
|
||
document.getElementById('mod_desc').value = data.description;
|
||
window.scrollTo(0,0);
|
||
}
|
||
function resetModifierForm() { document.getElementById('modifierForm').reset(); document.getElementById('mod_id').value = 0; }
|
||
|
||
function editFaction(data) {
|
||
document.getElementById('fac_id').value = data.id;
|
||
document.getElementById('fac_name').value = data.name;
|
||
document.getElementById('fac_slug').value = data.slug || '';
|
||
const color = data.color || '#808080';
|
||
document.getElementById('fac_color').value = color;
|
||
if (document.getElementById('fac_color_picker')) {
|
||
document.getElementById('fac_color_picker').value = color.startsWith('#') ? color : '#808080';
|
||
}
|
||
document.getElementById('fac_fa_icon').value = data.fa_icon || '';
|
||
window.scrollTo(0,0);
|
||
}
|
||
function resetFactionForm() {
|
||
document.getElementById('factionForm').reset();
|
||
document.getElementById('fac_id').value = 0;
|
||
document.getElementById('fac_color').value = '#808080';
|
||
document.getElementById('fac_color_picker').value = '#808080';
|
||
}
|
||
|
||
function editResource(data) {
|
||
document.getElementById('res_id').value = data.id;
|
||
document.getElementById('res_name').value = data.name;
|
||
document.getElementById('res_slug').value = data.slug;
|
||
document.getElementById('res_icon').value = data.icon || '';
|
||
document.getElementById('res_desc').value = data.description || '';
|
||
document.getElementById('res_show').checked = (data.show_in_header == 1);
|
||
window.scrollTo(0,0);
|
||
}
|
||
function resetResourceForm() { document.getElementById('resourceForm').reset(); document.getElementById('res_id').value = 0; }
|
||
|
||
// --- LOOTBOX SYSTEM ---
|
||
function addRollRow(count = 1, prob = 100) {
|
||
const container = document.getElementById('rolls_container');
|
||
const row = document.createElement('div');
|
||
row.className = 'sub-form-row';
|
||
row.innerHTML = `
|
||
<input type="number" name="rolls_count[]" value="${count}" placeholder="Nb total" min="0">
|
||
<input type="number" name="rolls_prob[]" value="${prob}" placeholder="Chance %" step="0.01">
|
||
<div class="btn-del-row" onclick="this.parentElement.remove()">×</div>
|
||
`;
|
||
container.appendChild(row);
|
||
}
|
||
|
||
function toggleItemType(cb) {
|
||
const row = cb.closest('.sub-form-row');
|
||
const probInput = row.querySelector('.item-prob-input');
|
||
const typeLabel = row.querySelector('.type-label');
|
||
if (cb.checked) {
|
||
probInput.style.visibility = 'hidden';
|
||
probInput.value = 100;
|
||
typeLabel.textContent = 'DIRECT';
|
||
typeLabel.style.color = '#a3be8c';
|
||
} else {
|
||
probInput.style.visibility = 'visible';
|
||
typeLabel.textContent = 'POULE';
|
||
typeLabel.style.color = '#8c92a3';
|
||
}
|
||
}
|
||
|
||
function addItemRow(slug = '', prob = 0, qmin = 1, qmax = 1, isGuaranteed = 0) {
|
||
const container = document.getElementById('items_container');
|
||
const rowIdx = container.children.length;
|
||
const row = document.createElement('div');
|
||
row.className = 'sub-form-row';
|
||
let options = '<option value="">(Rien)</option>';
|
||
resourcesList.forEach(r => {
|
||
options += `<option value="${r.slug}" ${slug === r.slug ? 'selected' : ''}>${r.name}</option>`;
|
||
});
|
||
|
||
row.innerHTML = `
|
||
<div class="toggle-container">
|
||
<label class="switch">
|
||
<input type="hidden" name="item_is_guaranteed[${rowIdx}]" value="0">
|
||
<input type="checkbox" name="item_is_guaranteed[${rowIdx}]" value="1" ${isGuaranteed ? 'checked' : ''} onchange="toggleItemType(this)">
|
||
<span class="slider"></span>
|
||
</label>
|
||
<span class="type-label" style="color: ${isGuaranteed ? '#a3be8c' : '#8c92a3'}">${isGuaranteed ? 'DIRECT' : 'POULE'}</span>
|
||
</div>
|
||
<select name="item_slug[${rowIdx}]" style="flex: 2;">${options}</select>
|
||
<input type="number" name="item_prob[${rowIdx}]" value="${prob}" class="item-prob-input" style="flex: 1; ${isGuaranteed ? 'visibility:hidden' : ''}" placeholder="Prob %" step="0.01">
|
||
<input type="number" name="item_qmin[${rowIdx}]" value="${qmin}" style="flex: 0 0 70px;" placeholder="Min">
|
||
<input type="number" name="item_qmax[${rowIdx}]" value="${qmax}" style="flex: 0 0 70px;" placeholder="Max">
|
||
<div class="btn-del-row" onclick="this.parentElement.remove()">×</div>
|
||
`;
|
||
container.appendChild(row);
|
||
}
|
||
|
||
function editLootbox(data) {
|
||
document.getElementById('lb_id').value = data.id;
|
||
document.getElementById('lb_name').value = data.name;
|
||
document.getElementById('lb_slug').value = data.slug;
|
||
document.getElementById('lb_desc').value = data.description || '';
|
||
|
||
document.getElementById('rolls_container').innerHTML = '';
|
||
if (data.rolls && data.rolls.length > 0) {
|
||
data.rolls.forEach(r => addRollRow(r.roll_count, r.probability));
|
||
} else {
|
||
addRollRow();
|
||
}
|
||
|
||
document.getElementById('items_container').innerHTML = '';
|
||
if (data.items && data.items.length > 0) {
|
||
data.items.forEach((i, idx) => addItemRow(i.resource_slug, i.probability, i.quantity_min, i.quantity_max, i.is_guaranteed));
|
||
} else {
|
||
addItemRow();
|
||
}
|
||
window.scrollTo(0,0);
|
||
}
|
||
|
||
function resetLootboxForm() {
|
||
document.getElementById('lootboxForm').reset();
|
||
document.getElementById('lb_id').value = 0;
|
||
document.getElementById('rolls_container').innerHTML = '';
|
||
document.getElementById('items_container').innerHTML = '';
|
||
addRollRow();
|
||
addItemRow();
|
||
}
|
||
|
||
<?php if ($tab === 'lootboxes'): ?>
|
||
window.onload = function() {
|
||
if (document.getElementById('rolls_container').children.length === 0) addRollRow();
|
||
if (document.getElementById('items_container').children.length === 0) addItemRow();
|
||
};
|
||
<?php endif; ?>
|
||
</script>
|
||
</body>
|
||
</html>
|