Autosave: 20260222-102030
This commit is contained in:
parent
4d1b2d5499
commit
1bb89f9b7e
151
admin.php
151
admin.php
@ -42,13 +42,29 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
$icon = $_POST['icon'];
|
||||
$description = $_POST['description'];
|
||||
$modifier_ids = isset($_POST['modifiers']) ? $_POST['modifiers'] : [];
|
||||
|
||||
$image_url = null;
|
||||
if ($id > 0) {
|
||||
$stmt_img = $db->prepare("SELECT image_url FROM celestial_object_types WHERE id = ?");
|
||||
$stmt_img->execute([$id]);
|
||||
$image_url = $stmt_img->fetchColumn();
|
||||
}
|
||||
|
||||
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
|
||||
$ext = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
|
||||
$filename = $slug . "_" . time() . "." . $ext;
|
||||
$target = "assets/images/celestial/" . $filename;
|
||||
if (move_uploaded_file($_FILES['image']['tmp_name'], $target)) {
|
||||
$image_url = $target;
|
||||
}
|
||||
}
|
||||
|
||||
if ($id > 0) {
|
||||
$stmt = $db->prepare("UPDATE celestial_object_types SET name = ?, slug = ?, icon = ?, description = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $slug, $icon, $description, $id]);
|
||||
$stmt = $db->prepare("UPDATE celestial_object_types SET name = ?, slug = ?, icon = ?, description = ?, image_url = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $slug, $icon, $description, $image_url, $id]);
|
||||
} else {
|
||||
$stmt = $db->prepare("INSERT INTO celestial_object_types (name, slug, icon, description) VALUES (?, ?, ?, ?)");
|
||||
$stmt->execute([$name, $slug, $icon, $description]);
|
||||
$stmt = $db->prepare("INSERT INTO celestial_object_types (name, slug, icon, description, image_url) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$name, $slug, $icon, $description, $image_url]);
|
||||
$id = $db->lastInsertId();
|
||||
}
|
||||
|
||||
@ -148,12 +164,50 @@ if (isset($_GET['delete_modifier'])) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Handle Faction CRUD
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_faction') {
|
||||
$id = (int)$_POST['id'];
|
||||
$name = $_POST['name'];
|
||||
$fa_icon = $_POST['fa_icon'];
|
||||
$image_url = null;
|
||||
if ($id > 0) {
|
||||
$stmt_img = $db->prepare("SELECT image_url FROM factions WHERE id = ?");
|
||||
$stmt_img->execute([$id]);
|
||||
$image_url = $stmt_img->fetchColumn();
|
||||
}
|
||||
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
|
||||
$ext = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
|
||||
$filename = "faction_" . time() . "." . $ext;
|
||||
$target = "assets/images/factions/" . $filename;
|
||||
if (move_uploaded_file($_FILES['image']['tmp_name'], $target)) {
|
||||
$image_url = $target;
|
||||
}
|
||||
}
|
||||
if ($id > 0) {
|
||||
$stmt = $db->prepare("UPDATE factions SET name = ?, image_url = ?, fa_icon = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $image_url, $fa_icon, $id]);
|
||||
} else {
|
||||
$stmt = $db->prepare("INSERT INTO factions (name, image_url, fa_icon) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$name, $image_url, $fa_icon]);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// --- DATA FETCHING ---
|
||||
$users_list = [];
|
||||
$objects_list = [];
|
||||
$statuses_list = [];
|
||||
$settlement_types_list = [];
|
||||
$modifiers_list = [];
|
||||
$factions_list = [];
|
||||
|
||||
if ($tab === 'users') {
|
||||
$users_list = $db->query("SELECT id, username, email, role FROM users ORDER BY username ASC")->fetchAll();
|
||||
@ -172,6 +226,8 @@ if ($tab === 'users') {
|
||||
$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();
|
||||
}
|
||||
|
||||
?>
|
||||
@ -240,6 +296,7 @@ if ($tab === 'users') {
|
||||
<a href="?tab=modifiers" class="tab-link <?php echo $tab === 'modifiers' ? 'active' : ''; ?>"><i class="fa-solid fa-bolt"></i> Bonus & Malus</a>
|
||||
<a href="?tab=statuses" class="tab-link <?php echo $tab === 'statuses' ? 'active' : ''; ?>"><i class="fa-solid fa-signal"></i> Statuts / États</a>
|
||||
<a href="?tab=settlement_types" class="tab-link <?php echo $tab === 'settlement_types' ? 'active' : ''; ?>"><i class="fa-solid fa-city"></i> Types d'Établissements</a>
|
||||
<a href="?tab=factions" class="tab-link <?php echo $tab === 'factions' ? 'active' : ''; ?>"><i class="fa-solid fa-flag"></i> Factions</a>
|
||||
</div>
|
||||
|
||||
<?php if ($tab === 'users'): ?>
|
||||
@ -279,7 +336,7 @@ if ($tab === 'users') {
|
||||
<h3 style="color: #88c0d0;">Objets Célestes</h3>
|
||||
<div class="form-card">
|
||||
<h4>Ajouter / Modifier un Objet</h4>
|
||||
<form method="POST" id="objectForm">
|
||||
<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;">
|
||||
@ -295,6 +352,10 @@ if ($tab === 'users') {
|
||||
<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;">
|
||||
@ -323,11 +384,17 @@ if ($tab === 'users') {
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead><tr><th>Icône</th><th>Nom</th><th>Slug</th><th>Bonus/Malus</th><th>Actions</th></tr></thead>
|
||||
<thead><tr><th>Visuel</th><th>Nom</th><th>Slug</th><th>Bonus/Malus</th><th>Actions</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach ($objects_list as $o): ?>
|
||||
<tr>
|
||||
<td><i class="fa-solid <?php echo htmlspecialchars($o['icon']); ?> fa-lg"></i></td>
|
||||
<td style="text-align: center;">
|
||||
<?php if (!empty($o['image_url'])): ?>
|
||||
<img src="<?php echo htmlspecialchars($o['image_url']); ?>?v=<?php echo time(); ?>" style="max-width: 40px; max-height: 40px; display: block; margin: 0 auto;">
|
||||
<?php else: ?>
|
||||
<i class="fa-solid <?php echo htmlspecialchars($o['icon']); ?> fa-lg"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><strong><?php echo htmlspecialchars($o['name']); ?></strong></td>
|
||||
<td><code><?php echo htmlspecialchars($o['slug']); ?></code></td>
|
||||
<td>
|
||||
@ -342,7 +409,7 @@ if ($tab === 'users') {
|
||||
<?php endforeach; ?>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-edit" onclick='editObject(<?php echo json_encode($o); ?>)'>Editer</button>
|
||||
<button class="btn btn-edit" onclick='editObject(<?php echo json_encode($o, JSON_HEX_APOS); ?>)'>Editer</button>
|
||||
<a href="?tab=objects&delete_object=<?php echo $o['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cet objet ?')">Suppr</a>
|
||||
</td>
|
||||
</tr>
|
||||
@ -392,7 +459,7 @@ if ($tab === 'users') {
|
||||
<td><strong><?php echo htmlspecialchars($m['name']); ?></strong></td>
|
||||
<td><small><?php echo htmlspecialchars($m['description']); ?></small></td>
|
||||
<td>
|
||||
<button class="btn btn-edit" onclick='editModifier(<?php echo json_encode($m); ?>)'>Editer</button>
|
||||
<button class="btn btn-edit" onclick='editModifier(<?php echo json_encode($m, JSON_HEX_APOS); ?>)'>Editer</button>
|
||||
<a href="?tab=modifiers&delete_modifier=<?php echo $m['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce modificateur ?')">Suppr</a>
|
||||
</td>
|
||||
</tr>
|
||||
@ -439,7 +506,7 @@ if ($tab === 'users') {
|
||||
<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); ?>)'>Editer</button>
|
||||
<button class="btn btn-edit" onclick='editStatus(<?php echo json_encode($s, JSON_HEX_APOS); ?>)'>Editer</button>
|
||||
<a href="?tab=statuses&delete_status=<?php echo $s['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce statut ?')">Suppr</a>
|
||||
</td>
|
||||
</tr>
|
||||
@ -482,13 +549,65 @@ if ($tab === 'users') {
|
||||
<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); ?>)'>Editer</button>
|
||||
<button class="btn btn-edit" onclick='editSettlementType(<?php echo json_encode($st, JSON_HEX_APOS); ?>)'>Editer</button>
|
||||
<a href="?tab=settlement_types&delete_settlement_type=<?php echo $st['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce type ?')">Suppr</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php elseif ($tab === 'factions'): ?>
|
||||
<h3 style="color: #88c0d0;">Gestion des Factions</h3>
|
||||
<div class="form-card">
|
||||
<h4>Ajouter / Modifier une Faction</h4>
|
||||
<form method="POST" id="factionForm" enctype="multipart/form-data">
|
||||
<input type="hidden" name="action" value="upsert_faction">
|
||||
<input type="hidden" name="id" id="fac_id" value="0">
|
||||
<div style="display: flex; gap: 20px;">
|
||||
<div class="form-group" style="flex: 2;">
|
||||
<label>Nom de la Faction</label>
|
||||
<input type="text" name="name" id="fac_name" required placeholder="Ex: Fédération, Empire...">
|
||||
</div>
|
||||
<div class="form-group" style="flex: 1;">
|
||||
<label>Icône (FontAwesome)</label>
|
||||
<input type="text" name="fa_icon" id="fac_fa_icon" placeholder="Ex: fa-users">
|
||||
</div>
|
||||
<div class="form-group" style="flex: 1;">
|
||||
<label>PNG (Prioritaire)</label>
|
||||
<input type="file" name="image" accept="image/png">
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-add">ENREGISTRER LA FACTION</button>
|
||||
<button type="button" class="btn" style="background: #4c566a; color: #fff;" onclick="resetFactionForm()">ANNULER</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead><tr><th>Visuel</th><th>Nom</th><th>Actions</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach ($factions_list as $f): ?>
|
||||
<tr>
|
||||
<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"></i>
|
||||
<?php else: ?>
|
||||
<i class="fa-solid fa-flag fa-lg" style="color: #4c566a;"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><strong><?php echo htmlspecialchars($f['name']); ?></strong></td>
|
||||
<td>
|
||||
<button class="btn btn-edit" onclick='editFaction(<?php echo json_encode($f, JSON_HEX_APOS); ?>)'>Editer</button>
|
||||
<?php if ($f['name'] !== 'Aucune'): ?>
|
||||
<a href="?tab=factions&delete_faction=<?php echo $f['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cette faction ?')">Suppr</a>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
@ -544,6 +663,14 @@ if ($tab === 'users') {
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetModifierForm() { document.getElementById('modifierForm').reset(); document.getElementById('mod_id').value = 0; }
|
||||
|
||||
function editFaction(data) {
|
||||
document.getElementById('fac_id').value = data.id;
|
||||
document.getElementById('fac_name').value = data.name;
|
||||
document.getElementById('fac_fa_icon').value = data.fa_icon || '';
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetFactionForm() { document.getElementById('factionForm').reset(); document.getElementById('fac_id').value = 0; }
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
BIN
assets/images/celestial/black_hole_1771735023.png
Normal file
BIN
assets/images/celestial/black_hole_1771735023.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
BIN
assets/images/celestial/planet_desert_01_1771755173.png
Normal file
BIN
assets/images/celestial/planet_desert_01_1771755173.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
BIN
assets/images/celestial/planet_volcanic_02_1771733154.png
Normal file
BIN
assets/images/celestial/planet_volcanic_02_1771733154.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
BIN
assets/images/celestial/planet_volcanic_1771732666.png
Normal file
BIN
assets/images/celestial/planet_volcanic_1771732666.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
BIN
assets/images/celestial/star_1771754685.png
Normal file
BIN
assets/images/celestial/star_1771754685.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
assets/pasted-20260222-040104-75ec63e6.png
Normal file
BIN
assets/pasted-20260222-040104-75ec63e6.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
16
db/add_fa_icon_to_factions.php
Normal file
16
db/add_fa_icon_to_factions.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
$db = db();
|
||||
|
||||
try {
|
||||
$cols = $db->query("DESCRIBE factions")->fetchAll(PDO::FETCH_COLUMN);
|
||||
if (!in_array('fa_icon', $cols)) {
|
||||
$db->exec("ALTER TABLE factions ADD COLUMN fa_icon VARCHAR(50) NULL AFTER image_url");
|
||||
echo "Column 'fa_icon' added to 'factions' table.\n";
|
||||
} else {
|
||||
echo "Column 'fa_icon' already exists in 'factions' table.\n";
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
die("Migration failed: " . $e->getMessage());
|
||||
}
|
||||
|
||||
35
db/migrate_factions.php
Normal file
35
db/migrate_factions.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
$db = db();
|
||||
|
||||
try {
|
||||
// Create factions table
|
||||
$db->exec("CREATE TABLE IF NOT EXISTS factions (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
image_url VARCHAR(255) NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)");
|
||||
echo "Table 'factions' created or already exists.\n";
|
||||
|
||||
// Add faction_id to planets table
|
||||
$cols = $db->query("DESCRIBE planets")->fetchAll(PDO::FETCH_COLUMN);
|
||||
if (!in_array('faction_id', $cols)) {
|
||||
$db->exec("ALTER TABLE planets ADD COLUMN faction_id INT DEFAULT NULL AFTER status");
|
||||
echo "Column 'faction_id' added to 'planets' table.\n";
|
||||
} else {
|
||||
echo "Column 'faction_id' already exists in 'planets' table.\n";
|
||||
}
|
||||
|
||||
// Check if 'Aucune' faction exists
|
||||
$stmt = $db->prepare("SELECT COUNT(*) FROM factions WHERE name = 'Aucune'");
|
||||
$stmt->execute();
|
||||
if ($stmt->fetchColumn() == 0) {
|
||||
$db->exec("INSERT INTO factions (name) VALUES ('Aucune')");
|
||||
echo "Default faction 'Aucune' created.\n";
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Migration failed: " . $e->getMessage());
|
||||
}
|
||||
|
||||
281
gm_console.php
281
gm_console.php
@ -20,13 +20,15 @@ if (!$current_user || ($current_user['role'] !== 'admin' && $current_user['role'
|
||||
|
||||
$is_admin = ($current_user['role'] === 'admin');
|
||||
|
||||
// Fetch Dynamic Types, Statuses, and Settlement Types - Sorted Alphabetically
|
||||
// Fetch Dynamic Types, Statuses, Settlement Types, and Factions
|
||||
$object_types_db = $db->query("SELECT * FROM celestial_object_types ORDER BY name ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$statuses_db = $db->query("SELECT * FROM celestial_object_statuses ORDER BY name ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$settlement_types_db = $db->query("SELECT * FROM settlement_types ORDER BY name ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$factions_db = $db->query("SELECT * FROM factions ORDER BY name ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$object_types_map = []; foreach($object_types_db as $ot) $object_types_map[$ot['slug']] = $ot;
|
||||
$statuses_map = []; foreach($statuses_db as $s) $statuses_map[$s['slug']] = $s;
|
||||
$factions_map = []; foreach($factions_db as $f) $factions_map[$f['id']] = $f;
|
||||
|
||||
// Handle Planet/Slot Update
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_slot') {
|
||||
@ -37,6 +39,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
$name = $_POST['name'];
|
||||
$type = $_POST['type'];
|
||||
$status = $_POST['status'];
|
||||
$faction_id = (int)$_POST['faction_id'];
|
||||
$orbital = (int)$_POST['orbital_control'];
|
||||
$terrestrial = (int)$_POST['terrestrial_control'];
|
||||
|
||||
@ -47,12 +50,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
}
|
||||
} else {
|
||||
if ($slot_id > 0) {
|
||||
$stmt = $db->prepare("UPDATE planets SET name = ?, type = ?, status = ?, orbital_control = ?, terrestrial_control = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $type, $status, $orbital, $terrestrial, $slot_id]);
|
||||
$stmt = $db->prepare("UPDATE planets SET name = ?, type = ?, status = ?, faction_id = ?, orbital_control = ?, terrestrial_control = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $type, $status, $faction_id, $orbital, $terrestrial, $slot_id]);
|
||||
$planet_id = $slot_id;
|
||||
} else {
|
||||
$stmt = $db->prepare("INSERT INTO planets (galaxy_id, sector_id, slot, name, type, status, orbital_control, terrestrial_control) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$galaxy_id, $sector_id, $slot_num, $name, $type, $status, $orbital, $terrestrial]);
|
||||
$stmt = $db->prepare("INSERT INTO planets (galaxy_id, sector_id, slot, name, type, status, faction_id, orbital_control, terrestrial_control) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$galaxy_id, $sector_id, $slot_num, $name, $type, $status, $faction_id, $orbital, $terrestrial]);
|
||||
$planet_id = $db->lastInsertId();
|
||||
}
|
||||
|
||||
@ -72,7 +75,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
$sent_city_ids[] = $c_id;
|
||||
} else {
|
||||
$stmt = $db->prepare("INSERT INTO cities (planet_id, name, settlement_type_id) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$planet_id, $c_name, $c_type_id]);
|
||||
$stmt->execute([$c_name, $c_type_id]);
|
||||
$sent_city_ids[] = $db->lastInsertId();
|
||||
}
|
||||
}
|
||||
@ -100,13 +103,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
$s_name = $_POST['sector_name'];
|
||||
$s_status = $_POST['sector_status'];
|
||||
|
||||
$stmt = $db->prepare("SELECT id FROM sectors WHERE id = ?");
|
||||
$stmt->execute([$sector_id]);
|
||||
if ($stmt->fetch()) {
|
||||
$db->prepare("UPDATE sectors SET name = ?, status = ? WHERE id = ?")->execute([$s_name, $s_status, $sector_id]);
|
||||
} else {
|
||||
$db->prepare("INSERT INTO sectors (id, name, status, galaxy_id) VALUES (?, ?, ?, ?)")->execute([$s_name, $s_status, $sector_id, $galaxy_id]);
|
||||
}
|
||||
$stmt = $db->prepare("INSERT INTO sectors (id, galaxy_id, name, status) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE name = ?, status = ?");
|
||||
$stmt->execute([$sector_id, $galaxy_id, $s_name, $s_status, $s_name, $s_status]);
|
||||
|
||||
header("Location: gm_console.php?view=sector&galaxy_id=$galaxy_id§or_id=$sector_id&success=1");
|
||||
exit;
|
||||
}
|
||||
@ -117,20 +116,18 @@ $sector_id = isset($_GET['sector_id']) ? (int)$_GET['sector_id'] : 1;
|
||||
$grid_size = 36;
|
||||
|
||||
if ($view === 'sector') {
|
||||
// Fetch planets
|
||||
$stmt = $db->prepare("SELECT * FROM planets WHERE galaxy_id = ? AND sector_id = ? AND slot BETWEEN 1 AND ?");
|
||||
$stmt->execute([$galaxy_id, $sector_id, $grid_size]);
|
||||
$objects_raw = $stmt->fetchAll();
|
||||
|
||||
$grid = array_fill(1, $grid_size, null);
|
||||
$planet_ids = [];
|
||||
foreach ($objects_raw as $obj) {
|
||||
$grid[$obj['slot']] = $obj;
|
||||
foreach ($objects_raw as $obj) {
|
||||
$grid[$obj['slot']] = $obj;
|
||||
$planet_ids[] = $obj['id'];
|
||||
$grid[$obj['slot']]['cities'] = [];
|
||||
}
|
||||
|
||||
// Fetch ALL cities for these planets
|
||||
if (!empty($planet_ids)) {
|
||||
$placeholders = implode(',', array_fill(0, count($planet_ids), '?'));
|
||||
$stmt = $db->prepare("SELECT * FROM cities WHERE planet_id IN ($placeholders)");
|
||||
@ -144,26 +141,24 @@ if ($view === 'sector') {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT * FROM sectors WHERE id = ?");
|
||||
$stmt = $db->prepare("SELECT name FROM sectors WHERE id = ?");
|
||||
$stmt->execute([$sector_id]);
|
||||
$sector_info = $stmt->fetch();
|
||||
} elseif ($view === 'galaxy') {
|
||||
} else {
|
||||
$stmt = $db->prepare("SELECT sector_id, slot, status, type FROM planets WHERE galaxy_id = ? ORDER BY sector_id, slot ASC");
|
||||
$stmt->execute([$galaxy_id]);
|
||||
$all_planets = $stmt->fetchAll();
|
||||
$sector_data = [];
|
||||
$active_sectors = [];
|
||||
foreach ($all_planets as $p) {
|
||||
$sector_data[$p['sector_id']][$p['slot']] = ['status' => $p['status'], 'type' => $p['type']];
|
||||
if (!in_array($p['sector_id'], $active_sectors)) { $active_sectors[] = (int)$p['sector_id']; }
|
||||
}
|
||||
$stmt = $db->prepare("SELECT id, status FROM sectors WHERE galaxy_id = ?");
|
||||
$stmt->execute([$galaxy_id]);
|
||||
$global_sector_statuses = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
|
||||
}
|
||||
|
||||
function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
if (isset($statuses_map[$status])) return $statuses_map[$status]['color'];
|
||||
return 'rgba(255,255,255,0.05)';
|
||||
if ($type === 'empty') return 'rgba(255,255,255,0.05)';
|
||||
return $statuses_map[$status]['color'] ?? 'rgba(255,255,255,0.05)';
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
@ -174,73 +169,130 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
<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; }
|
||||
body { background: #0b0f19; 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: 20px; display: flex; flex-direction: column; align-items: center; }
|
||||
.container { padding: 40px; display: flex; flex-direction: column; align-items: center; }
|
||||
|
||||
.galaxy-map { background: rgba(0,0,0,0.9); border: 2px solid #2d3545; display: grid; grid-template-columns: repeat(6, 120px); grid-template-rows: repeat(6, 100px); gap: 1px; }
|
||||
.slot { background: #050505; border: 1px solid #1a1a1a; display: flex; flex-direction: column; align-items: center; justify-content: center; position: relative; cursor: pointer; transition: all 0.2s; }
|
||||
.slot:hover { background: #1a2a4a; border-color: #88c0d0; transform: scale(1.05); z-index: 10; }
|
||||
.slot-id { position: absolute; top: 2px; left: 5px; font-size: 9px; color: #444; }
|
||||
.object-icon { font-size: 24px; margin-bottom: 5px; }
|
||||
.object-name { font-size: 10px; font-weight: bold; color: #3b82f6; text-align: center; max-width: 90%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
|
||||
.sector-grid { display: grid; grid-template-columns: repeat(6, 160px); grid-template-rows: repeat(6, 130px); gap: 10px; }
|
||||
.sector-card { background: rgba(10,15,30,0.9); border: 1px solid #3b4252; display: flex; flex-direction: column; align-items: center; justify-content: center; cursor: pointer; text-decoration: none; color: #fff; padding: 10px; position: relative; transition: all 0.2s; }
|
||||
.sector-card:hover { border-color: #88c0d0; background: #1a2a4a; }
|
||||
.mini-map { display: grid; grid-template-columns: repeat(6, 8px); gap: 2px; background: #000; padding: 5px; border: 1px solid #4c566a; }
|
||||
.mini-dot { width: 8px; height: 8px; background: rgba(255,255,255,0.05); }
|
||||
.sector-status-label { position: absolute; top: 5px; right: 5px; font-size: 8px; padding: 2px 5px; border-radius: 3px; background: rgba(0,0,0,0.5); }
|
||||
|
||||
#editModal, #sectorModal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 1000; justify-content: center; align-items: center; }
|
||||
.modal-content { background: #1e293b; padding: 25px; border: 2px solid #88c0d0; width: 550px; box-shadow: 0 0 50px rgba(136, 192, 208, 0.2); max-height: 90vh; overflow-y: auto; border-radius: 8px; }
|
||||
.modal-content h3 { margin-top: 0; color: #88c0d0; font-size: 18px; border-bottom: 1px solid #334155; padding-bottom: 10px; margin-bottom: 20px; }
|
||||
.form-group { margin-bottom: 15px; }
|
||||
.form-group label { display: block; font-size: 11px; color: #8c92a3; margin-bottom: 5px; text-transform: uppercase; letter-spacing: 0.5px; }
|
||||
.form-group input, .form-group select { width: 100%; background: #0f172a; border: 1px solid #334155; color: #fff; padding: 8px 12px; box-sizing: border-box; border-radius: 4px; font-size: 13px; }
|
||||
.form-group input:focus, .form-group select:focus { border-color: #88c0d0; outline: none; }
|
||||
.galaxy-map {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 140px);
|
||||
grid-template-rows: repeat(6, 140px);
|
||||
gap: 10px;
|
||||
padding: 15px;
|
||||
background: rgba(10, 15, 30, 0.5);
|
||||
border: 1px solid #2d3545;
|
||||
}
|
||||
.slot {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
background: rgba(46, 52, 64, 0.3);
|
||||
border: 1px solid #3b4252;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
overflow: hidden;
|
||||
}
|
||||
.slot:hover { background: rgba(136, 192, 208, 0.1); border-color: #88c0d0; }
|
||||
.slot-id { position: absolute; top: 5px; left: 8px; font-size: 9px; color: #4c566a; font-weight: bold; z-index: 5; }
|
||||
|
||||
.btn-save { background: #a3be8c; color: #000; border: none; padding: 12px 20px; font-weight: bold; cursor: pointer; width: 100%; font-size: 14px; margin-top: 10px; border-radius: 4px; text-transform: uppercase; }
|
||||
.btn-cancel { background: #4c566a; color: #fff; border: none; padding: 10px 20px; font-weight: bold; cursor: pointer; width: 100%; margin-top: 10px; border-radius: 4px; font-size: 12px; }
|
||||
|
||||
.settlement-item { background: rgba(15, 23, 42, 0.5); padding: 12px; border: 1px solid #334155; margin-bottom: 10px; position: relative; border-radius: 6px; }
|
||||
.btn-remove-settlement { position: absolute; top: -8px; right: -8px; background: #bf616a; color: #fff; border: none; width: 20px; height: 20px; border-radius: 50%; cursor: pointer; font-size: 10px; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 4px rgba(0,0,0,0.3); }
|
||||
.btn-add-settlement { background: transparent; color: #88c0d0; border: 1px dashed #88c0d0; padding: 8px 15px; font-weight: bold; cursor: pointer; font-size: 11px; margin-bottom: 20px; width: 100%; border-radius: 4px; transition: all 0.2s; }
|
||||
.btn-add-settlement:hover { background: rgba(136, 192, 208, 0.1); }
|
||||
.object-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 1;
|
||||
font-size: 90px;
|
||||
z-index: 2;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.object-image { width: 90px; height: 90px; object-fit: contain; margin: 0; }
|
||||
.slot:hover .object-icon { transform: translate(-50%, -50%) scale(1.1); }
|
||||
|
||||
.compact-row { display: flex; gap: 12px; align-items: flex-end; }
|
||||
.compact-row .form-group { margin-bottom: 0; flex: 1; }
|
||||
.faction-icon {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 8px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
z-index: 6;
|
||||
filter: drop-shadow(0 0 2px rgba(0,0,0,0.8));
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.object-name {
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
color: #eceff4;
|
||||
text-align: center;
|
||||
width: 95%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
z-index: 3;
|
||||
text-shadow: 0 0 4px rgba(0,0,0,0.8);
|
||||
}
|
||||
|
||||
.sector-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 180px);
|
||||
grid-template-rows: repeat(6, 180px);
|
||||
gap: 15px;
|
||||
}
|
||||
.sector-card { background: rgba(10, 15, 30, 0.95); border: 1px solid #2d3545; padding: 20px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-decoration: none; color: #fff; transition: all 0.2s; width: 180px; height: 180px; box-sizing: border-box; }
|
||||
.sector-card:hover { border-color: #88c0d0; background: #1a202c; transform: translateY(-3px); }
|
||||
.mini-map { display: grid; grid-template-columns: repeat(6, 12px); gap: 4px; margin-bottom: 10px; background: #000; padding: 6px; }
|
||||
.mini-dot { width: 12px; height: 12px; border-radius: 1px; }
|
||||
|
||||
#editModal, #sectorModal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 1000; align-items: center; justify-content: center; }
|
||||
.modal-content { background: #1e293b; padding: 30px; border: 1px solid #88c0d0; width: 550px; max-height: 90vh; overflow-y: auto; border-radius: 8px; box-shadow: 0 10px 30px rgba(0,0,0,0.5); }
|
||||
.form-group { margin-bottom: 20px; }
|
||||
.form-group label { display: block; font-size: 12px; color: #8c92a3; margin-bottom: 8px; font-weight: bold; }
|
||||
.form-group input, .form-group select, .form-group textarea { width: 100%; background: #0f172a; border: 1px solid #334155; color: #fff; padding: 10px; box-sizing: border-box; border-radius: 4px; font-size: 14px; }
|
||||
|
||||
.btn-save { background: #a3be8c; border: none; padding: 12px 25px; color: #000; font-weight: bold; cursor: pointer; border-radius: 4px; font-size: 14px; width: 100%; }
|
||||
.btn-cancel { background: #4c566a; border: none; padding: 12px 25px; color: #fff; font-weight: bold; cursor: pointer; border-radius: 4px; font-size: 14px; width: 100%; margin-top: 10px; }
|
||||
|
||||
.settlement-item { background: #1e293b; border: 1px solid #334155; padding: 15px; margin-bottom: 10px; position: relative; border-radius: 6px; }
|
||||
.btn-remove-settlement { position: absolute; right: 8px; top: 8px; background: #bf616a; color: #fff; border: none; width: 22px; height: 22px; cursor: pointer; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; }
|
||||
.btn-add-settlement { background: #81a1c1; color: #000; border: none; padding: 8px 15px; cursor: pointer; font-size: 11px; font-weight: bold; border-radius: 4px; width: 100%; margin-bottom: 15px; transition: 0.2s; }
|
||||
.btn-add-settlement:hover { background: #88c0d0; }
|
||||
.compact-row { display: flex; gap: 15px; align-items: flex-end; }
|
||||
.compact-row .form-group { margin-bottom: 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div style="display: flex; align-items: center; gap: 20px;">
|
||||
<h2 style="margin: 0; color: #ebcb8b;"><i class="fa-solid fa-headset"></i> CONSOLE MJ</h2>
|
||||
<nav class="nav-links">
|
||||
<a href="?view=galaxy"><i class="fa-solid fa-braille"></i> Galaxie</a>
|
||||
<nav style="display: flex; gap: 20px;">
|
||||
<a href="index.php" style="color: #88c0d0; text-decoration: none; font-size: 14px; font-weight: bold;"><i class="fa-solid fa-eye"></i> Vue Joueur</a>
|
||||
<?php if ($is_admin): ?>
|
||||
<a href="admin.php" target="_blank"><i class="fa-solid fa-shield-halved"></i> Console Admin</a>
|
||||
<a href="admin.php" style="color: #bf616a; text-decoration: none; font-size: 14px; font-weight: bold;"><i class="fa-solid fa-shield-halved"></i> Console Admin</a>
|
||||
<?php endif; ?>
|
||||
<a href="index.php"><i class="fa-solid fa-eye"></i> Vue Joueur</a>
|
||||
</nav>
|
||||
</div>
|
||||
<div>
|
||||
<span style="color: #8c92a3; font-size: 12px;">Maître du Jeu: </span>
|
||||
<span style="font-weight: bold; color: #88c0d0;"><?php echo htmlspecialchars($_SESSION['username']); ?></span>
|
||||
</div>
|
||||
<div style="font-size: 14px;">Connecté en tant que MJ: <strong style="color: #ebcb8b;">@<?php echo htmlspecialchars($_SESSION['username']); ?></strong></div>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
<?php if ($view === 'galaxy'): ?>
|
||||
<h3 style="color: #88c0d0;">Sélecteur de Secteur</h3>
|
||||
<h3 style="color: #88c0d0; margin-bottom: 30px;">Navigateur de Galaxie</h3>
|
||||
<div class="sector-grid">
|
||||
<?php for($s=1; $s<=$grid_size; $s++):
|
||||
$sStatus = $global_sector_statuses[$s] ?? 'unexplored';
|
||||
?>
|
||||
<?php for($s=1; $s<=$grid_size; $s++): ?>
|
||||
<a href="?view=sector&galaxy_id=<?php echo $galaxy_id; ?>§or_id=<?php echo $s; ?>" class="sector-card">
|
||||
<span class="sector-status-label" style="background: <?php echo ($sStatus == 'stable' ? '#a3be8c' : ($sStatus == 'hostile' ? '#bf616a' : ($sStatus == 'war' ? '#ef4444' : '#4c566a'))); ?>; color: #000; font-weight: bold;"><?php echo strtoupper($sStatus); ?></span>
|
||||
<div class="mini-map">
|
||||
<?php for($p=1; $p<=$grid_size; $p++):
|
||||
$dotColor = 'rgba(255,255,255,0.05)';
|
||||
@ -255,7 +307,7 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
</div>
|
||||
|
||||
<?php elseif ($view === 'sector'): ?>
|
||||
<div style="display: flex; justify-content: space-between; width: 100%; max-width: 720px; align-items: center; margin-bottom: 20px;">
|
||||
<div style="display: flex; justify-content: space-between; width: 100%; max-width: 840px; align-items: center; margin-bottom: 20px;">
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<a href="?view=galaxy" style="color: #88c0d0; text-decoration: none;"><i class="fa-solid fa-arrow-left"></i> Retour</a>
|
||||
<h3 style="color: #88c0d0; margin: 0;">Secteur <?php echo $sector_id; ?>: <?php echo htmlspecialchars($sector_info['name'] ?? "Secteur $sector_id"); ?></h3>
|
||||
@ -267,13 +319,31 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
<?php for($i=1; $i<=$grid_size; $i++): ?>
|
||||
<div class="slot" onclick='editSlot(<?php echo $i; ?>, <?php echo json_encode($grid[$i] ?? null); ?>)'>
|
||||
<span class="slot-id"><?php echo $i; ?></span>
|
||||
<?php if (isset($grid[$i])): $obj = $grid[$i]; ?>
|
||||
<?php if (isset($grid[$i])): $obj = $grid[$i];
|
||||
$type_info = $object_types_map[$obj['type']] ?? null;
|
||||
$fac_info = isset($obj['faction_id']) ? ($factions_map[$obj['faction_id']] ?? null) : null;
|
||||
?>
|
||||
<div class="faction-icon">
|
||||
<?php if ($fac_info): ?>
|
||||
<?php if (!empty($fac_info['image_url'])): ?>
|
||||
<img src="<?php echo htmlspecialchars($fac_info['image_url']); ?>?v=<?php echo time(); ?>" style="width: 100%; height: 100%; object-fit: contain;" title="<?php echo htmlspecialchars($fac_info['name']); ?>">
|
||||
<?php elseif (!empty($fac_info['fa_icon'])): ?>
|
||||
<i class="fa-solid <?php echo htmlspecialchars($fac_info['fa_icon']); ?>" style="color: #fff; font-size: 16px;" title="<?php echo htmlspecialchars($fac_info['name']); ?>"></i>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="object-icon">
|
||||
<?php
|
||||
$icon = $object_types_map[$obj['type']]['icon'] ?? 'fa-circle';
|
||||
$icon = $type_info['icon'] ?? 'fa-circle';
|
||||
$color = getStatusColor($obj['status'], $obj['type'], $statuses_map, $object_types_map);
|
||||
$imageUrl = $type_info['image_url'] ?? null;
|
||||
?>
|
||||
<i class="fa-solid <?php echo $icon; ?>" style="color: <?php echo $color; ?>;"></i>
|
||||
<?php if ($imageUrl): ?>
|
||||
<img src="<?php echo htmlspecialchars($imageUrl); ?>?v=<?php echo time(); ?>" class="object-image">
|
||||
<?php else: ?>
|
||||
<i class="fa-solid <?php echo $icon; ?>" style="color: <?php echo $color; ?>;"></i>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<span class="object-name"><?php echo htmlspecialchars($obj['name']); ?></span>
|
||||
<?php else: ?>
|
||||
@ -306,19 +376,29 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
<select name="type" id="form_type">
|
||||
<option value="empty">VIDE (Suppr)</option>
|
||||
<?php foreach($object_types_db as $ot): ?>
|
||||
<option value="<?php echo $ot['slug']; ?>"><?php echo $ot['name']; ?></option>
|
||||
<option value="<?php echo $ot['slug']; ?>"><?php echo $ot['name']; ?> (<?php echo $ot['slug']; ?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Statut / État</label>
|
||||
<select name="status" id="form_status">
|
||||
<?php foreach($statuses_db as $st): ?>
|
||||
<option value="<?php echo $st['slug']; ?>"><?php echo $st['name']; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div style="display: flex; gap: 15px;">
|
||||
<div class="form-group" style="flex: 1;">
|
||||
<label>Statut / État</label>
|
||||
<select name="status" id="form_status">
|
||||
<?php foreach($statuses_db as $st): ?>
|
||||
<option value="<?php echo $st['slug']; ?>"><?php echo $st['name']; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" style="flex: 1;">
|
||||
<label>Faction</label>
|
||||
<select name="faction_id" id="form_faction">
|
||||
<?php foreach($factions_db as $fac): ?>
|
||||
<option value="<?php echo $fac['id']; ?>"><?php echo $fac['name']; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="background: rgba(0,0,0,0.1); padding: 15px; border-radius: 6px; border: 1px solid #334155; margin-bottom: 20px;">
|
||||
@ -400,48 +480,47 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
const sel = (data && data.settlement_type_id == t.id) ? 'selected' : '';
|
||||
html += `<option value="${t.id}" ${sel}>${t.name}</option>`;
|
||||
});
|
||||
html += `</select></div>`;
|
||||
html += `</div>`;
|
||||
html += `</select></div></div>`;
|
||||
|
||||
div.innerHTML = html;
|
||||
container.appendChild(div);
|
||||
}
|
||||
|
||||
function editSlot(num, data) {
|
||||
document.getElementById('modalTitle').innerText = 'Modifier la case n°' + num;
|
||||
document.getElementById('form_slot_num').value = num;
|
||||
document.getElementById('settlementsContainer').innerHTML = '';
|
||||
settlementIndex = 0;
|
||||
|
||||
document.getElementById('form_slot_id').value = data ? data.id : 0;
|
||||
document.getElementById('modalTitle').innerText = 'Éditer Case #' + num;
|
||||
|
||||
if (data) {
|
||||
document.getElementById('form_slot_id').value = data.id;
|
||||
document.getElementById('form_name').value = data.name;
|
||||
document.getElementById('form_type').value = data.type;
|
||||
document.getElementById('form_status').value = data.status;
|
||||
document.getElementById('form_faction').value = data.faction_id || 0;
|
||||
document.getElementById('form_orbital').value = data.orbital_control;
|
||||
document.getElementById('form_terrestrial').value = data.terrestrial_control;
|
||||
|
||||
// Load settlements
|
||||
document.getElementById('settlementsContainer').innerHTML = '';
|
||||
settlementIndex = 0;
|
||||
if (data.cities && data.cities.length > 0) {
|
||||
data.cities.forEach(c => addSettlementRow(c));
|
||||
}
|
||||
} else {
|
||||
document.getElementById('form_slot_id').value = 0;
|
||||
document.getElementById('form_name').value = 'Objet ' + num;
|
||||
document.getElementById('form_type').value = 'planet';
|
||||
document.getElementById('form_status').value = 'empty';
|
||||
document.getElementById('form_name').value = '';
|
||||
document.getElementById('form_type').value = 'empty';
|
||||
document.getElementById('form_status').value = 'neutral';
|
||||
document.getElementById('form_faction').value = document.querySelector('#form_faction option').value;
|
||||
document.getElementById('form_orbital').value = 0;
|
||||
document.getElementById('form_terrestrial').value = 0;
|
||||
document.getElementById('settlementsContainer').innerHTML = '';
|
||||
}
|
||||
|
||||
document.getElementById('editModal').style.display = 'flex';
|
||||
}
|
||||
|
||||
function closeModal() { document.getElementById('editModal').style.display = 'none'; }
|
||||
function editSector() { document.getElementById('sectorModal').style.display = 'flex'; }
|
||||
function closeSectorModal() { document.getElementById('sectorModal').style.display = 'none'; }
|
||||
|
||||
window.onclick = function(event) {
|
||||
if (event.target == document.getElementById('editModal')) closeModal();
|
||||
if (event.target == document.getElementById('sectorModal')) closeSectorModal();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
210
index.php
210
index.php
@ -15,9 +15,10 @@ $view = isset($_GET['view']) ? $_GET['view'] : 'sector';
|
||||
$galaxy_id = isset($_GET['galaxy_id']) ? (int)$_GET['galaxy_id'] : 1;
|
||||
$sector_id = isset($_GET['sector_id']) ? (int)$_GET['sector_id'] : 1;
|
||||
|
||||
// Fetch Dynamic Types and Statuses
|
||||
// Fetch Dynamic Types, Statuses and Factions
|
||||
$object_types_db = $db->query("SELECT * FROM celestial_object_types")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$statuses_db = $db->query("SELECT * FROM celestial_object_statuses")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$factions_db = $db->query("SELECT * FROM factions")->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$object_types_map = [];
|
||||
foreach($object_types_db as $ot) {
|
||||
@ -29,6 +30,7 @@ foreach($object_types_db as $ot) {
|
||||
}
|
||||
|
||||
$statuses_map = []; foreach($statuses_db as $s) $statuses_map[$s['slug']] = $s;
|
||||
$factions_map = []; foreach($factions_db as $f) $factions_map[$f['id']] = $f;
|
||||
|
||||
// Grid size: 6x6 = 36 slots per sector
|
||||
$grid_size = 36;
|
||||
@ -98,56 +100,148 @@ function getStatusColor($status, $statuses_map) {
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?php echo $page_title; ?></title>
|
||||
<title>Nexus - <?php echo $page_title; ?></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; margin: 0; padding: 0; font-family: Arial, sans-serif; color: #fff; background-image: radial-gradient(circle at 50% 50%, #1a2a4a 0%, #000 70%); background-attachment: fixed; }
|
||||
#main-wrapper { display: flex; flex-direction: column; min-height: 100vh; background: rgba(0, 0, 0, 0.4); }
|
||||
header#top-bar { padding: 10px; background: rgba(10, 15, 30, 0.95); border-bottom: 2px solid #2d3545; display: flex; flex-direction: column; align-items: center; gap: 10px; }
|
||||
.resource-container { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
|
||||
.user-auth-bar { width: 100%; display: flex; justify-content: flex-end; padding: 0 20px; box-sizing: border-box; font-size: 12px; margin-bottom: 5px; }
|
||||
.user-auth-bar a { color: #88c0d0; text-decoration: none; margin-left: 15px; display: flex; align-items: center; gap: 5px; }
|
||||
.user-auth-bar a:hover { text-decoration: underline; color: #fff; }
|
||||
.user-auth-bar .username { color: #ebcb8b; font-weight: bold; }
|
||||
.resource-box { background: #0a0a0a; border: 1px solid #3b4252; padding: 5px 15px; text-align: left; min-width: 140px; position: relative; }
|
||||
.resource-box i { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); opacity: 0.3; font-size: 20px; }
|
||||
.resource-name { font-size: 10px; color: #8c92a3; text-transform: uppercase; }
|
||||
.resource-value { font-size: 13px; font-weight: bold; color: #fff; }
|
||||
.resource-prod { font-size: 10px; color: #22c55e; }
|
||||
#game-container { flex-grow: 1; padding: 20px; display: flex; flex-direction: column; align-items: center; }
|
||||
.nav-panel { background: rgba(20, 30, 50, 0.95); border: 1px solid #4c566a; padding: 15px; width: 200px; margin-bottom: 20px; box-shadow: 0 0 15px rgba(0,0,0,0.5); }
|
||||
.nav-panel h3 { margin: 0 0 10px 0; font-size: 14px; text-transform: uppercase; color: #88c0d0; border-bottom: 1px solid #4c566a; padding-bottom: 5px; }
|
||||
.nav-panel div { margin-bottom: 8px; font-size: 12px; }
|
||||
.nav-panel label { display: inline-block; width: 60px; color: #8c92a3; }
|
||||
.nav-panel input { width: 60px; background: #000; border: 1px solid #4c566a; color: #fff; padding: 2px 5px; text-align: center; }
|
||||
.nav-panel button { width: 100%; background: #4c566a; border: none; color: #fff; padding: 5px; margin-top: 10px; cursor: pointer; text-transform: uppercase; font-weight: bold; }
|
||||
.nav-panel button:hover { background: #5e81ac; }
|
||||
.galaxy-map { background: rgba(0, 0, 0, 0.9); border: 2px solid #2d3545; padding: 1px; display: grid; grid-template-columns: repeat(6, 120px); grid-template-rows: repeat(6, 100px); gap: 1px; position: relative; }
|
||||
.sector-grid { display: grid; grid-template-columns: repeat(6, 160px); grid-template-rows: repeat(6, 130px); gap: 10px; }
|
||||
.sector-card { background: rgba(10, 15, 30, 0.9); border: 1px solid #3b4252; display: flex; flex-direction: column; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s; text-decoration: none; color: #fff; padding: 10px; position: relative; }
|
||||
.sector-card:hover { border-color: #88c0d0; background: rgba(20, 30, 50, 0.95); transform: translateY(-2px); box-shadow: 0 0 15px rgba(136, 192, 208, 0.2); }
|
||||
.sector-card.empty { opacity: 0.7; }
|
||||
.mini-map { display: grid; grid-template-columns: repeat(6, 8px); gap: 2px; margin-bottom: 12px; background: rgba(0,0,0,0.7); padding: 5px; border: 1px solid #4c566a; }
|
||||
.mini-dot { width: 8px; height: 8px; background: rgba(255,255,255,0.05); }
|
||||
.slot { background: #050505; border: 1px solid #1a1a1a; display: flex; flex-direction: column; align-items: center; justify-content: center; position: relative; cursor: pointer; transition: all 0.2s; }
|
||||
.slot:hover { background: #111; border-color: #3b82f6; z-index: 100; }
|
||||
.slot-id { position: absolute; top: 2px; left: 5px; font-size: 9px; color: #444; }
|
||||
.object-icon { font-size: 24px; margin-bottom: 5px; }
|
||||
.object-name { font-size: 10px; font-weight: bold; color: #3b82f6; text-align: center; }
|
||||
.object-status { font-size: 9px; color: #8c92a3; }
|
||||
.city-label { font-size: 8px; color: #ebcb8b; margin-top: 2px; display: block; width: 90%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
body { background: #000; color: #fff; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; }
|
||||
#main-wrapper { display: flex; flex-direction: column; min-height: 100vh; }
|
||||
header#top-bar { background: rgba(10, 15, 30, 0.95); border-bottom: 2px solid #2d3545; padding: 10px 40px; }
|
||||
.user-auth-bar { display: flex; justify-content: flex-end; gap: 20px; font-size: 11px; color: #8c92a3; margin-bottom: 10px; }
|
||||
.user-auth-bar a { color: #88c0d0; text-decoration: none; font-weight: bold; }
|
||||
.user-auth-bar .username { color: #ebcb8b; }
|
||||
|
||||
/* Tooltip Styles */
|
||||
.tooltip-box { display: none; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); background: #1e293b; border: 1px solid #3b82f6; padding: 10px; width: 180px; z-index: 1000; box-shadow: 0 10px 25px rgba(0,0,0,0.8); pointer-events: none; }
|
||||
.resource-container { display: flex; gap: 25px; align-items: center; justify-content: center; }
|
||||
.resource-box { display: flex; flex-direction: column; align-items: center; position: relative; min-width: 80px; }
|
||||
.resource-box i { position: absolute; right: -15px; top: 5px; font-size: 20px; color: rgba(136, 192, 208, 0.2); }
|
||||
.resource-name { font-size: 10px; color: #88c0d0; text-transform: uppercase; font-weight: bold; }
|
||||
.resource-value { font-size: 14px; font-weight: bold; color: #fff; }
|
||||
.resource-prod { font-size: 9px; color: #a3be8c; }
|
||||
|
||||
#game-container { flex: 1; padding: 30px; display: flex; flex-direction: column; align-items: center; }
|
||||
.nav-panel { background: rgba(10, 15, 30, 0.95); border: 1px solid #2d3545; padding: 20px; width: 180px; }
|
||||
.nav-panel h3 { margin: 0 0 15px 0; color: #88c0d0; font-size: 14px; text-transform: uppercase; border-bottom: 1px solid #2d3545; padding-bottom: 10px; }
|
||||
.nav-panel label { display: block; font-size: 10px; color: #8c92a3; margin-top: 10px; }
|
||||
.nav-panel input { width: 100%; background: #000; border: 1px solid #3b4252; color: #fff; padding: 5px; margin-top: 3px; font-size: 12px; }
|
||||
.nav-panel button { width: 100%; margin-top: 15px; background: #88c0d0; border: none; padding: 8px; color: #000; font-weight: bold; cursor: pointer; border-radius: 2px; }
|
||||
|
||||
.galaxy-map {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 140px);
|
||||
grid-template-rows: repeat(6, 140px);
|
||||
gap: 10px;
|
||||
padding: 15px;
|
||||
background: rgba(10, 15, 30, 0.5);
|
||||
border: 1px solid #2d3545;
|
||||
box-shadow: 0 0 30px rgba(0,0,0,0.5);
|
||||
}
|
||||
.slot {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
background: rgba(46, 52, 64, 0.3);
|
||||
border: 1px solid #3b4252;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
overflow: hidden;
|
||||
}
|
||||
.slot:hover { background: rgba(136, 192, 208, 0.1); border-color: #88c0d0; z-index: 10; }
|
||||
.slot-id { position: absolute; top: 5px; left: 8px; font-size: 9px; color: #4c566a; font-weight: bold; z-index: 5; }
|
||||
|
||||
.faction-icon {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 8px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
z-index: 6;
|
||||
filter: drop-shadow(0 0 2px rgba(0,0,0,0.8));
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.object-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
line-height: 1;
|
||||
font-size: 90px;
|
||||
z-index: 2;
|
||||
}
|
||||
.object-image { width: 90px; height: 90px; object-fit: contain; margin: 0; }
|
||||
.slot:hover .object-icon { transform: translate(-50%, -50%) scale(1.1); }
|
||||
|
||||
.object-name {
|
||||
position: absolute;
|
||||
bottom: 24px;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
color: #eceff4;
|
||||
text-align: center;
|
||||
width: 95%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
z-index: 3;
|
||||
text-shadow: 0 0 4px rgba(0,0,0,0.8);
|
||||
}
|
||||
.object-status {
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
font-size: 8px;
|
||||
color: #88c0d0;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
z-index: 3;
|
||||
text-shadow: 0 0 4px rgba(0,0,0,0.8);
|
||||
}
|
||||
.city-label {
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
font-size: 8px;
|
||||
color: #ebcb8b;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
z-index: 3;
|
||||
text-shadow: 0 0 4px rgba(0,0,0,0.8);
|
||||
}
|
||||
|
||||
.sector-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 180px);
|
||||
grid-template-rows: repeat(6, 180px);
|
||||
gap: 15px;
|
||||
}
|
||||
.sector-card { background: rgba(10, 15, 30, 0.95); border: 1px solid #2d3545; padding: 20px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-decoration: none; color: #fff; transition: all 0.2s; position: relative; width: 180px; height: 180px; box-sizing: border-box; }
|
||||
.sector-card:hover { border-color: #88c0d0; background: #1a202c; transform: translateY(-3px); }
|
||||
.sector-card.empty { opacity: 0.6; }
|
||||
|
||||
.mini-map { display: grid; grid-template-columns: repeat(6, 12px); gap: 4px; margin-bottom: 15px; background: #000; padding: 6px; border-radius: 2px; }
|
||||
.mini-dot { width: 12px; height: 12px; border-radius: 1px; }
|
||||
|
||||
.tooltip-box { display: none; position: absolute; top: -10px; left: 105%; width: 220px; background: #1e293b; border: 1px solid #88c0d0; padding: 15px; z-index: 100; pointer-events: none; box-shadow: 10px 10px 20px rgba(0,0,0,0.5); }
|
||||
.slot:hover .tooltip-box { display: block; }
|
||||
.tooltip-title { font-size: 12px; font-weight: bold; color: #88c0d0; border-bottom: 1px solid #334155; margin-bottom: 5px; padding-bottom: 3px; }
|
||||
.tooltip-desc { font-size: 10px; color: #8c92a3; margin-bottom: 8px; line-height: 1.3; }
|
||||
.mod-list { display: flex; flex-direction: column; gap: 3px; margin-top: 8px; }
|
||||
.mod-item { font-size: 9px; padding: 2px 5px; border-radius: 2px; display: flex; align-items: center; gap: 4px; }
|
||||
.mod-bonus { background: rgba(163, 190, 140, 0.2); color: #a3be8c; border: 1px solid rgba(163, 190, 140, 0.4); }
|
||||
.mod-malus { background: rgba(191, 97, 106, 0.2); color: #bf616a; border: 1px solid rgba(191, 97, 106, 0.4); }
|
||||
.tooltip-title { font-size: 14px; color: #88c0d0; font-weight: bold; border-bottom: 1px solid #334155; padding-bottom: 8px; margin-bottom: 8px; }
|
||||
.tooltip-desc { font-size: 11px; color: #d8dee9; line-height: 1.4; font-style: italic; margin-bottom: 10px; }
|
||||
.mod-list { display: flex; flex-direction: column; gap: 5px; }
|
||||
.mod-item { font-size: 10px; padding: 4px 8px; border-radius: 3px; display: flex; align-items: center; gap: 8px; }
|
||||
.mod-bonus { background: rgba(163, 190, 140, 0.15); color: #a3be8c; border: 1px solid rgba(163, 190, 140, 0.3); }
|
||||
.mod-malus { background: rgba(191, 97, 106, 0.15); color: #bf616a; border: 1px solid rgba(191, 97, 106, 0.3); }
|
||||
.mod-item i { font-size: 12px; }
|
||||
|
||||
.settlement-title { font-size: 10px; color: #ebcb8b; font-weight: bold; border-top: 1px solid #334155; margin-top: 8px; padding-top: 5px; }
|
||||
.settlement-item-tool { font-size: 9px; color: #fff; margin-bottom: 3px; }
|
||||
@ -195,7 +289,7 @@ function getStatusColor($status, $statuses_map) {
|
||||
<?php if($view === 'sector'): ?> > <?php echo htmlspecialchars($sector_display_name); ?> <?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 40px; align-items: flex-start; width: 100%; max-width: 1100px; justify-content: center;">
|
||||
<div style="display: flex; gap: 40px; align-items: flex-start; width: 100%; max-width: 1200px; justify-content: center;">
|
||||
<div class="nav-panel">
|
||||
<h3>Univers</h3>
|
||||
<form method="GET"><input type="hidden" name="view" value="<?php echo $view; ?>">
|
||||
@ -213,9 +307,13 @@ function getStatusColor($status, $statuses_map) {
|
||||
<span class="slot-id"><?php echo $i; ?></span>
|
||||
<?php if (isset($grid[$i])): $obj = $grid[$i];
|
||||
$type_info = $object_types_map[$obj['type']] ?? null;
|
||||
$fac_info = isset($obj['faction_id']) ? ($factions_map[$obj['faction_id']] ?? null) : null;
|
||||
?>
|
||||
<div class="tooltip-box">
|
||||
<div class="tooltip-title"><?php echo htmlspecialchars($obj['name']); ?></div>
|
||||
<?php if ($fac_info && $fac_info['name'] !== 'Aucune'): ?>
|
||||
<div style="font-size: 10px; color: #ebcb8b; margin-bottom: 5px;"><i class="fa-solid fa-flag"></i> Faction: <?php echo htmlspecialchars($fac_info['name']); ?></div>
|
||||
<?php endif; ?>
|
||||
<div class="tooltip-desc"><?php echo htmlspecialchars($type_info['description'] ?? ''); ?></div>
|
||||
|
||||
<?php if (!empty($obj['cities'])): ?>
|
||||
@ -239,12 +337,28 @@ function getStatusColor($status, $statuses_map) {
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="faction-icon">
|
||||
<?php if ($fac_info): ?>
|
||||
<?php if (!empty($fac_info['image_url'])): ?>
|
||||
<img src="<?php echo htmlspecialchars($fac_info['image_url']); ?>?v=<?php echo time(); ?>" style="width: 100%; height: 100%; object-fit: contain;" title="<?php echo htmlspecialchars($fac_info['name']); ?>">
|
||||
<?php elseif (!empty($fac_info['fa_icon'])): ?>
|
||||
<i class="fa-solid <?php echo htmlspecialchars($fac_info['fa_icon']); ?>" style="color: #fff; font-size: 16px;" title="<?php echo htmlspecialchars($fac_info['name']); ?>"></i>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="object-icon">
|
||||
<?php
|
||||
$icon = $type_info['icon'] ?? 'fa-earth-europe';
|
||||
$color = getStatusColor($obj['status'], $statuses_map);
|
||||
$imageUrl = $type_info['image_url'] ?? null;
|
||||
?>
|
||||
<i class="fa-solid <?php echo $icon; ?>" style="color: <?php echo $color; ?>;"></i>
|
||||
<?php if ($imageUrl): ?>
|
||||
<img src="<?php echo htmlspecialchars($imageUrl); ?>?v=<?php echo time(); ?>" class="object-image">
|
||||
<?php else: ?>
|
||||
<i class="fa-solid <?php echo $icon; ?>" style="color: <?php echo $color; ?>;"></i>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<span class="object-name"><?php echo htmlspecialchars($obj['name']); ?></span>
|
||||
<span class="object-status"><?php echo $statuses_map[$obj['status']]['name'] ?? ucfirst($obj['status']); ?></span>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user