2687 lines
153 KiB
PHP
2687 lines
153 KiB
PHP
<?php
|
||
|
||
function get_user_grade($pdo, $user_id) {
|
||
$stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?");
|
||
$stmt->execute([$user_id]);
|
||
$user = $stmt->fetch();
|
||
if (!$user) return null;
|
||
|
||
$role = $user['role'];
|
||
$level = 0;
|
||
try {
|
||
$stmt_lvl = $pdo->prepare("SELECT level FROM users WHERE id = ?");
|
||
$stmt_lvl->execute([$user_id]);
|
||
$level = (int)$stmt_lvl->fetchColumn();
|
||
} catch (Exception $e) {
|
||
// level column might not exist
|
||
}
|
||
|
||
if ($role === 'admin') {
|
||
$stmt = $pdo->prepare("SELECT * FROM grades WHERE user_type = 'admin' LIMIT 1");
|
||
$stmt->execute();
|
||
return $stmt->fetch();
|
||
} elseif ($role === 'gm') {
|
||
$stmt = $pdo->prepare("SELECT * FROM grades WHERE user_type = 'GM' LIMIT 1");
|
||
$stmt->execute();
|
||
return $stmt->fetch();
|
||
} else {
|
||
$stmt = $pdo->prepare("SELECT * FROM grades WHERE user_type = 'utilisateur' AND ? BETWEEN min_level AND max_level LIMIT 1");
|
||
$stmt->execute([$level]);
|
||
return $stmt->fetch();
|
||
}
|
||
}
|
||
|
||
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.");
|
||
}
|
||
|
||
// Default tab is now users as before, but let's see if we should change it to project_logs
|
||
$tab = isset($_GET['tab']) ? $_GET['tab'] : 'project_logs';
|
||
|
||
// --- 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'];
|
||
$status_profile_id = !empty($_POST['status_profile_id']) ? (int)$_POST['status_profile_id'] : null;
|
||
$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;
|
||
}
|
||
}
|
||
|
||
$orbital_enabled = isset($_POST["orbital_control_enabled"]) ? 1 : 0;
|
||
$terrestrial_enabled = isset($_POST["terrestrial_control_enabled"]) ? 1 : 0;
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE celestial_object_types SET name = ?, slug = ?, icon = ?, description = ?, image_url = ?, orbital_control_enabled = ?, terrestrial_control_enabled = ?, status_profile_id = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $icon, $description, $image_url, $orbital_enabled, $terrestrial_enabled, $status_profile_id, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO celestial_object_types (name, slug, icon, description, image_url, orbital_control_enabled, terrestrial_control_enabled, status_profile_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $icon, $description, $image_url, $orbital_enabled, $terrestrial_enabled, $status_profile_id]);
|
||
$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 Title CRUD
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_title') {
|
||
$id = (int)$_POST['id'];
|
||
$name = $_POST["name"];
|
||
$slug = $_POST['slug'];
|
||
$color = $_POST["color"] ?? "#ffffff";
|
||
$allowed_user_type = $_POST['allowed_user_type'];
|
||
$required_level = (int)$_POST['required_level'];
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE titles SET name = ?, slug = ?, allowed_user_type = ?, required_level = ?, color = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $allowed_user_type, $required_level, $color, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO titles (name, slug, allowed_user_type, required_level, color) VALUES (?, ?, ?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $allowed_user_type, $required_level, $color]);
|
||
}
|
||
header("Location: admin.php?tab=badges&success=1");
|
||
exit;
|
||
}
|
||
|
||
// Handle Badge CRUD
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_badge') {
|
||
$id = (int)$_POST['id'];
|
||
$name = $_POST["name"];
|
||
$slug = $_POST['slug'];
|
||
$allowed_user_type = $_POST['allowed_user_type'];
|
||
$required_level = (int)$_POST['required_level'];
|
||
|
||
$image_url = null;
|
||
if ($id > 0) {
|
||
$stmt_img = $db->prepare("SELECT image_url FROM badges 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 = "badge_" . $slug . "_" . time() . "." . $ext;
|
||
$target = "assets/images/badges/" . $filename;
|
||
if (!is_dir("assets/images/badges/")) mkdir("assets/images/badges/", 0775, true);
|
||
if (move_uploaded_file($_FILES['image']['tmp_name'], $target)) {
|
||
$image_url = $target;
|
||
}
|
||
}
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE badges SET name = ?, slug = ?, allowed_user_type = ?, required_level = ?, image_url = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $allowed_user_type, $required_level, $image_url, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO badges (name, slug, allowed_user_type, required_level, image_url) VALUES (?, ?, ?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $allowed_user_type, $required_level, $image_url]);
|
||
}
|
||
header("Location: admin.php?tab=badges&success=1");
|
||
exit;
|
||
}
|
||
|
||
// Handle Title/Badge Deletion
|
||
if (isset($_GET['delete_title'])) {
|
||
$id = (int)$_GET['delete_title'];
|
||
$db->prepare("DELETE FROM titles WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=badges&success=deleted");
|
||
exit;
|
||
}
|
||
if (isset($_GET['delete_badge'])) {
|
||
$id = (int)$_GET['delete_badge'];
|
||
$db->prepare("DELETE FROM badges WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=badges&success=deleted");
|
||
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"];
|
||
|
||
// Gérer le clignotement
|
||
if (isset($_POST["is_blinking"]) && $_POST["is_blinking"] === "on") {
|
||
if (strpos($color, ";blink") === false) {
|
||
$color .= ";blink";
|
||
}
|
||
} else {
|
||
$color = str_replace(";blink", "", $color);
|
||
}
|
||
|
||
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 Status Profile CRUD
|
||
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "upsert_status_profile") {
|
||
$id = (int)$_POST["id"];
|
||
$name = $_POST["name"];
|
||
$slug = $_POST["slug"];
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE celestial_object_status_profiles SET name = ?, slug = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO celestial_object_status_profiles (name, slug) VALUES (?, ?)");
|
||
$stmt->execute([$name, $slug]);
|
||
}
|
||
header("Location: admin.php?tab=statuses&success=1");
|
||
exit;
|
||
}
|
||
|
||
if (isset($_GET["delete_status_profile"])) {
|
||
$id = (int)$_GET["delete_status_profile"];
|
||
// Check if it is used
|
||
$count = $db->query("SELECT COUNT(*) FROM celestial_object_status_rules WHERE profile_id = $id")->fetchColumn();
|
||
$count2 = $db->query("SELECT COUNT(*) FROM celestial_object_types WHERE status_profile_id = $id")->fetchColumn();
|
||
if ($count == 0 && $count2 == 0) {
|
||
$db->prepare("DELETE FROM celestial_object_status_profiles WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=statuses&success=1");
|
||
} else {
|
||
header("Location: admin.php?tab=statuses&error=profile_in_use");
|
||
}
|
||
exit;
|
||
}
|
||
|
||
// Handle Status Rule CRUD
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_status_rule') {
|
||
$id = (int)$_POST['id'];
|
||
$name = $_POST["name"];
|
||
$status_id = (int)$_POST['status_id'];
|
||
$profile_id = (int)$_POST['profile_id'];
|
||
$priority = (int)$_POST['priority'];
|
||
|
||
$orbital_count_op = $_POST['orbital_count_op'] ?: null;
|
||
$orbital_count_val = $_POST['orbital_count_val'] !== '' ? (int)$_POST['orbital_count_val'] : null;
|
||
$terrestrial_count_op = $_POST['terrestrial_count_op'] ?: null;
|
||
$terrestrial_count_val = $_POST['terrestrial_count_val'] !== '' ? (int)$_POST['terrestrial_count_val'] : null;
|
||
$orbital_dominance = isset($_POST['orbital_dominance']) ? implode(',', (array)$_POST['orbital_dominance']) : null;
|
||
$terrestrial_dominance = isset($_POST['terrestrial_dominance']) ? implode(',', (array)$_POST['terrestrial_dominance']) : null;
|
||
$is_empty_case = isset($_POST['is_empty_case']) ? 1 : 0;
|
||
$combine_mode = $_POST['combine_mode'] ?? 'OR';
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE celestial_object_status_rules SET name = ?, status_id = ?, profile_id = ?, priority = ?, orbital_count_op = ?, orbital_count_val = ?, terrestrial_count_op = ?, terrestrial_count_val = ?, orbital_dominance = ?, terrestrial_dominance = ?, is_empty_case = ?, combine_mode = ? WHERE id = ?");
|
||
$stmt->execute([$name, $status_id, $profile_id, $priority, $orbital_count_op, $orbital_count_val, $terrestrial_count_op, $terrestrial_count_val, $orbital_dominance, $terrestrial_dominance, $is_empty_case, $combine_mode, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO celestial_object_status_rules (name, status_id, profile_id, priority, orbital_count_op, orbital_count_val, terrestrial_count_op, terrestrial_count_val, orbital_dominance, terrestrial_dominance, is_empty_case, combine_mode) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||
$stmt->execute([$name, $status_id, $profile_id, $priority, $orbital_count_op, $orbital_count_val, $terrestrial_count_op, $terrestrial_count_val, $orbital_dominance, $terrestrial_dominance, $is_empty_case, $combine_mode]);
|
||
}
|
||
header("Location: admin.php?tab=statuses&success=1");
|
||
exit;
|
||
}
|
||
|
||
if (isset($_GET['delete_status_rule'])) {
|
||
$id = (int)$_GET['delete_status_rule'];
|
||
$db->prepare("DELETE FROM celestial_object_status_rules 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;
|
||
$alliance_ids = isset($_POST['alliances']) ? $_POST['alliances'] : [];
|
||
|
||
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]);
|
||
$id = $db->lastInsertId();
|
||
}
|
||
|
||
// Handle Alliances (Reciprocal)
|
||
$db->prepare("DELETE FROM faction_alliances WHERE faction_id_1 = ? OR faction_id_2 = ?")->execute([$id, $id]);
|
||
foreach ($alliance_ids as $ally_id) {
|
||
$f1 = min((int)$id, (int)$ally_id);
|
||
$f2 = max((int)$id, (int)$ally_id);
|
||
if ($f1 === $f2) continue;
|
||
$db->prepare("INSERT IGNORE INTO faction_alliances (faction_id_1, faction_id_2) VALUES (?, ?)")->execute([$f1, $f2]);
|
||
}
|
||
|
||
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 Levels CRUD
|
||
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "upsert_level") {
|
||
$id = (int)$_POST["id"];
|
||
$name = $_POST["name"];
|
||
$slug = $_POST["slug"];
|
||
$resource_id = (int)$_POST["resource_id"];
|
||
$required_quantity = (int)$_POST["required_quantity"];
|
||
|
||
if ($required_quantity <= 0) {
|
||
header("Location: admin.php?tab=levels&error=invalid_amount");
|
||
exit;
|
||
}
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE levels SET name = ?, slug = ?, resource_id = ?, required_quantity = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $resource_id, $required_quantity, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO levels (name, slug, resource_id, required_quantity) VALUES (?, ?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $resource_id, $required_quantity]);
|
||
}
|
||
|
||
header("Location: admin.php?tab=levels&success=1");
|
||
exit;
|
||
}
|
||
|
||
if (isset($_GET["delete_level"])) {
|
||
$id = (int)$_GET["delete_level"];
|
||
$db->prepare("DELETE FROM levels WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=levels&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 Guild System Config
|
||
error_log(print_r($_POST, true));
|
||
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "update_guild_requirements") {
|
||
$db->exec("DELETE FROM guild_creation_requirements");
|
||
$stmt = $db->prepare("INSERT INTO guild_creation_requirements (resource_id, amount) VALUES (?, ?)");
|
||
foreach ($_POST as $key => $value) {
|
||
if (strpos($key, "res_") === 0 && (int)$value >= 0) {
|
||
$res_id = (int)str_replace("res_", "", $key);
|
||
$stmt->execute([$res_id, (int)$value]);
|
||
}
|
||
}
|
||
|
||
if (isset($_POST['guild_member_limit'])) {
|
||
$stmt = $db->prepare("UPDATE guild_restrictions SET value = ? WHERE restriction_key = 'member_limit'");
|
||
$stmt->execute([(int)$_POST['guild_member_limit']]);
|
||
}
|
||
header("Location: admin.php?tab=guilds&success=1");
|
||
exit;
|
||
}
|
||
|
||
// Handle Lootbox CRUD
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_grade') {
|
||
$id = (int)$_POST['id'];
|
||
$name = trim($_POST["name"]);
|
||
$slug = trim($_POST['slug']);
|
||
$user_type = $_POST['user_type'];
|
||
$min_level = ($user_type === 'utilisateur') ? (int)$_POST['min_level'] : null;
|
||
$max_level = ($user_type === 'utilisateur') ? (int)$_POST['max_level'] : null;
|
||
|
||
if ($user_type === 'utilisateur' && $min_level > $max_level) {
|
||
header('Location: ?tab=ranks&error=invalid_range');
|
||
exit;
|
||
}
|
||
|
||
// Check for overlap if user_type is 'utilisateur'
|
||
if ($user_type === 'utilisateur') {
|
||
$check = db()->prepare("SELECT id FROM grades WHERE user_type = 'utilisateur' AND id != ? AND NOT (max_level < ? OR min_level > ?)");
|
||
$check->execute([$id, $min_level, $max_level]);
|
||
if ($check->fetch()) {
|
||
header('Location: ?tab=ranks&error=overlap_levels');
|
||
exit;
|
||
}
|
||
}
|
||
|
||
try {
|
||
$image_url = null;
|
||
if (!empty($_FILES["image"]["name"])) {
|
||
$ext = pathinfo($_FILES["image"]["name"], PATHINFO_EXTENSION);
|
||
$filename = "grade_" . time() . "_" . uniqid() . "." . $ext;
|
||
if (!is_dir("assets/images/grades/")) mkdir("assets/images/grades/", 0775, true);
|
||
move_uploaded_file($_FILES["image"]["tmp_name"], "assets/images/grades/" . $filename);
|
||
$image_url = "assets/images/grades/" . $filename;
|
||
}
|
||
|
||
if ($id > 0) {
|
||
$stmt = db()->prepare("UPDATE grades SET name = ?, slug = ?, user_type = ?, min_level = ?, max_level = ?, image_url = COALESCE(?, image_url) WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $user_type, $min_level, $max_level, $image_url, $id]);
|
||
} else {
|
||
$stmt = db()->prepare("INSERT INTO grades (name, slug, user_type, min_level, max_level, image_url) VALUES (?, ?, ?, ?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $user_type, $min_level, $max_level, $image_url]);
|
||
}
|
||
header('Location: ?tab=ranks&success=1');
|
||
exit;
|
||
} catch (PDOException $e) {
|
||
header('Location: ?tab=ranks&error=db');
|
||
exit;
|
||
}
|
||
}
|
||
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;
|
||
}
|
||
|
||
|
||
// Handle Project Log CRUD
|
||
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "upsert_project_log") {
|
||
$id = (int)$_POST["id"];
|
||
$version = $_POST["version"];
|
||
$title = $_POST["title"];
|
||
$content_log = $_POST["content"];
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE project_logs SET version = ?, title = ?, content = ? WHERE id = ?");
|
||
$stmt->execute([$version, $title, $content_log, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO project_logs (version, title, content) VALUES (?, ?, ?)");
|
||
$stmt->execute([$version, $title, $content_log]);
|
||
}
|
||
header("Location: admin.php?tab=project_logs&success=1");
|
||
exit;
|
||
}
|
||
|
||
if (isset($_GET['delete_grade'])) {
|
||
$id = (int)$_GET['delete_grade'];
|
||
$stmt = db()->prepare("DELETE FROM grades WHERE id = ?");
|
||
$stmt->execute([$id]);
|
||
header('Location: ?tab=ranks&success=deleted');
|
||
exit;
|
||
}
|
||
if (isset($_GET["delete_project_log"])) {
|
||
$id = (int)$_GET["delete_project_log"];
|
||
$db->prepare("DELETE FROM project_logs WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=project_logs&success=1");
|
||
exit;
|
||
}
|
||
|
||
// Handle Unit CRUD
|
||
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "upsert_unit") {
|
||
$id = (int)$_POST["id"];
|
||
$name = $_POST["name"];
|
||
$slug = $_POST["slug"];
|
||
$faction_id = !empty($_POST["faction_id"]) ? (int)$_POST["faction_id"] : null;
|
||
$can_be_destroyed = isset($_POST["can_be_destroyed"]) ? 1 : 0;
|
||
$can_be_captured = isset($_POST["can_be_captured"]) ? 1 : 0;
|
||
$points_per_hit = (int)$_POST["points_per_hit"];
|
||
$bonus_destruction = (int)$_POST["bonus_destruction"];
|
||
$bonus_capture = (int)$_POST["bonus_capture"];
|
||
$grid_data = $_POST["grid_data"];
|
||
|
||
$image_url = null;
|
||
if ($id > 0) {
|
||
$stmt_img = $db->prepare("SELECT image_url FROM units 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 = "unit_" . $slug . "_" . time() . "." . $ext;
|
||
$target = "assets/images/units/" . $filename;
|
||
if (!is_dir("assets/images/units/")) mkdir("assets/images/units/", 0775, true);
|
||
if (move_uploaded_file($_FILES["image"]["tmp_name"], $target)) {
|
||
$image_url = $target;
|
||
}
|
||
}
|
||
|
||
if ($id > 0) {
|
||
$stmt = $db->prepare("UPDATE units SET name = ?, slug = ?, faction_id = ?, can_be_destroyed = ?, can_be_captured = ?, points_per_hit = ?, bonus_destruction = ?, bonus_capture = ?, grid_data = ?, image_url = ? WHERE id = ?");
|
||
$stmt->execute([$name, $slug, $faction_id, $can_be_destroyed, $can_be_captured, $points_per_hit, $bonus_destruction, $bonus_capture, $grid_data, $image_url, $id]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO units (name, slug, faction_id, can_be_destroyed, can_be_captured, points_per_hit, bonus_destruction, bonus_capture, grid_data, image_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||
$stmt->execute([$name, $slug, $faction_id, $can_be_destroyed, $can_be_captured, $points_per_hit, $bonus_destruction, $bonus_capture, $grid_data, $image_url]);
|
||
$id = $db->lastInsertId();
|
||
}
|
||
|
||
// Handle Rewards
|
||
$db->prepare("DELETE FROM unit_rewards WHERE unit_id = ?")->execute([$id]);
|
||
if (isset($_POST["reward_action"]) && is_array($_POST["reward_action"])) {
|
||
$ins_rw = $db->prepare("INSERT INTO unit_rewards (unit_id, action_type, resource_id, amount) VALUES (?, ?, ?, ?)");
|
||
foreach ($_POST["reward_action"] as $idx => $action) {
|
||
$res_id = (int)$_POST["reward_resource_id"][$idx];
|
||
$amount = (int)$_POST["reward_amount"][$idx];
|
||
if ($amount > 0) {
|
||
$ins_rw->execute([$id, $action, $res_id, $amount]);
|
||
}
|
||
}
|
||
}
|
||
|
||
header("Location: admin.php?tab=units&success=1");
|
||
exit;
|
||
}
|
||
|
||
if (isset($_GET["delete_unit"])) {
|
||
$id = (int)$_GET["delete_unit"];
|
||
$db->prepare("DELETE FROM units WHERE id = ?")->execute([$id]);
|
||
header("Location: admin.php?tab=units&success=1");
|
||
exit;
|
||
}
|
||
|
||
// --- DATA FETCHING ---
|
||
|
||
$users_list = [];
|
||
$objects_list = [];
|
||
$statuses_list = [];
|
||
$status_rules_list = [];
|
||
$status_profiles_list = [];
|
||
$settlement_types_list = [];
|
||
$modifiers_list = [];
|
||
$factions_list = [];
|
||
$resources_list = [];
|
||
$lootboxes_list = [];
|
||
$project_logs_list = [];
|
||
$units_list = [];
|
||
$titles_list = [];
|
||
$badges_list = [];
|
||
$levels_list = [];
|
||
$ranks_list = [];
|
||
$guild_requirements = [];
|
||
$guild_member_limit = 50;
|
||
|
||
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);
|
||
}
|
||
unset($obj);
|
||
$modifiers_list = $db->query("SELECT * FROM modifiers ORDER BY type, name ASC")->fetchAll();
|
||
$status_profiles_list = $db->query("SELECT * FROM celestial_object_status_profiles ORDER BY name ASC")->fetchAll();
|
||
} elseif ($tab === 'statuses') {
|
||
$statuses_list = $db->query("SELECT * FROM celestial_object_statuses ORDER BY name ASC")->fetchAll();
|
||
$status_rules_list = $db->query("SELECT r.*, s.name as status_name, p.name as profile_name FROM celestial_object_status_rules r JOIN celestial_object_statuses s ON r.status_id = s.id LEFT JOIN celestial_object_status_profiles p ON r.profile_id = p.id ORDER BY r.profile_id, r.priority DESC, r.name ASC")->fetchAll();
|
||
$status_profiles_list = $db->query("SELECT * FROM celestial_object_status_profiles ORDER BY name ASC")->fetchAll();
|
||
$factions_list = $db->query("SELECT * FROM factions 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();
|
||
foreach ($factions_list as &$f) {
|
||
$stmt = $db->prepare("SELECT faction_id_1 as ally_id FROM faction_alliances WHERE faction_id_2 = ? UNION SELECT faction_id_2 as ally_id FROM faction_alliances WHERE faction_id_1 = ?");
|
||
$stmt->execute([$f['id'], $f['id']]);
|
||
$f['alliance_ids'] = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||
}
|
||
unset($f);
|
||
} elseif ($tab === 'levels') {
|
||
$levels_list = $db->query("SELECT l.*, r.name as resource_name FROM levels l JOIN game_resources r ON l.resource_id = r.id ORDER BY l.required_quantity ASC")->fetchAll();
|
||
$resources_list = $db->query("SELECT id, name FROM game_resources ORDER BY name ASC")->fetchAll();
|
||
} elseif ($tab === 'resources') {
|
||
$resources_list = $db->query("SELECT * FROM game_resources ORDER BY name ASC")->fetchAll();
|
||
} elseif ($tab === 'project_logs') {
|
||
$project_logs_list = $db->query("SELECT * FROM project_logs ORDER BY created_at DESC")->fetchAll();
|
||
} elseif ($tab === 'badges') {
|
||
$titles_list = $db->query("SELECT * FROM titles ORDER BY name ASC")->fetchAll();
|
||
$badges_list = $db->query("SELECT * FROM badges ORDER BY name ASC")->fetchAll();
|
||
} elseif ($tab === 'ranks') {
|
||
$ranks_list = $db->query("SELECT * FROM grades ORDER BY user_type DESC, min_level 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();
|
||
}
|
||
unset($lb);
|
||
} elseif ($tab === 'guilds') {
|
||
$guild_requirements = $db->query("SELECT r.id, r.name, r.icon, gr.amount FROM game_resources r LEFT JOIN guild_creation_requirements gr ON r.id = gr.resource_id")->fetchAll();
|
||
$stmt = $db->query("SELECT value FROM guild_restrictions WHERE restriction_key = 'member_limit'");
|
||
$guild_member_limit = $stmt->fetchColumn() ?: 50;
|
||
}
|
||
elseif ($tab === "units") {
|
||
$units_list = $db->query("SELECT u.*, f.name as faction_name FROM units u LEFT JOIN factions f ON u.faction_id = f.id ORDER BY u.name ASC")->fetchAll();
|
||
foreach ($units_list as &$unit) {
|
||
$stmt_rw = $db->prepare("SELECT action_type, resource_id, amount FROM unit_rewards WHERE unit_id = ?");
|
||
$stmt_rw->execute([$unit["id"]]);
|
||
$unit["rewards"] = $stmt_rw->fetchAll();
|
||
}
|
||
unset($unit);
|
||
$factions_list = $db->query("SELECT id, name FROM factions ORDER BY name ASC")->fetchAll();
|
||
$resources_list = $db->query("SELECT id, name FROM game_resources ORDER BY name ASC")->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: 10px; 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; }
|
||
|
||
@keyframes blink {
|
||
0% { opacity: 1; }
|
||
50% { opacity: 0.3; }
|
||
100% { opacity: 1; }
|
||
}
|
||
.blink-effect {
|
||
animation: blink 1s infinite;
|
||
}
|
||
|
||
/* 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; }
|
||
|
||
/* Multi-select dropdown */
|
||
.ms-container { position: relative; width: 100%; }
|
||
.ms-display {
|
||
background: #0f172a; border: 1px solid #334155; color: #fff; padding: 8px; cursor: pointer; min-height: 34px; box-sizing: border-box; font-size: 12px; display: flex; align-items: center; justify-content: space-between;
|
||
}
|
||
.ms-display:after { content: '▼'; font-size: 8px; color: #8c92a3; }
|
||
.ms-dropdown {
|
||
position: absolute; top: 100%; left: 0; right: 0; background: #1a202c; border: 1px solid #334155; z-index: 1000; display: none; max-height: 200px; overflow-y: auto; padding: 5px;
|
||
}
|
||
.ms-item { padding: 5px 8px; cursor: pointer; display: flex; align-items: center; gap: 8px; font-size: 11px; }
|
||
.ms-item:hover { background: #2d3545; }
|
||
.ms-item input { width: auto !important; }
|
||
.unit-grid-container { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
|
||
.unit-grid { display: grid; grid-template-columns: repeat(6, 64px); grid-template-rows: repeat(6, 64px); gap: 2px; background: #2d3545; padding: 2px; width: fit-content; }
|
||
.unit-cell { width: 64px; height: 64px; background: #0f172a; cursor: pointer; border: 1px solid #334155; }
|
||
.unit-cell.active { background: #88c0d0; }
|
||
.unit-cell:hover { border-color: #88c0d0; }
|
||
</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="project_log.php"><i class="fa-solid fa-clipboard-list"></i> Journal</a> <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['error']) && $_GET['error'] === 'invalid_amount'): ?>
|
||
<div class="success-msg" style="background: #bf616a; color: #fff;"><i class="fa-solid fa-triangle-exclamation"></i> Erreur : La quantité doit être un nombre strictement positif.</div>
|
||
<?php endif; ?>
|
||
<?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; ?>
|
||
|
||
<!-- LIGNE 1 (UTILISATEUR) -->
|
||
<div class="tabs">
|
||
<a href="?tab=project_logs" class="tab-link <?php echo $tab === "project_logs" ? "active" : ""; ?>"><i class="fa-solid fa-clipboard-list"></i> Journal de Bord</a>
|
||
<a href="?tab=users" class="tab-link <?php echo $tab === 'users' ? 'active' : ''; ?>"><i class="fa-solid fa-users"></i> Utilisateurs</a>
|
||
<a href="?tab=levels" class="tab-link <?php echo $tab === 'levels' ? 'active' : ''; ?>"><i class="fa-solid fa-layer-group"></i> Niveaux</a>
|
||
<a href="?tab=ranks" class="tab-link <?php echo $tab === 'ranks' ? 'active' : ''; ?>"><i class="fa-solid fa-medal"></i> Grades</a>
|
||
<a href="?tab=badges" class="tab-link <?php echo $tab === 'badges' ? 'active' : ''; ?>"><i class="fa-solid fa-id-badge"></i> Titres & Badges</a>
|
||
<a href="?tab=guilds" class="tab-link <?php echo $tab === "guilds" ? "active" : ""; ?>"><i class="fa-solid fa-building-shield"></i> Gestion de guilde</a>
|
||
</div>
|
||
|
||
<!-- LIGNE 2 (JEU) -->
|
||
<div class="tabs" style="margin-bottom: 20px;">
|
||
<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> Lieux et points d’intérêt</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>
|
||
<a href="?tab=units" class="tab-link <?php echo $tab === 'units' ? 'active' : ''; ?>"><i class="fa-solid fa-rocket"></i> Unité</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 === 'units'): ?>
|
||
<h3 style="color: #88c0d0;">Gestion des Unités</h3>
|
||
<div class="form-card">
|
||
<h4>Ajouter / Modifier une Unité</h4>
|
||
<form method="POST" enctype="multipart/form-data" id="unitForm">
|
||
<input type="hidden" name="action" value="upsert_unit">
|
||
<input type="hidden" name="id" id="unit_id" value="0">
|
||
<div style="display: flex; gap: 20px; flex-wrap: wrap;">
|
||
<div class="form-group" style="flex: 1; min-width: 250px;">
|
||
<label>Nom de l'unité</label>
|
||
<input type="text" name="name" id="unit_name" required placeholder="Chasseur Stellaire" onkeyup="syncSlug(this.value, 'unit_slug')">
|
||
</div>
|
||
<div class="form-group" style="flex: 1; min-width: 200px;">
|
||
<label>Slug (unique)</label>
|
||
<input type="text" name="slug" id="unit_slug" required placeholder="chasseur_stellaire">
|
||
</div>
|
||
<div class="form-group" style="flex: 1; min-width: 200px;">
|
||
<label>Faction</label>
|
||
<select name="faction_id" id="unit_faction_id">
|
||
<option value="">Aucune (Neutre)</option>
|
||
<?php foreach ($factions_list as $f): ?>
|
||
<option value="<?php echo $f['id']; ?>"><?php echo htmlspecialchars($f['name']); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 20px; flex-wrap: wrap; align-items: flex-end;">
|
||
<div class="form-group" style="flex: 1; min-width: 250px;">
|
||
<label>Image de l'unité</label>
|
||
<input type="file" name="image" accept="image/*">
|
||
</div>
|
||
<div class="form-group" style="flex: 1; min-width: 200px;">
|
||
<label>Points par coup (dégâts)</label>
|
||
<input type="number" name="points_per_hit" id="unit_points_per_hit" value="1" min="0">
|
||
</div>
|
||
<div class="form-group" style="display: flex; gap: 20px; flex: 1; min-width: 200px; padding-bottom: 10px;">
|
||
<label style="display: flex; align-items: center; gap: 5px; cursor: pointer;">
|
||
<input type="checkbox" name="can_be_destroyed" id="unit_can_be_destroyed" value="1"> Destructible
|
||
</label>
|
||
<label style="display: flex; align-items: center; gap: 5px; cursor: pointer;">
|
||
<input type="checkbox" name="can_be_captured" id="unit_can_be_captured" value="1"> Capturable
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 20px; flex-wrap: wrap;">
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Bonus Destruction (Points)</label>
|
||
<input type="number" name="bonus_destruction" id="unit_bonus_destruction" value="0" min="0">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Bonus Capture (Points)</label>
|
||
<input type="number" name="bonus_capture" id="unit_bonus_capture" value="0" min="0">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Données de Grille (Format JSON)</label>
|
||
<div class="unit-grid-container">
|
||
<div class="unit-grid" id="unitGrid"></div>
|
||
<div style="font-size: 10px; color: #8c92a3;">Cliquez sur les cases pour définir la forme de l'unité (6x6).</div>
|
||
<textarea name="grid_data" id="unit_grid_data" style="height: 40px; font-size: 10px;" readonly></textarea>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Récompenses additionnelles (Action / Ressource / Quantité)</label>
|
||
<div id="unitRewardsContainer">
|
||
<div class="sub-form-header">
|
||
<div style="flex: 1;">Action</div>
|
||
<div style="flex: 1;">Ressource</div>
|
||
<div style="flex: 1;">Quantité</div>
|
||
<div class="btn-del-row-placeholder"></div>
|
||
</div>
|
||
</div>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff; margin-top: 5px;" onclick="addUnitRewardRow()">+ AJOUTER UNE RÉCOMPENSE</button>
|
||
</div>
|
||
|
||
<div style="margin-top: 20px;">
|
||
<button type="submit" class="btn btn-add" id="unit_submit_btn">ENREGISTRER L'UNITÉ</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetUnitForm()">ANNULER</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Image</th>
|
||
<th>Nom / Slug</th>
|
||
<th>Faction</th>
|
||
<th>Propriétés</th>
|
||
<th>Récompenses</th>
|
||
<th>Actions</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php if (empty($units_list)): ?>
|
||
<tr><td colspan="6" style="text-align: center; color: #8c92a3;">Aucune unité configurée.</td></tr>
|
||
<?php else: ?>
|
||
<?php foreach ($units_list as $unit): ?>
|
||
<tr>
|
||
<td>
|
||
<?php if ($unit['image_url']): ?>
|
||
<img src="<?php echo $unit['image_url']; ?>" style="width: 40px; height: 40px; object-fit: contain; background: #1a202c; border-radius: 4px;">
|
||
<?php else: ?>
|
||
<div style="width: 40px; height: 40px; background: #1a202c; border-radius: 4px; display: flex; align-items: center; justify-content: center;">
|
||
<i class="fa-solid fa-rocket" style="color: #2d3545;"></i>
|
||
</div>
|
||
<?php endif; ?>
|
||
</td>
|
||
<td>
|
||
<strong><?php echo htmlspecialchars($unit['name']); ?></strong><br>
|
||
<code style="font-size: 10px;"><?php echo htmlspecialchars($unit['slug']); ?></code>
|
||
</td>
|
||
<td>
|
||
<span style="color: #88c0d0; font-weight: bold; font-size: 12px;">
|
||
<?php echo $unit['faction_name'] ? htmlspecialchars($unit['faction_name']) : 'Neutre'; ?>
|
||
</span>
|
||
</td>
|
||
<td style="font-size: 11px;">
|
||
Pts/Coup: <?php echo $unit['points_per_hit']; ?><br>
|
||
<?php if ($unit['can_be_destroyed']): ?><span style="color: #bf616a;">● Destructible</span><br><?php endif; ?>
|
||
<?php if ($unit['can_be_captured']): ?><span style="color: #a3be8c;">● Capturable</span><?php endif; ?>
|
||
</td>
|
||
<td style="font-size: 10px;">
|
||
<?php if ($unit['bonus_destruction'] > 0): ?>Destr: +<?php echo $unit['bonus_destruction']; ?> pts<br><?php endif; ?>
|
||
<?php if ($unit['bonus_capture'] > 0): ?>Capt: +<?php echo $unit['bonus_capture']; ?> pts<br><?php endif; ?>
|
||
<?php foreach ($unit['rewards'] as $rw): ?>
|
||
<?php
|
||
$rName = '?';
|
||
foreach($resources_list as $res) { if($res['id'] == $rw['resource_id']) { $rName = $res['name']; break; } }
|
||
?>
|
||
<span style="color: #8c92a3;"><?php echo $rw['action_type'] === 'destroy' ? 'Destr' : 'Capt'; ?>:</span>
|
||
+<?php echo $rw['amount']; ?> <?php echo htmlspecialchars($rName); ?><br>
|
||
<?php endforeach; ?>
|
||
</td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editUnit(<?php echo json_encode($unit, JSON_HEX_APOS); ?>)'>Modifier</button>
|
||
<a href="?tab=units&delete_unit=<?php echo $unit['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cette unité ?')">Supprimer</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
<?php elseif ($tab === 'levels'): ?>
|
||
<h3 style="color: #88c0d0;">Gestion des Niveaux</h3>
|
||
<div class="form-card">
|
||
<h4>Ajouter / Modifier un Niveau</h4>
|
||
<form method="POST" id="levelForm">
|
||
<input type="hidden" name="action" value="upsert_level">
|
||
<input type="hidden" name="id" id="level_id" value="0">
|
||
<div style="display: flex; gap: 20px;">
|
||
<div class="form-group" style="flex: 2;">
|
||
<label>Nom du niveau (ex : Niveau 1)</label>
|
||
<input type="text" name="name" id="level_name" required placeholder="Niveau 1">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Slug (identifiant technique unique)</label>
|
||
<input type="text" name="slug" id="level_slug" required placeholder="niveau_1">
|
||
</div>
|
||
</div>
|
||
<div style="display: flex; gap: 20px;">
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Ressource requise</label>
|
||
<select name="resource_id" id="level_resource_id" required>
|
||
<?php foreach ($resources_list as $res): ?>
|
||
<option value="<?php echo $res['id']; ?>" <?php echo (stripos($res["name"], 'Expérience') !== false || stripos($res["name"], 'Experience') !== false) ? 'selected' : ''; ?>>
|
||
<?php echo htmlspecialchars($res["name"]); ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Quantité requise (nombre strictement positif)</label>
|
||
<input type="number" name="required_quantity" id="level_required_quantity" required min="1" placeholder="100">
|
||
</div>
|
||
</div>
|
||
<button type="submit" class="btn btn-add">ENREGISTRER LE NIVEAU</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetLevelForm()">ANNULER</button>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Nom</th>
|
||
<th>Slug</th>
|
||
<th>Ressource requise</th>
|
||
<th>Quantité requise</th>
|
||
<th>Actions</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php if (empty($levels_list)): ?>
|
||
<tr><td colspan="5" style="text-align: center; color: #8c92a3;">Aucun niveau configuré.</td></tr>
|
||
<?php else: ?>
|
||
<?php foreach ($levels_list as $lvl): ?>
|
||
<tr>
|
||
<td><strong><?php echo htmlspecialchars($lvl["name"]); ?></strong></td>
|
||
<td><code><?php echo htmlspecialchars($lvl['slug']); ?></code></td>
|
||
<td><?php echo htmlspecialchars($lvl['resource_name']); ?></td>
|
||
<td><?php echo number_format($lvl['required_quantity'], 0, ',', ' '); ?></td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editLevel(<?php echo json_encode($lvl, JSON_HEX_APOS); ?>)'>Modifier</button>
|
||
<a href="?tab=levels&delete_level=<?php echo $lvl['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce niveau ?')">Supprimer</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
<?php elseif ($tab === 'ranks'): ?>
|
||
<h3 style="color: #88c0d0;">Gestion des Grades</h3>
|
||
|
||
<?php if (isset($_GET['error']) && $_GET['error'] === 'overlap_levels'): ?>
|
||
<div style="background: #bf616a; color: #fff; padding: 10px; border-radius: 4px; margin-bottom: 15px;">
|
||
Erreur : Les intervalles de niveaux pour les grades utilisateurs ne doivent pas se chevaucher.
|
||
</div>
|
||
<?php elseif (isset($_GET['error']) && $_GET['error'] === 'invalid_range'): ?>
|
||
<div style="background: #bf616a; color: #fff; padding: 10px; border-radius: 4px; margin-bottom: 15px;">
|
||
Erreur : Le niveau maximum doit être supérieur ou égal au niveau minimum.
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div class="form-card">
|
||
<h4>Ajouter / Modifier un Grade</h4>
|
||
<form method="POST" id="rankForm" enctype="multipart/form-data">
|
||
<input type="hidden" name="action" value="upsert_grade">
|
||
<input type="hidden" name="id" id="rank_id" value="0">
|
||
<div style="display: flex; gap: 20px; margin-bottom: 15px;">
|
||
<div class="form-group" style="flex: 2;">
|
||
<label>Nom du Grade</label>
|
||
<input type="text" name="name" id="rank_name" required placeholder="Ex: Pionnier">
|
||
</div>
|
||
<div class="form-group" style="flex: 2;">
|
||
<label>Slug (Identifiant technique unique)</label>
|
||
<input type="text" name="slug" id="rank_slug" required placeholder="Ex: pionnier">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Type d'utilisateur</label>
|
||
<select name="user_type" id="rank_type" required onchange="updateRankFields()">
|
||
<option value="utilisateur">Utilisateur</option>
|
||
<option value="GM">GM</option>
|
||
<option value="admin">Admin</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div style="display: flex; gap: 20px;">
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Niveau Minimum</label>
|
||
<input type="number" name="min_level" id="rank_min" min="0" placeholder="Ex: 1">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Niveau Maximum</label>
|
||
<input type="number" name="max_level" id="rank_max" min="0" placeholder="Ex: 10">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Image (PNG) - Optionnel</label>
|
||
<input type="file" name="image" accept="image/png">
|
||
</div>
|
||
</div>
|
||
<div style="margin-top: 15px;">
|
||
<button type="submit" class="btn btn-add">ENREGISTRER LE GRADE</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetRankForm()">ANNULER</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Visuel</th>
|
||
<th>Nom</th>
|
||
<th>Slug</th>
|
||
<th>Type</th>
|
||
<th>Intervalle Niveau</th>
|
||
<th>Actions</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php if (empty($ranks_list)): ?>
|
||
<tr><td colspan="6" style="text-align: center;">Aucun grade configuré.</td></tr>
|
||
<?php else: ?>
|
||
<?php foreach ($ranks_list as $r): ?>
|
||
<tr>
|
||
<td><img src="<?php echo htmlspecialchars($r["image_url"]); ?>" style="width:40px;"></td><td><strong><?php echo htmlspecialchars($r["name"]); ?></strong></td>
|
||
<td><code><?php echo htmlspecialchars($r['slug']); ?></code></td>
|
||
<td>
|
||
<span class="badge <?php echo $r['user_type'] === 'admin' ? 'tag-malus' : ($r['user_type'] === 'GM' ? 'tag-bonus' : ''); ?>"
|
||
style="background: <?php echo $r['user_type'] === 'admin' ? '#bf616a' : ($r['user_type'] === 'GM' ? '#ebcb8b' : '#88c0d0'); ?>; color: #2e3440; padding: 2px 8px; border-radius: 10px; font-size: 10px; text-transform: uppercase; font-weight: bold;">
|
||
<?php echo htmlspecialchars($r['user_type']); ?>
|
||
</span>
|
||
</td>
|
||
<td>
|
||
<?php if ($r['user_type'] === 'utilisateur'): ?>
|
||
<?php echo $r['min_level']; ?> - <?php echo $r['max_level']; ?>
|
||
<?php else: ?>
|
||
<span style="color: #4c566a;">N/A</span>
|
||
<?php endif; ?>
|
||
</td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editRank(<?php echo json_encode($r, JSON_HEX_APOS); ?>)'>Modifier</button>
|
||
<a href="?tab=ranks&delete_grade=<?php echo $r['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce grade ?')">Supprimer</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
<?php elseif ($tab === 'guilds'): ?>
|
||
<h3 style="color: #88c0d0;">Gestion des Guildes</h3>
|
||
<div class="form-card">
|
||
<h4>Paramètres globaux des Guildes</h4>
|
||
<form method="POST" action="admin.php?tab=guilds">
|
||
<input type="hidden" name="action" value="update_guild_requirements">
|
||
<div class="form-group">
|
||
<label>Limite de membres par guilde</label>
|
||
<input type="number" name="guild_member_limit" value="<?php echo htmlspecialchars($guild_member_limit); ?>">
|
||
</div>
|
||
|
||
<h4>Coût de création</h4>
|
||
<table>
|
||
<thead><tr><th>Ressource</th><th>Quantité requise</th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($guild_requirements as $req): ?>
|
||
<tr>
|
||
<td>
|
||
<i class="fa-solid <?php echo htmlspecialchars($req['icon'] ?: 'fa-gem'); ?>"></i>
|
||
<?php echo htmlspecialchars($req["name"]); ?>
|
||
</td>
|
||
<td><input type="number" name="res_<?php echo $req["id"]; ?>" value="<?php echo $req["amount"] ?: 0; ?>"></td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
<button type="submit" class="btn btn-add" style="margin-top: 15px;">ENREGISTRER</button>
|
||
</form>
|
||
</div>
|
||
<?php elseif ($tab === 'badges'): ?>
|
||
<h3 style="color: #88c0d0;">Titres & Badges</h3>
|
||
<div style="display: flex; gap: 20px; align-items: flex-start;">
|
||
|
||
<!-- COLONNE GAUCHE : TITRES -->
|
||
<div style="flex: 1; background: #0a1420; padding: 20px; border: 1px solid #2d3545; border-radius: 4px;">
|
||
<h4 style="color: #88c0d0; border-bottom: 1px solid #2d3545; padding-bottom: 10px; margin-bottom: 20px;">
|
||
<i class="fa-solid fa-id-card"></i> Gestion des Titres
|
||
</h4>
|
||
|
||
<form method="POST" id="titleForm" class="form-card" style="margin-bottom: 20px;">
|
||
<input type="hidden" name="action" value="upsert_title">
|
||
<input type="hidden" name="id" id="title_id" value="0">
|
||
|
||
<div class="form-group">
|
||
<label>Nom du titre</label>
|
||
<input type="text" name="name" id="title_name" required placeholder="Ex: Pionnier du Nexus">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Slug (Identifiant technique)</label>
|
||
<input type="text" name="slug" id="title_slug" required placeholder="Ex: pioneer">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Type d'utilisateur autorisé</label>
|
||
<select name="allowed_user_type" id="title_allowed_type">
|
||
<option value="all">Tous (all)</option>
|
||
<option value="user">Utilisateurs standards</option>
|
||
<option value="gm">Maîtres de jeu (GM)</option>
|
||
<option value="admin">Administrateurs</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Niveau minimum requis</label>
|
||
<input type="number" name="required_level" id="title_req_level" value="0" min="0">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Couleur du titre</label>
|
||
<input type="color" name="color" id="title_color" value="#ffffff">
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 10px;">
|
||
<button type="submit" class="btn btn-add" style="flex: 1;">ENREGISTRER</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetTitleForm()">ANNULER</button>
|
||
</div>
|
||
</form>
|
||
|
||
<table style="font-size: 13px;">
|
||
<thead>
|
||
<tr>
|
||
<th>Titre</th>
|
||
<th>Slug</th>
|
||
<th>Niveau</th>
|
||
<th>Couleur</th>
|
||
<th>Actions</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($titles_list as $t): ?>
|
||
<tr>
|
||
<td><strong style="color: <?php echo $t['color'] ?: '#ffffff'; ?>;"><?php echo htmlspecialchars($t['name']); ?></strong></td>
|
||
<td><code style="color: #ebcb8b;"><?php echo htmlspecialchars($t['slug']); ?></code></td>
|
||
<td><?php echo $t['required_level']; ?></td>
|
||
<td><div style="width: 20px; height: 20px; border-radius: 50%; background: <?php echo $t['color'] ?: '#ffffff'; ?>; border: 1px solid #2d3545;"></div></td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editTitle(<?php echo json_encode($t, JSON_HEX_APOS); ?>)'>Modifier</button>
|
||
<a href="?tab=badges&delete_title=<?php echo $t['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce titre ?')">X</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- COLONNE DROITE : BADGES -->
|
||
<div style="flex: 1; background: #0a1420; padding: 20px; border: 1px solid #2d3545; border-radius: 4px;">
|
||
<h4 style="color: #88c0d0; border-bottom: 1px solid #2d3545; padding-bottom: 10px; margin-bottom: 20px;">
|
||
<i class="fa-solid fa-id-badge"></i> Gestion des Badges
|
||
</h4>
|
||
|
||
<form method="POST" id="badgeForm" class="form-card" enctype="multipart/form-data" style="margin-bottom: 20px;">
|
||
<input type="hidden" name="action" value="upsert_badge">
|
||
<input type="hidden" name="id" id="badge_id" value="0">
|
||
|
||
<div style="display: flex; gap: 10px;">
|
||
<div class="form-group" style="flex: 2;">
|
||
<label>Image du badge</label>
|
||
<input type="file" name="image" accept="image/*">
|
||
</div>
|
||
<div id="badge_preview_container" style="flex: 1; text-align: center; background: #0f172a; border: 1px solid #334155; border-radius: 4px; padding: 5px; display: none;">
|
||
<img id="badge_preview" src="" style="max-height: 50px; max-width: 50px;">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Nom du badge</label>
|
||
<input type="text" name="name" id="badge_name" required placeholder="Ex: Fondateur">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Slug (Identifiant technique)</label>
|
||
<input type="text" name="slug" id="badge_slug" required placeholder="Ex: founder">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Type d'utilisateur autorisé</label>
|
||
<select name="allowed_user_type" id="badge_allowed_type">
|
||
<option value="all">Tous (all)</option>
|
||
<option value="user">Utilisateurs standards</option>
|
||
<option value="gm">Maîtres de jeu (GM)</option>
|
||
<option value="admin">Administrateurs</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Niveau minimum requis</label>
|
||
<input type="number" name="required_level" id="badge_req_level" value="0" min="0">
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 10px;">
|
||
<button type="submit" class="btn btn-add" style="flex: 1;">ENREGISTRER</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetBadgeForm()">ANNULER</button>
|
||
</div>
|
||
</form>
|
||
|
||
<table style="font-size: 13px;">
|
||
<thead>
|
||
<tr>
|
||
<th>Visuel</th>
|
||
<th>Badge</th>
|
||
<th>Slug</th>
|
||
<th>Niveau</th>
|
||
<th>Actions</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($badges_list as $b): ?>
|
||
<tr>
|
||
<td style="text-align: center;">
|
||
<img src="<?php echo htmlspecialchars($b['image_url']); ?>" style="max-height: 30px; max-width: 30px;">
|
||
</td>
|
||
<td><strong><?php echo htmlspecialchars($b['name']); ?></strong></td>
|
||
<td><code style="color: #ebcb8b;"><?php echo htmlspecialchars($b['slug']); ?></code></td>
|
||
<td><?php echo $b['required_level']; ?></td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editBadge(<?php echo json_encode($b, JSON_HEX_APOS); ?>)'>Modifier</button>
|
||
<a href="?tab=badges&delete_badge=<?php echo $b['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce badge ?')">X</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<?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; margin-bottom: 15px;">
|
||
<div class="form-group" style="flex: 1; background: rgba(0,0,0,0.2); padding: 10px; border-radius: 4px; border: 1px solid #334155;">
|
||
<label style="color: #88c0d0; font-weight: bold;">Contrôles activés</label>
|
||
<div style="display: flex; gap: 20px; margin-top: 5px;">
|
||
<div style="display: flex; align-items: center; gap: 10px;">
|
||
<input type="checkbox" name="orbital_control_enabled" id="obj_orbital_enabled" checked style="width: auto;">
|
||
<label for="obj_orbital_enabled" style="margin-bottom: 0; cursor: pointer;">Orbital</label>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 10px;">
|
||
<input type="checkbox" name="terrestrial_control_enabled" id="obj_terrestrial_enabled" checked style="width: auto;">
|
||
<label for="obj_terrestrial_enabled" style="margin-bottom: 0; cursor: pointer;">Terrestre</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="form-group" style="flex: 1; background: rgba(136, 192, 208, 0.1); padding: 10px; border-radius: 4px; border: 1px solid #88c0d0;">
|
||
<label style="color: #88c0d0; font-weight: bold;">Règle(s) à appliquer</label>
|
||
<select name="status_profile_id" id="obj_profile_id" style="margin-top: 5px;">
|
||
<option value="">(Aucune règle - Statut fixe)</option>
|
||
<?php foreach ($status_profiles_list as $p): ?>
|
||
<option value="<?php echo $p['id']; ?>"><?php echo htmlspecialchars($p["name"]); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</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>Contrôles</th><th>Règles</th><th>Bonus/Malus</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><br><small><code><?php echo htmlspecialchars($o['slug']); ?></code></small></td>
|
||
<td style="text-align: center;">
|
||
<div style="display: flex; flex-direction: column; gap: 4px; align-items: center;">
|
||
<span style="font-size: 10px; display: inline-flex; align-items: center; gap: 3px; padding: 2px 6px; border-radius: 4px; background: <?php echo $o['orbital_control_enabled'] ? 'rgba(163, 190, 140, 0.2)' : 'rgba(191, 97, 106, 0.2)'; ?>; color: <?php echo $o['orbital_control_enabled'] ? '#a3be8c' : '#bf616a'; ?>; border: 1px solid <?php echo $o['orbital_control_enabled'] ? '#a3be8c' : '#bf616a'; ?>; width: 90px; justify-content: center;">
|
||
<i class="fa-solid <?php echo $o['orbital_control_enabled'] ? 'fa-check' : 'fa-xmark'; ?>"></i> ORBITAL
|
||
</span>
|
||
<span style="font-size: 10px; display: inline-flex; align-items: center; gap: 3px; padding: 2px 6px; border-radius: 4px; background: <?php echo $o['terrestrial_control_enabled'] ? 'rgba(163, 190, 140, 0.2)' : 'rgba(191, 97, 106, 0.2)'; ?>; color: <?php echo $o['terrestrial_control_enabled'] ? '#a3be8c' : '#bf616a'; ?>; border: 1px solid <?php echo $o['terrestrial_control_enabled'] ? '#a3be8c' : '#bf616a'; ?>; width: 90px; justify-content: center;">
|
||
<i class="fa-solid <?php echo $o['terrestrial_control_enabled'] ? 'fa-check' : 'fa-xmark'; ?>"></i> TERRESTRE
|
||
</span>
|
||
</div>
|
||
</td>
|
||
<td>
|
||
<?php
|
||
$p_name = "<em>Fixe</em>";
|
||
foreach($status_profiles_list as $p) if($p['id'] == $o['status_profile_id']) $p_name = htmlspecialchars($p["name"]);
|
||
echo $p_name;
|
||
?>
|
||
</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>
|
||
<button class="btn btn-edit" onclick='editObject(<?php echo json_encode($o, JSON_HEX_APOS); ?>)'>Modifier</button>
|
||
<a href="?tab=objects&delete_object=<?php echo $o['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cet objet ?')">Supprimer</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); ?>)'>Modifier</button>
|
||
<a href="?tab=modifiers&delete_modifier=<?php echo $m['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce modificateur ?')">Supprimer</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<?php elseif ($tab === 'statuses'): ?>
|
||
<h3 style="color: #88c0d0;">Statuts / États</h3>
|
||
<div style="display: flex; gap: 30px; align-items: flex-start;">
|
||
<!-- LEFT: Status Management -->
|
||
<div style="flex: 1;">
|
||
<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 class="form-group" style="flex: 0 0 100px;">
|
||
<label>Clignotement</label>
|
||
<label class="switch">
|
||
<input type="checkbox" name="is_blinking" id="st_is_blinking">
|
||
<span class="slider"></span>
|
||
</label>
|
||
</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>
|
||
<?php
|
||
$c = $s['color'];
|
||
$isBlink = strpos($c, ';blink') !== false;
|
||
$pureColor = str_replace(';blink', '', $c);
|
||
?>
|
||
<td><div class="<?php echo $isBlink ? 'blink-effect' : ''; ?>" style="width: 20px; height: 20px; background: <?php echo $pureColor; ?>; 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); ?>)'>Modifier</button>
|
||
<a href="?tab=statuses&delete_status=<?php echo $s['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce statut ?')">Supprimer</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- RIGHT: Rules Management -->
|
||
<div style="flex: 1.5;">
|
||
<!-- PROFILE MANAGEMENT -->
|
||
<div class="form-card" style="border-color: #ebcb8b; margin-bottom: 20px;">
|
||
<h4 style="color: #ebcb8b;"><i class="fa-solid fa-layer-group"></i> PROFILS / GROUPES DE RÈGLES</h4>
|
||
<form method="POST" id="profileForm" style="display: flex; gap: 10px; align-items: flex-end;">
|
||
<input type="hidden" name="action" value="upsert_status_profile">
|
||
<input type="hidden" name="id" id="prof_id" value="0">
|
||
<div class="form-group" style="flex: 1; margin-bottom: 0;">
|
||
<label>Nom du Profil</label>
|
||
<input type="text" name="name" id="prof_name" required placeholder="Ex: Planètes Spéciales">
|
||
</div>
|
||
<div class="form-group" style="flex: 1; margin-bottom: 0;">
|
||
<label>Slug</label>
|
||
<input type="text" name="slug" id="prof_slug" required placeholder="Ex: planetes_speciales">
|
||
</div>
|
||
<button type="submit" class="btn btn-add" style="margin-bottom: 0;">ENREGISTRER</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff; margin-bottom: 0;" onclick="resetProfileForm()">ANNULER</button>
|
||
</form>
|
||
<div style="margin-top: 15px; display: flex; flex-wrap: wrap; gap: 10px;">
|
||
<?php foreach ($status_profiles_list as $p): ?>
|
||
<div style="background: rgba(235, 203, 139, 0.1); border: 1px solid #ebcb8b; padding: 5px 10px; border-radius: 4px; display: flex; align-items: center; gap: 10px;">
|
||
<strong><?php echo htmlspecialchars($p["name"]); ?></strong> (<code><?php echo htmlspecialchars($p['slug']); ?></code>)
|
||
<div style="display: flex; gap: 5px;">
|
||
<i class="fa-solid fa-pen-to-square" style="cursor: pointer; color: #ebcb8b;" onclick='editProfile(<?php echo json_encode($p, JSON_HEX_APOS); ?>)'></i>
|
||
<a href="?tab=statuses&delete_status_profile=<?php echo $p['id']; ?>" onclick="return confirm('Supprimer ce profil ?')" style="color: #bf616a;"><i class="fa-solid fa-trash"></i></a>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
<div class="form-card" style="border-color: #88c0d0;">
|
||
<h4 style="color: #88c0d0;"><i class="fa-solid fa-gears"></i> CONFIGURATION DES RÈGLES</h4>
|
||
<form method="POST" id="ruleForm">
|
||
<input type="hidden" name="action" value="upsert_status_rule">
|
||
<input type="hidden" name="id" id="rule_id" value="0">
|
||
|
||
<div style="display: flex; gap: 15px; margin-bottom: 15px;">
|
||
<div class="form-group" style="flex: 1.5;">
|
||
<label>Nom de la règle</label>
|
||
<input type="text" name="name" id="rule_name" required placeholder="Ex: Occupation ennemie">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Profile / Groupe</label>
|
||
<select name="profile_id" id="rule_profile_id" required>
|
||
<?php foreach ($status_profiles_list as $p): ?>
|
||
<option value="<?php echo $p['id']; ?>"><?php echo htmlspecialchars($p["name"]); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Statut à appliquer</label>
|
||
<select name="status_id" id="rule_status_id" required>
|
||
<?php foreach ($statuses_list as $s): ?>
|
||
<option value="<?php echo $s['id']; ?>"><?php echo htmlspecialchars($s["name"]); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
<div class="form-group" style="flex: 0.5;">
|
||
<label>Priorité</label>
|
||
<input type="number" name="priority" id="rule_priority" value="0">
|
||
</div>
|
||
</div>
|
||
|
||
<div style="background: rgba(0,0,0,0.2); padding: 15px; border-radius: 4px; border: 1px solid #334155; margin-bottom: 15px;">
|
||
<div style="display: flex; gap: 20px; align-items: stretch;">
|
||
|
||
<!-- COLONNE ORBITALE -->
|
||
<div style="flex: 1; display: flex; flex-direction: column; gap: 15px; padding-right: 15px; border-right: 1px dashed #334155;">
|
||
<div style="font-size: 11px; color: #88c0d0; font-weight: bold; text-align: center; border-bottom: 1px solid #334155; padding-bottom: 5px; margin-bottom: 5px;">EN ORBITE</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 0;">
|
||
<label style="font-size: 10px;">Nombre de factions</label>
|
||
<div style="display: flex; gap: 5px;">
|
||
<select name="orbital_count_op" id="rule_orb_op" style="width: 70px;">
|
||
<option value="">-</option>
|
||
<option value="=">=</option>
|
||
<option value=">">></option>
|
||
<option value="<"><</option>
|
||
<option value=">=">>=</option>
|
||
<option value="<="><=</option>
|
||
</select>
|
||
<input type="number" name="orbital_count_val" id="rule_orb_val" placeholder="0">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 0;">
|
||
<label style="font-size: 10px;">Filtre Dominance</label>
|
||
<div class="ms-container" id="ms_orb">
|
||
<div class="ms-display" onclick="toggleMS('ms_orb_list')">Toutes / Peu importe</div>
|
||
<div class="ms-dropdown" id="ms_orb_list">
|
||
<label class="ms-item"><input type="checkbox" value="none" onchange="updateMSLabel('ms_orb')"> Aucune (Vide)</label>
|
||
<?php foreach($factions_list as $f): if($f["name"] !== 'Aucune'): ?>
|
||
<label class="ms-item"><input type="checkbox" value="<?php echo $f['id']; ?>" name="orbital_dominance[]" onchange="updateMSLabel('ms_orb')"> <?php echo htmlspecialchars($f["name"]); ?></label>
|
||
<?php endif; endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- COLONNE COMBINAISON (MILIEU) -->
|
||
<div style="flex: 0 0 100px; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 10px; background: rgba(136, 192, 208, 0.05); border-radius: 8px; border: 1px solid rgba(136, 192, 208, 0.2); padding: 10px;">
|
||
<label style="font-size: 10px; color: #88c0d0; font-weight: bold; text-transform: uppercase;">Combinaison</label>
|
||
<select name="combine_mode" id="rule_combine" style="width: 100%; text-align: center; font-weight: bold; color: #ebcb8b; background: #2e3440; border-color: #88c0d0;">
|
||
<option value="OR">OU</option>
|
||
<option value="AND">ET</option>
|
||
</select>
|
||
<div style="font-size: 9px; color: #d8dee9; text-align: center; opacity: 0.7;">(Orbital) [?] (Sol)</div>
|
||
</div>
|
||
|
||
<!-- COLONNE SOL -->
|
||
<div style="flex: 1; display: flex; flex-direction: column; gap: 15px; padding-left: 15px; border-left: 1px dashed #334155;">
|
||
<div style="font-size: 11px; color: #88c0d0; font-weight: bold; text-align: center; border-bottom: 1px solid #334155; padding-bottom: 5px; margin-bottom: 5px;">AU SOL</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 0;">
|
||
<label style="font-size: 10px;">Nombre de factions</label>
|
||
<div style="display: flex; gap: 5px;">
|
||
<select name="terrestrial_count_op" id="rule_terr_op" style="width: 70px;">
|
||
<option value="">-</option>
|
||
<option value="=">=</option>
|
||
<option value=">">></option>
|
||
<option value="<"><</option>
|
||
<option value=">=">>=</option>
|
||
<option value="<="><=</option>
|
||
</select>
|
||
<input type="number" name="terrestrial_count_val" id="rule_terr_val" placeholder="0">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 0;">
|
||
<label style="font-size: 10px;">Filtre Dominance</label>
|
||
<div class="ms-container" id="ms_terr">
|
||
<div class="ms-display" onclick="toggleMS('ms_terr_list')">Toutes / Peu importe</div>
|
||
<div class="ms-dropdown" id="ms_terr_list">
|
||
<label class="ms-item"><input type="checkbox" value="none" onchange="updateMSLabel('ms_terr')"> Aucune (Vide)</label>
|
||
<?php foreach($factions_list as $f): if($f["name"] !== 'Aucune'): ?>
|
||
<label class="ms-item"><input type="checkbox" value="<?php echo $f['id']; ?>" name="terrestrial_dominance[]" onchange="updateMSLabel('ms_terr')"> <?php echo htmlspecialchars($f["name"]); ?></label>
|
||
<?php endif; endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display: flex; align-items: center; gap: 10px; padding-top: 15px; margin-top: 15px; border-top: 1px solid #334155;">
|
||
<input type="checkbox" name="is_empty_case" id="rule_empty" style="width: auto;">
|
||
<label for="rule_empty" style="margin-bottom: 0; color: #ebcb8b;">Cas "CASE VIDE" (Aucune faction nulle part)</label>
|
||
</div>
|
||
</div>
|
||
|
||
<button type="submit" class="btn btn-add">ENREGISTRER LA RÈGLE</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetRuleForm()">ANNULER</button>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead><tr><th>Profile</th><th>Priorité</th><th>Nom / Condition</th><th>Statut</th><th>Actions</th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($status_rules_list as $r): ?>
|
||
<tr>
|
||
<td><span style="background: #3b4252; padding: 2px 6px; border-radius: 4px; font-size: 10px;"><?php echo htmlspecialchars($r['profile_name'] ?: 'Standard'); ?></span></td>
|
||
<td><code><?php echo $r['priority']; ?></code></td>
|
||
<td>
|
||
<strong><?php echo htmlspecialchars($r["name"]); ?></strong><br>
|
||
<small style="color: #8c92a3; font-size: 10px;">
|
||
<?php
|
||
$orb_conds = [];
|
||
if($r['orbital_count_op']) $orb_conds[] = "Factions " . $r['orbital_count_op'] . " " . $r['orbital_count_val'];
|
||
if($r['orbital_dominance']) $orb_conds[] = "IN (" . $r['orbital_dominance'] . ")";
|
||
|
||
$terr_conds = [];
|
||
if($r['terrestrial_count_op']) $terr_conds[] = "Factions " . $r['terrestrial_count_op'] . " " . $r['terrestrial_count_val'];
|
||
if($r['terrestrial_dominance']) $terr_conds[] = "IN (" . $r['terrestrial_dominance'] . ")";
|
||
|
||
$final_parts = [];
|
||
if ($r['is_empty_case']) $final_parts[] = "Case Vide";
|
||
|
||
$orb_str = !empty($orb_conds) ? "Orbital (" . implode(' AND ', $orb_conds) . ")" : "";
|
||
$terr_str = !empty($terr_conds) ? "Ground (" . implode(' AND ', $terr_conds) . ")" : "";
|
||
|
||
if ($orb_str && $terr_str) {
|
||
$sep = ($r['combine_mode'] == 'AND') ? ' AND ' : ' OR ';
|
||
$final_parts[] = $orb_str . $sep . $terr_str;
|
||
} elseif ($orb_str) {
|
||
$final_parts[] = $orb_str;
|
||
} elseif ($terr_str) {
|
||
$final_parts[] = $terr_str;
|
||
}
|
||
|
||
echo !empty($final_parts) ? implode(' AND ', $final_parts) : '<em>Toujours vrai</em>';
|
||
?>
|
||
</small>
|
||
</td>
|
||
<td><span style="color: <?php echo str_replace(';blink','', $statuses_list[array_search($r['status_id'], array_column($statuses_list, 'id'))]['color'] ?? '#fff'); ?>; font-weight: bold;"><i class="fa-solid fa-circle" style="font-size: 8px;"></i> <?php echo htmlspecialchars($r['status_name']); ?></span></td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editRule(<?php echo json_encode($r, JSON_HEX_APOS); ?>)'>Modifier</button>
|
||
<a href="?tab=statuses&delete_status_rule=<?php echo $r['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cette règle ?')">Supprimer</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<?php elseif ($tab === 'settlement_types'): ?>
|
||
<h3 style="color: #88c0d0;">Lieux et points d’intérêt</h3>
|
||
<div class="form-card">
|
||
<h4>Ajouter / Modifier un Lieu et point d’intérêt</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); ?>)'>Modifier</button>
|
||
<a href="?tab=settlement_types&delete_settlement_type=<?php echo $st['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce type ?')">Supprimer</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>
|
||
|
||
<div class="form-group">
|
||
<label style="font-size: 12px; color: #8c92a3;">Alliances (Réciprocité automatique)</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 ($factions_list as $potential_ally): ?>
|
||
<label class="alliance-label" style="font-size: 11px; display: flex; align-items: center; gap: 5px; cursor: pointer;" data-id="<?php echo $potential_ally['id']; ?>">
|
||
<input type="checkbox" name="alliances[]" value="<?php echo $potential_ally['id']; ?>" class="alliance-checkbox" data-id="<?php echo $potential_ally['id']; ?>">
|
||
<span style="padding: 2px 8px; border-radius: 4px; background: #334155; color: #fff;">
|
||
<?php echo htmlspecialchars($potential_ally["name"]); ?>
|
||
</span>
|
||
</label>
|
||
<?php endforeach; ?>
|
||
</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>Alliances</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>
|
||
<?php
|
||
$stmt = $db->prepare("SELECT f.name FROM factions f JOIN faction_alliances fa ON (f.id = fa.faction_id_1 OR f.id = fa.faction_id_2) WHERE (fa.faction_id_1 = ? OR fa.faction_id_2 = ?) AND f.id != ?");
|
||
$stmt->execute([$f['id'], $f['id'], $f['id']]);
|
||
$allies = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||
if(empty($allies)) echo '<span style="color: #4c566a;">Aucune</span>';
|
||
foreach($allies as $ally) echo '<span class="modifier-tag tag-bonus" style="font-size: 9px;">' . htmlspecialchars($ally) . '</span>';
|
||
?>
|
||
</td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editFaction(<?php echo json_encode($f, JSON_HEX_APOS); ?>)'>Modifier</button>
|
||
<a href="?tab=factions&delete_faction=<?php echo $f['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cette faction ?')">Supprimer</a>
|
||
</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: Crédits">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Slug</label>
|
||
<input type="text" name="slug" id="res_slug" required placeholder="Ex: credits">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Icône (FontAwesome)</label>
|
||
<input type="text" name="icon" id="res_icon" placeholder="Ex: fa-coins">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Image (PNG/JPG)</label>
|
||
<input type="file" name="image" accept="image/*">
|
||
</div>
|
||
</div>
|
||
<div style="display: flex; gap: 20px; align-items: center;">
|
||
<div class="form-group" style="flex: 2;">
|
||
<label>Description</label>
|
||
<textarea name="description" id="res_desc" rows="1"></textarea>
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label style="display: flex; align-items: center; gap: 8px; cursor: pointer;">
|
||
<input type="checkbox" name="show_in_header" id="res_show_header" value="1" style="width: auto;"> Afficher dans le header global
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<button type="submit" class="btn btn-add">ENREGISTRER</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetResourceForm()">ANNULER</button>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead><tr><th>Visuel</th><th>Header</th><th>Nom</th><th>Slug</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: 30px; max-height: 30px;">
|
||
<?php elseif (!empty($r['icon'])): ?>
|
||
<i class="fa-solid <?php echo htmlspecialchars($r['icon']); ?> fa-lg"></i>
|
||
<?php endif; ?>
|
||
</td>
|
||
<td style="text-align: center;">
|
||
<?php if ($r['show_in_header']): ?>
|
||
<i class="fa-solid fa-check" style="color: #a3be8c;"></i>
|
||
<?php endif; ?>
|
||
</td>
|
||
<td><strong><?php echo htmlspecialchars($r["name"]); ?></strong></td>
|
||
<td><code><?php echo htmlspecialchars($r['slug']); ?></code></td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editResource(<?php echo json_encode($r, JSON_HEX_APOS); ?>)'>Modifier</button>
|
||
<a href="?tab=resources&delete_resource=<?php echo $r['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cette ressource ?')">Supprimer</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>Ajouter / 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: 1;">
|
||
<label>Nom de la Box</label>
|
||
<input type="text" name="name" id="lb_name" required>
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Slug</label>
|
||
<input type="text" name="slug" id="lb_slug" required>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Description</label>
|
||
<textarea name="description" id="lb_desc" rows="2"></textarea>
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 30px; margin-top: 20px;">
|
||
<!-- Configuration des Tirages -->
|
||
<div style="flex: 1;">
|
||
<h5 style="color: #ebcb8b;">Nombre de tirages (Probabilités)</h5>
|
||
<div id="rollsContainer">
|
||
<div class="sub-form-header">
|
||
<div style="flex: 1;">Nb Tirages</div>
|
||
<div style="flex: 1;">Probabilité (%)</div>
|
||
<div class="btn-del-row-placeholder"></div>
|
||
</div>
|
||
</div>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff; margin-top: 5px;" onclick="addRollRow()">+ AJOUTER NB TIRAGE</button>
|
||
</div>
|
||
|
||
<!-- Configuration du Loot -->
|
||
<div style="flex: 2;">
|
||
<h5 style="color: #88c0d0;">Objets possibles dans la box</h5>
|
||
<div id="itemsContainer">
|
||
<div class="sub-form-header">
|
||
<div style="flex: 1;">Ressource (Slug)</div>
|
||
<div style="flex: 1;">Probabilité (%)</div>
|
||
<div style="flex: 1;">Quantité (Min/Max)</div>
|
||
<div style="flex: 1;">Garanti ?</div>
|
||
<div class="btn-del-row-placeholder"></div>
|
||
</div>
|
||
</div>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff; margin-top: 5px;" onclick="addItemRow()">+ AJOUTER OBJET AU LOOT</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="margin-top: 25px;">
|
||
<button type="submit" class="btn btn-add">ENREGISTRER LA LOOTBOX</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetLootboxForm()">ANNULER</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<table>
|
||
<thead><tr><th>Nom</th><th>Slug</th><th>Tirages Possibles</th><th>Nombre d'items</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 style="font-size: 11px;">
|
||
<?php foreach($lb['rolls'] as $r) echo $r['roll_count'] . " (" . $r['probability'] . "%) "; ?>
|
||
</td>
|
||
<td><?php echo count($lb['items']); ?></td>
|
||
<td>
|
||
<button class="btn btn-edit" onclick='editLootbox(<?php echo json_encode($lb, JSON_HEX_APOS); ?>)'>Modifier</button>
|
||
<a href="?tab=lootboxes&delete_lootbox=<?php echo $lb['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cette lootbox ?')">Supprimer</a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<?php elseif ($tab === 'project_logs'): ?>
|
||
<h3 style="color: #88c0d0;">Journal de Bord du Projet</h3>
|
||
<div class="form-card">
|
||
<h4>Nouvelle Entrée</h4>
|
||
<form method="POST" id="logForm">
|
||
<input type="hidden" name="action" value="upsert_project_log">
|
||
<input type="hidden" name="id" id="log_id" value="0">
|
||
<div style="display: flex; gap: 20px;">
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Version</label>
|
||
<input type="text" name="version" id="log_version" required placeholder="Ex: 0.1.0">
|
||
</div>
|
||
<div class="form-group" style="flex: 3;">
|
||
<label>Titre</label>
|
||
<input type="text" name="title" id="log_title" required placeholder="Résumé des changements">
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Contenu (Détails)</label>
|
||
<textarea name="content" id="log_content" rows="4"></textarea>
|
||
</div>
|
||
<button type="submit" class="btn btn-add">PUBLIER</button>
|
||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetLogForm()">ANNULER</button>
|
||
</form>
|
||
</div>
|
||
|
||
<?php foreach ($project_logs_list as $log): ?>
|
||
<div style="background: #0a0f1d; border: 1px solid #2d3545; padding: 20px; margin-bottom: 20px; position: relative;">
|
||
<div style="display: flex; justify-content: space-between; align-items: flex-start;">
|
||
<div>
|
||
<span style="background: #ebcb8b; color: #000; padding: 2px 8px; border-radius: 4px; font-weight: bold; font-size: 12px;"><?php echo htmlspecialchars($log['version']); ?></span>
|
||
<h4 style="display: inline; margin-left: 10px; color: #88c0d0;"><?php echo htmlspecialchars($log['title']); ?></h4>
|
||
</div>
|
||
<div style="font-size: 12px; color: #4c566a;">
|
||
<i class="fa-solid fa-calendar-day"></i> <?php echo date('d/m/Y H:i', strtotime($log['created_at'])); ?>
|
||
</div>
|
||
</div>
|
||
<div style="margin-top: 15px; font-size: 14px; line-height: 1.6; color: #d8dee9; white-space: pre-line;">
|
||
<?php echo htmlspecialchars($log['content']); ?>
|
||
</div>
|
||
<div style="margin-top: 15px; border-top: 1px solid #1a202c; padding-top: 10px; text-align: right;">
|
||
<button class="btn btn-edit" style="padding: 4px 10px; font-size: 10px;" onclick='editLog(<?php echo json_encode($log, JSON_HEX_APOS); ?>)'>Modifier</button>
|
||
<a href="?tab=project_logs&delete_project_log=<?php echo $log['id']; ?>" class="btn btn-del" style="padding: 4px 10px; font-size: 10px;" onclick="return confirm('Supprimer cette entrée ?')">Supprimer</a>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
|
||
<?php endif; ?>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
function syncSlug(v,t){const e=document.getElementById(t);if(e){e.value=v.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g,'').replace(/[^a-z0-9]+/g,'-').replace(/^-+|-+$/g,'');} if(typeof checkUnitFormValidity==='function')checkUnitFormValidity();}
|
||
|
||
function checkUnitFormValidity(){const n=document.getElementById('unit_name')?.value,s=document.getElementById('unit_slug')?.value,g=document.getElementById('unit_grid_data')?.value,b=document.getElementById('unit_submit_btn');if(b){const v=n&&s&&g&&g!=='[]'&&g!=='';b.disabled=!v;b.style.opacity=v?'1':'0.5';}}
|
||
|
||
function editUnit(data) {
|
||
resetUnitForm();
|
||
document.getElementById('unit_id').value = data.id;
|
||
document.getElementById('unit_name').value = data.name;
|
||
document.getElementById('unit_slug').value = data.slug;
|
||
document.getElementById('unit_faction_id').value = data.faction_id || "";
|
||
document.getElementById('unit_points_per_hit').value = data.points_per_hit;
|
||
document.getElementById('unit_can_be_destroyed').checked = data.can_be_destroyed == 1;
|
||
document.getElementById('unit_can_be_captured').checked = data.can_be_captured == 1;
|
||
document.getElementById('unit_bonus_destruction').value = data.bonus_destruction;
|
||
document.getElementById('unit_bonus_capture').value = data.bonus_capture;
|
||
document.getElementById('unit_grid_data').value = data.grid_data;
|
||
setUnitGridFromData(data.grid_data);
|
||
|
||
if (data.rewards) {
|
||
data.rewards.forEach(r => {
|
||
addUnitRewardRow(r.action_type, r.resource_id, r.amount);
|
||
});
|
||
}
|
||
if(typeof checkUnitFormValidity==='function')checkUnitFormValidity();
|
||
window.scrollTo(0,0);
|
||
}
|
||
|
||
function resetUnitForm() {
|
||
document.getElementById('unitForm').reset();
|
||
document.getElementById('unit_id').value = 0;
|
||
document.getElementById('unit_grid_data').value = "";
|
||
document.getElementById('unitRewardsContainer').innerHTML = `
|
||
<div class="sub-form-header">
|
||
<div style="flex: 1;">Action</div>
|
||
<div style="flex: 1;">Ressource</div>
|
||
<div style="flex: 1;">Quantité</div>
|
||
<div class="btn-del-row-placeholder"></div>
|
||
</div>`;
|
||
const cells = document.querySelectorAll('.unit-cell');
|
||
cells.forEach(c => c.classList.remove('active'));
|
||
if(typeof checkUnitFormValidity==='function')checkUnitFormValidity();
|
||
}
|
||
|
||
function addUnitRewardRow(action = 'destroy', resId = '', amount = 0) {
|
||
const container = document.getElementById('unitRewardsContainer');
|
||
const row = document.createElement('div');
|
||
row.className = 'sub-form-row';
|
||
|
||
let resOptions = '';
|
||
<?php foreach ($resources_list as $res): ?>
|
||
resOptions += '<option value="<?php echo $res['id']; ?>" ' + (resId == <?php echo $res['id']; ?> ? 'selected' : '') + '><?php echo addslashes($res['name']); ?></option>';
|
||
<?php endforeach; ?>
|
||
|
||
row.innerHTML = `
|
||
<select name="reward_action[]" style="flex: 1;">
|
||
<option value="destroy" ${action === 'destroy' ? 'selected' : ''}>Destruction</option>
|
||
<option value="capture" ${action === 'capture' ? 'selected' : ''}>Capture</option>
|
||
</select>
|
||
<select name="reward_resource_id[]" style="flex: 1;">
|
||
<option value="">-- Ressource --</option>
|
||
${resOptions}
|
||
</select>
|
||
<input type="number" name="reward_amount[]" value="${amount}" style="flex: 1;" placeholder="Qté">
|
||
<div class="btn-del-row" onclick="this.parentElement.remove()">×</div>
|
||
`;
|
||
container.appendChild(row);
|
||
}
|
||
|
||
function createUnitGrid() {
|
||
const grid = document.getElementById('unitGrid');
|
||
if (!grid) return;
|
||
for (let i = 0; i < 36; i++) {
|
||
const cell = document.createElement('div');
|
||
cell.className = 'unit-cell';
|
||
cell.dataset.index = i;
|
||
cell.onclick = function() {
|
||
this.classList.toggle('active');
|
||
updateUnitGridData();
|
||
};
|
||
grid.appendChild(cell);
|
||
}
|
||
}
|
||
|
||
function updateUnitGridData() {
|
||
const activeCells = [];
|
||
document.querySelectorAll('.unit-cell.active').forEach(c => {
|
||
activeCells.push(parseInt(c.dataset.index));
|
||
});
|
||
document.getElementById("unit_grid_data").value = JSON.stringify(activeCells);
|
||
if(typeof checkUnitFormValidity==='function')checkUnitFormValidity();
|
||
}
|
||
|
||
function setUnitGridFromData(json) {
|
||
const cells = document.querySelectorAll('.unit-cell');
|
||
cells.forEach(c => c.classList.remove('active'));
|
||
try {
|
||
const activeIndices = JSON.parse(json);
|
||
activeIndices.forEach(idx => {
|
||
const cell = document.querySelector(`.unit-cell[data-index="${idx}"]`);
|
||
if (cell) cell.classList.add('active');
|
||
});
|
||
} catch(e) {}
|
||
}
|
||
|
||
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.getElementById('obj_orbital_enabled').checked = (data.orbital_control_enabled == 1);
|
||
document.getElementById('obj_terrestrial_enabled').checked = (data.terrestrial_control_enabled == 1);
|
||
document.getElementById('obj_profile_id').value = data.status_profile_id || "";
|
||
|
||
// Reset checkboxes
|
||
document.querySelectorAll('.modifier-checkbox').forEach(cb => cb.checked = false);
|
||
if (data.modifier_ids) {
|
||
data.modifier_ids.forEach(mid => {
|
||
const cb = document.querySelector(`.modifier-checkbox[data-id="${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 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 editStatus(data) {
|
||
document.getElementById('st_id').value = data.id;
|
||
document.getElementById('st_name').value = data.name;
|
||
document.getElementById('st_slug').value = data.slug;
|
||
|
||
let color = data.color;
|
||
let isBlinking = false;
|
||
if (color.indexOf(';blink') !== -1) {
|
||
isBlinking = true;
|
||
color = color.replace(';blink', '');
|
||
}
|
||
document.getElementById('st_color').value = color;
|
||
document.getElementById('st_color_picker').value = color;
|
||
document.getElementById('st_is_blinking').checked = isBlinking;
|
||
document.getElementById('st_desc').value = data.description;
|
||
window.scrollTo(0, 0);
|
||
}
|
||
|
||
function resetStatusForm() {
|
||
document.getElementById('statusForm').reset();
|
||
document.getElementById('st_id').value = 0;
|
||
}
|
||
|
||
function editProfile(data) {
|
||
document.getElementById('prof_id').value = data.id;
|
||
document.getElementById('prof_name').value = data.name;
|
||
document.getElementById('prof_slug').value = data.slug;
|
||
window.scrollTo(0, 0);
|
||
}
|
||
|
||
function resetProfileForm() {
|
||
document.getElementById('profileForm').reset();
|
||
document.getElementById('prof_id').value = 0;
|
||
}
|
||
|
||
function editRule(data) {
|
||
document.getElementById('rule_id').value = data.id;
|
||
document.getElementById('rule_name').value = data.name;
|
||
document.getElementById('rule_status_id').value = data.status_id;
|
||
document.getElementById('rule_profile_id').value = data.profile_id;
|
||
document.getElementById('rule_priority').value = data.priority;
|
||
document.getElementById('rule_orb_op').value = data.orbital_count_op || "";
|
||
document.getElementById('rule_orb_val').value = data.orbital_count_val !== null ? data.orbital_count_val : "";
|
||
document.getElementById('rule_terr_op').value = data.terrestrial_count_op || "";
|
||
document.getElementById('rule_terr_val').value = data.terrestrial_count_val !== null ? data.terrestrial_count_val : "";
|
||
document.getElementById('rule_combine').value = data.combine_mode || "OR";
|
||
document.getElementById('rule_empty').checked = data.is_empty_case == 1;
|
||
|
||
// Reset MS lists
|
||
resetMS('ms_orb');
|
||
resetMS('ms_terr');
|
||
|
||
if (data.orbital_dominance) {
|
||
const ids = data.orbital_dominance.split(',');
|
||
ids.forEach(id => {
|
||
const cb = document.querySelector(`#ms_orb_list input[value="${id}"]`);
|
||
if (cb) cb.checked = true;
|
||
});
|
||
updateMSLabel('ms_orb');
|
||
}
|
||
if (data.terrestrial_dominance) {
|
||
const ids = data.terrestrial_dominance.split(',');
|
||
ids.forEach(id => {
|
||
const cb = document.querySelector(`#ms_terr_list input[value="${id}"]`);
|
||
if (cb) cb.checked = true;
|
||
});
|
||
updateMSLabel('ms_terr');
|
||
}
|
||
window.scrollTo(0, 0);
|
||
}
|
||
|
||
function resetRuleForm() {
|
||
document.getElementById('ruleForm').reset();
|
||
document.getElementById('rule_id').value = 0;
|
||
resetMS('ms_orb');
|
||
resetMS('ms_terr');
|
||
}
|
||
|
||
function toggleMS(id) {
|
||
const dropdown = document.getElementById(id);
|
||
dropdown.style.display = dropdown.style.display === 'block' ? 'none' : 'block';
|
||
}
|
||
|
||
function resetMS(containerId) {
|
||
document.querySelectorAll(`#${containerId}_list input`).forEach(cb => cb.checked = false);
|
||
updateMSLabel(containerId);
|
||
}
|
||
|
||
function updateMSLabel(containerId) {
|
||
const container = document.getElementById(containerId);
|
||
const checkboxes = container.querySelectorAll('.ms-dropdown input:checked');
|
||
const display = container.querySelector('.ms-display');
|
||
|
||
if (checkboxes.length === 0) {
|
||
display.innerText = "Toutes / Peu importe";
|
||
} else if (checkboxes.length === 1) {
|
||
const text = checkboxes[0].parentElement.innerText.trim();
|
||
display.innerText = text;
|
||
} else {
|
||
display.innerText = checkboxes.length + " sélectionnées";
|
||
}
|
||
}
|
||
|
||
// Close MS dropdowns when clicking outside
|
||
document.addEventListener('click', function(e) {
|
||
if (!e.target.closest('.ms-container')) {
|
||
document.querySelectorAll('.ms-dropdown').forEach(d => d.style.display = 'none');
|
||
}
|
||
});
|
||
|
||
function editFaction(data) {
|
||
document.getElementById('fac_id').value = data.id;
|
||
document.getElementById('fac_name').value = data.name;
|
||
document.getElementById('fac_slug').value = data.slug;
|
||
document.getElementById('fac_color').value = data.color || "#808080";
|
||
document.getElementById('fac_color_picker').value = data.color || "#808080";
|
||
document.getElementById('fac_fa_icon').value = data.fa_icon || "";
|
||
|
||
document.querySelectorAll('.alliance-checkbox').forEach(cb => cb.checked = false);
|
||
if (data.alliance_ids) {
|
||
data.alliance_ids.forEach(id => {
|
||
const cb = document.querySelector(`.alliance-checkbox[data-id="${id}"]`);
|
||
if (cb) cb.checked = true;
|
||
});
|
||
}
|
||
window.scrollTo(0, 0);
|
||
}
|
||
|
||
function resetFactionForm() {
|
||
document.getElementById('factionForm').reset();
|
||
document.getElementById('fac_id').value = 0;
|
||
document.querySelectorAll('.alliance-checkbox').forEach(cb => cb.checked = false);
|
||
}
|
||
|
||
function editLevel(data) {
|
||
document.getElementById('level_id').value = data.id;
|
||
document.getElementById('level_name').value = data.name;
|
||
document.getElementById('level_slug').value = data.slug;
|
||
document.getElementById('level_resource_id').value = data.resource_id;
|
||
document.getElementById('level_required_quantity').value = data.required_quantity;
|
||
window.scrollTo(0, 0);
|
||
}
|
||
|
||
function resetLevelForm() {
|
||
document.getElementById('levelForm').reset();
|
||
document.getElementById('level_id').value = 0;
|
||
}
|
||
|
||
function editRank(data) {
|
||
document.getElementById('rank_id').value = data.id;
|
||
document.getElementById('rank_name').value = data.name;
|
||
document.getElementById('rank_slug').value = data.slug;
|
||
document.getElementById('rank_type').value = data.user_type;
|
||
document.getElementById('rank_min').value = data.min_level;
|
||
document.getElementById('rank_max').value = data.max_level;
|
||
updateRankFields();
|
||
window.scrollTo(0,0);
|
||
}
|
||
function resetRankForm() {
|
||
document.getElementById('rankForm').reset();
|
||
document.getElementById('rank_id').value = 0;
|
||
updateRankFields();
|
||
}
|
||
function updateRankFields() {
|
||
const rankTypeEl = document.getElementById('rank_type'); if (!rankTypeEl) return; const type = rankTypeEl.value;
|
||
const lvlGrp = document.getElementById('rank_min').parentElement.parentElement;
|
||
if (type === 'utilisateur') {
|
||
lvlGrp.style.display = 'flex';
|
||
} else {
|
||
lvlGrp.style.display = 'none';
|
||
}
|
||
}
|
||
|
||
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_header').checked = data.show_in_header == 1;
|
||
window.scrollTo(0, 0);
|
||
}
|
||
|
||
function resetResourceForm() {
|
||
document.getElementById('resourceForm').reset();
|
||
document.getElementById('res_id').value = 0;
|
||
}
|
||
|
||
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('rollsContainer').innerHTML = `
|
||
<div class="sub-form-header">
|
||
<div style="flex: 1;">Nb Tirages</div>
|
||
<div style="flex: 1;">Probabilité (%)</div>
|
||
<div class="btn-del-row-placeholder"></div>
|
||
</div>`;
|
||
if (data.rolls) {
|
||
data.rolls.forEach(r => addRollRow(r.roll_count, r.probability));
|
||
}
|
||
|
||
document.getElementById('itemsContainer').innerHTML = `
|
||
<div class="sub-form-header">
|
||
<div style="flex: 1;">Ressource (Slug)</div>
|
||
<div style="flex: 1;">Probabilité (%)</div>
|
||
<div style="flex: 1;">Quantité (Min/Max)</div>
|
||
<div style="flex: 1;">Garanti ?</div>
|
||
<div class="btn-del-row-placeholder"></div>
|
||
</div>`;
|
||
if (data.items) {
|
||
data.items.forEach(i => addItemRow(i.resource_slug, i.probability, i.quantity_min, i.quantity_max, i.is_guaranteed));
|
||
}
|
||
window.scrollTo(0, 0);
|
||
}
|
||
|
||
function resetLootboxForm() {
|
||
document.getElementById('lootboxForm').reset();
|
||
document.getElementById('lb_id').value = 0;
|
||
document.getElementById('rollsContainer').innerHTML = '';
|
||
document.getElementById('itemsContainer').innerHTML = '';
|
||
}
|
||
|
||
function addRollRow(count = 1, prob = 0) {
|
||
const row = document.createElement('div');
|
||
row.className = 'sub-form-row';
|
||
row.innerHTML = `
|
||
<input type="number" name="rolls_count[]" value="${count}" style="flex: 1;">
|
||
<input type="number" step="0.01" name="rolls_prob[]" value="${prob}" style="flex: 1;">
|
||
<div class="btn-del-row" onclick="this.parentElement.remove()">×</div>
|
||
`;
|
||
document.getElementById('rollsContainer').appendChild(row);
|
||
}
|
||
|
||
function addItemRow(slug = '', prob = 0, min = 1, max = 1, guaranteed = 0) {
|
||
const row = document.createElement('div');
|
||
row.className = 'sub-form-row';
|
||
|
||
let options = '<option value="">(Aléatoire)</option>';
|
||
const resList = <?php echo json_encode($resources_list); ?>;
|
||
resList.forEach(r => {
|
||
options += `<option value="${r.slug}" ${r.slug === slug ? 'selected' : ''}>${r.name}</option>`;
|
||
});
|
||
|
||
row.innerHTML = `
|
||
<select name="item_slug[]" style="flex: 1.5;">${options}</select>
|
||
<input type="number" step="0.01" name="item_prob[]" value="${prob}" style="flex: 1;">
|
||
<div style="flex: 1.5; display: flex; gap: 2px;">
|
||
<input type="number" name="item_qmin[]" value="${min}" style="width: 50%;">
|
||
<input type="number" name="item_qmax[]" value="${max}" style="width: 50%;">
|
||
</div>
|
||
<div style="flex: 1; text-align: center;">
|
||
<input type="checkbox" name="item_is_guaranteed[]" value="1" ${guaranteed == 1 ? 'checked' : ''} onchange="this.previousElementSibling.value = this.checked ? 1 : 0">
|
||
<input type="hidden" name="item_is_guaranteed_val[]" value="${guaranteed}">
|
||
</div>
|
||
<div class="btn-del-row" onclick="this.parentElement.remove()">×</div>
|
||
`;
|
||
document.getElementById('itemsContainer').appendChild(row);
|
||
}
|
||
|
||
function editLog(data) {
|
||
document.getElementById('log_id').value = data.id;
|
||
document.getElementById('log_version').value = data.version;
|
||
document.getElementById('log_title').value = data.title;
|
||
document.getElementById('log_content').value = data.content;
|
||
window.scrollTo(0, 0);
|
||
}
|
||
|
||
function resetLogForm() {
|
||
document.getElementById('logForm').reset();
|
||
document.getElementById('log_id').value = 0;
|
||
}
|
||
|
||
function editTitle(data) {
|
||
document.getElementById('title_id').value = data.id;
|
||
document.getElementById('title_name').value = data.name;
|
||
document.getElementById('title_slug').value = data.slug;
|
||
document.getElementById('title_allowed_type').value = data.allowed_user_type;
|
||
document.getElementById('title_req_level').value = data.required_level;
|
||
document.getElementById('title_color').value = data.color || "#ffffff";
|
||
window.scrollTo(0,0);
|
||
}
|
||
function resetTitleForm() {
|
||
document.getElementById('titleForm').reset();
|
||
document.getElementById('title_id').value = 0;
|
||
}
|
||
function editBadge(data) {
|
||
document.getElementById('badge_id').value = data.id;
|
||
document.getElementById('badge_name').value = data.name;
|
||
document.getElementById('badge_slug').value = data.slug;
|
||
document.getElementById('badge_allowed_type').value = data.allowed_user_type;
|
||
document.getElementById('badge_req_level').value = data.required_level;
|
||
|
||
if (data.image_url) {
|
||
document.getElementById('badge_preview').src = data.image_url;
|
||
document.getElementById('badge_preview_container').style.display = 'block';
|
||
} else {
|
||
document.getElementById('badge_preview_container').style.display = 'none';
|
||
}
|
||
window.scrollTo(0,0);
|
||
}
|
||
function resetBadgeForm() {
|
||
document.getElementById('badgeForm').reset();
|
||
document.getElementById('badge_id').value = 0;
|
||
document.getElementById('badge_preview_container').style.display = 'none';
|
||
}
|
||
|
||
document.addEventListener("DOMContentLoaded", function() {
|
||
updateRankFields();
|
||
if (document.getElementById('tab') === 'units' || <?php echo $tab === 'units' ? 'true' : 'false'; ?>) {
|
||
createUnitGrid();
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|