Autosave: 20260222-033720
This commit is contained in:
parent
430868a6e8
commit
4d1b2d5499
217
admin.php
217
admin.php
@ -41,6 +41,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
$slug = $_POST['slug'];
|
||||
$icon = $_POST['icon'];
|
||||
$description = $_POST['description'];
|
||||
$modifier_ids = isset($_POST['modifiers']) ? $_POST['modifiers'] : [];
|
||||
|
||||
if ($id > 0) {
|
||||
$stmt = $db->prepare("UPDATE celestial_object_types SET name = ?, slug = ?, icon = ?, description = ? WHERE id = ?");
|
||||
@ -48,7 +49,18 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
} else {
|
||||
$stmt = $db->prepare("INSERT INTO celestial_object_types (name, slug, icon, description) VALUES (?, ?, ?, ?)");
|
||||
$stmt->execute([$name, $slug, $icon, $description]);
|
||||
$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;
|
||||
}
|
||||
@ -87,7 +99,7 @@ if (isset($_GET['delete_status'])) {
|
||||
}
|
||||
|
||||
// Handle Settlement Type CRUD
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_settlement') {
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_settlement_type') {
|
||||
$id = (int)$_POST['id'];
|
||||
$name = $_POST['name'];
|
||||
$slug = $_POST['slug'];
|
||||
@ -100,14 +112,39 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
$stmt = $db->prepare("INSERT INTO settlement_types (name, slug, description) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$name, $slug, $description]);
|
||||
}
|
||||
header("Location: admin.php?tab=settlements&success=1");
|
||||
header("Location: admin.php?tab=settlement_types&success=1");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_GET['delete_settlement'])) {
|
||||
$id = (int)$_GET['delete_settlement'];
|
||||
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=settlements&success=1");
|
||||
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'];
|
||||
$type = $_POST['type'];
|
||||
$description = $_POST['description'];
|
||||
|
||||
if ($id > 0) {
|
||||
$stmt = $db->prepare("UPDATE modifiers SET name = ?, type = ?, description = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $type, $description, $id]);
|
||||
} else {
|
||||
$stmt = $db->prepare("INSERT INTO modifiers (name, type, description) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$name, $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;
|
||||
}
|
||||
|
||||
@ -115,16 +152,26 @@ if (isset($_GET['delete_settlement'])) {
|
||||
$users_list = [];
|
||||
$objects_list = [];
|
||||
$statuses_list = [];
|
||||
$settlements_list = [];
|
||||
$settlement_types_list = [];
|
||||
$modifiers_list = [];
|
||||
|
||||
if ($tab === 'users') {
|
||||
$users_list = $db->query("SELECT id, username, email, role FROM users ORDER BY username ASC")->fetchAll();
|
||||
} elseif ($tab === 'objects') {
|
||||
$objects_list = $db->query("SELECT * FROM celestial_object_types ORDER BY name ASC")->fetchAll();
|
||||
// For each object, get its modifiers
|
||||
foreach ($objects_list as &$obj) {
|
||||
$stmt = $db->prepare("SELECT modifier_id FROM celestial_object_type_modifiers WHERE celestial_object_type_id = ?");
|
||||
$stmt->execute([$obj['id']]);
|
||||
$obj['modifier_ids'] = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
}
|
||||
$modifiers_list = $db->query("SELECT * FROM modifiers ORDER BY type, name ASC")->fetchAll();
|
||||
} elseif ($tab === 'statuses') {
|
||||
$statuses_list = $db->query("SELECT * FROM celestial_object_statuses ORDER BY name ASC")->fetchAll();
|
||||
} elseif ($tab === 'settlements') {
|
||||
$settlements_list = $db->query("SELECT * FROM settlement_types 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();
|
||||
}
|
||||
|
||||
?>
|
||||
@ -142,7 +189,7 @@ if ($tab === 'users') {
|
||||
.nav-links a:hover { color: #fff; }
|
||||
.container { padding: 40px; max-width: 1200px; margin: 0 auto; }
|
||||
|
||||
.tabs { display: flex; gap: 5px; margin-bottom: 20px; border-bottom: 2px solid #2d3545; }
|
||||
.tabs { display: flex; gap: 5px; margin-bottom: 20px; border-bottom: 2px solid #2d3545; flex-wrap: wrap; }
|
||||
.tab-link { padding: 10px 20px; text-decoration: none; color: #8c92a3; background: #0a0f1d; border: 1px solid #2d3545; border-bottom: none; font-weight: bold; font-size: 14px; }
|
||||
.tab-link.active { background: #1a202c; color: #88c0d0; border-bottom: 2px solid #88c0d0; }
|
||||
|
||||
@ -162,6 +209,10 @@ if ($tab === 'users') {
|
||||
.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; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -186,8 +237,9 @@ if ($tab === 'users') {
|
||||
<div class="tabs">
|
||||
<a href="?tab=users" class="tab-link <?php echo $tab === 'users' ? 'active' : ''; ?>"><i class="fa-solid fa-users"></i> Utilisateurs</a>
|
||||
<a href="?tab=objects" class="tab-link <?php echo $tab === 'objects' ? 'active' : ''; ?>"><i class="fa-solid fa-earth-europe"></i> Objets Célestes</a>
|
||||
<a href="?tab=modifiers" class="tab-link <?php echo $tab === 'modifiers' ? 'active' : ''; ?>"><i class="fa-solid fa-bolt"></i> Bonus & Malus</a>
|
||||
<a href="?tab=statuses" class="tab-link <?php echo $tab === 'statuses' ? 'active' : ''; ?>"><i class="fa-solid fa-signal"></i> Statuts / États</a>
|
||||
<a href="?tab=settlements" class="tab-link <?php echo $tab === 'settlements' ? 'active' : ''; ?>"><i class="fa-solid fa-city"></i> Villes / Avant-postes</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>
|
||||
</div>
|
||||
|
||||
<?php if ($tab === 'users'): ?>
|
||||
@ -244,7 +296,24 @@ if ($tab === 'users') {
|
||||
<input type="text" name="icon" id="obj_icon" required placeholder="Ex: fa-earth-europe">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
<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>
|
||||
@ -254,13 +323,24 @@ if ($tab === 'users') {
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead><tr><th>Icône</th><th>Nom</th><th>Slug</th><th>Actions</th></tr></thead>
|
||||
<thead><tr><th>Icône</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><strong><?php echo htmlspecialchars($o['name']); ?></strong></td>
|
||||
<td><code><?php echo htmlspecialchars($o['slug']); ?></code></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); ?>)'>Editer</button>
|
||||
<a href="?tab=objects&delete_object=<?php echo $o['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cet objet ?')">Suppr</a>
|
||||
@ -270,6 +350,56 @@ if ($tab === 'users') {
|
||||
</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>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>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>
|
||||
<button class="btn btn-edit" onclick='editModifier(<?php echo json_encode($m); ?>)'>Editer</button>
|
||||
<a href="?tab=modifiers&delete_modifier=<?php echo $m['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce modificateur ?')">Suppr</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php elseif ($tab === 'statuses'): ?>
|
||||
<h3 style="color: #88c0d0;">Statuts / États</h3>
|
||||
<div class="form-card">
|
||||
@ -317,43 +447,43 @@ if ($tab === 'users') {
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php elseif ($tab === 'settlements'): ?>
|
||||
<h3 style="color: #88c0d0;">Villes / Avant-postes</h3>
|
||||
<?php elseif ($tab === 'settlement_types'): ?>
|
||||
<h3 style="color: #88c0d0;">Types d'Établissements</h3>
|
||||
<div class="form-card">
|
||||
<h4>Ajouter / Modifier un Type d'Établissement</h4>
|
||||
<form method="POST" id="settlementForm">
|
||||
<input type="hidden" name="action" value="upsert_settlement">
|
||||
<input type="hidden" name="id" id="set_id" value="0">
|
||||
<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_name" required>
|
||||
<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_slug" required>
|
||||
<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_desc" rows="2"></textarea>
|
||||
<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="resetSettlementForm()">ANNULER</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 ($settlements_list as $st): ?>
|
||||
<?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='editSettlement(<?php echo json_encode($st); ?>)'>Editer</button>
|
||||
<a href="?tab=settlements&delete_settlement=<?php echo $st['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer ce type ?')">Suppr</a>
|
||||
<button class="btn btn-edit" onclick='editSettlementType(<?php echo json_encode($st); ?>)'>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; ?>
|
||||
@ -369,9 +499,23 @@ if ($tab === 'users') {
|
||||
document.getElementById('obj_slug').value = data.slug;
|
||||
document.getElementById('obj_icon').value = data.icon;
|
||||
document.getElementById('obj_desc').value = data.description;
|
||||
|
||||
// Reset checkboxes
|
||||
document.querySelectorAll('.modifier-checkbox').forEach(cb => cb.checked = false);
|
||||
// Check assigned modifiers
|
||||
if (data.modifier_ids) {
|
||||
data.modifier_ids.forEach(mid => {
|
||||
const cb = document.querySelector(`.modifier-checkbox[value="${mid}"]`);
|
||||
if (cb) cb.checked = true;
|
||||
});
|
||||
}
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetObjectForm() { document.getElementById('objectForm').reset(); document.getElementById('obj_id').value = 0; }
|
||||
function resetObjectForm() {
|
||||
document.getElementById('objectForm').reset();
|
||||
document.getElementById('obj_id').value = 0;
|
||||
document.querySelectorAll('.modifier-checkbox').forEach(cb => cb.checked = false);
|
||||
}
|
||||
|
||||
function editStatus(data) {
|
||||
document.getElementById('st_id').value = data.id;
|
||||
@ -383,14 +527,23 @@ if ($tab === 'users') {
|
||||
}
|
||||
function resetStatusForm() { document.getElementById('statusForm').reset(); document.getElementById('st_id').value = 0; }
|
||||
|
||||
function editSettlement(data) {
|
||||
document.getElementById('set_id').value = data.id;
|
||||
document.getElementById('set_name').value = data.name;
|
||||
document.getElementById('set_slug').value = data.slug;
|
||||
document.getElementById('set_desc').value = data.description;
|
||||
function editSettlementType(data) {
|
||||
document.getElementById('set_t_id').value = data.id;
|
||||
document.getElementById('set_t_name').value = data.name;
|
||||
document.getElementById('set_t_slug').value = data.slug;
|
||||
document.getElementById('set_t_desc').value = data.description;
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetSettlementForm() { document.getElementById('settlementForm').reset(); document.getElementById('set_id').value = 0; }
|
||||
function resetSettlementTypeForm() { document.getElementById('settlementTypeForm').reset(); document.getElementById('set_t_id').value = 0; }
|
||||
|
||||
function editModifier(data) {
|
||||
document.getElementById('mod_id').value = data.id;
|
||||
document.getElementById('mod_name').value = data.name;
|
||||
document.getElementById('mod_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; }
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
41
db/add_modifiers.php
Normal file
41
db/add_modifiers.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// Create modifiers table
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS modifiers (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
type ENUM('bonus', 'malus') NOT NULL,
|
||||
description TEXT,
|
||||
icon VARCHAR(50) DEFAULT 'info-circle'
|
||||
)");
|
||||
|
||||
// Create junction table for celestial_object_types and modifiers
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS celestial_object_type_modifiers (
|
||||
celestial_object_type_id INT NOT NULL,
|
||||
modifier_id INT NOT NULL,
|
||||
PRIMARY KEY (celestial_object_type_id, modifier_id),
|
||||
FOREIGN KEY (celestial_object_type_id) REFERENCES celestial_object_types(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (modifier_id) REFERENCES modifiers(id) ON DELETE CASCADE
|
||||
)");
|
||||
|
||||
// Insert sample modifiers
|
||||
$modifiers = [
|
||||
['Chaleur', 'malus', 'Progression des troupes divisée par deux due à la chaleur extrême.'],
|
||||
['Chaleur Extrême', 'malus', 'Effets de chaleur doublés, risque d\'incendie élevé.'],
|
||||
['Gravité Faible', 'bonus', 'Vitesse de construction et mouvement des troupes augmentés.'],
|
||||
['Atmosphère Toxique', 'malus', 'Besoin de respirateurs permanents, réduction de l\'espérance de vie.'],
|
||||
['Ressources Abondantes', 'bonus', 'Production de ressources doublée.'],
|
||||
['Froid Polaire', 'malus', 'Consommation d\'énergie accrue pour le chauffage.'],
|
||||
['Champ de Ruines', 'bonus', 'Possibilité de récupérer des débris technologiques anciens.']
|
||||
];
|
||||
|
||||
$stmt = $pdo->prepare("INSERT IGNORE INTO modifiers (name, type, description) VALUES (?, ?, ?)");
|
||||
foreach ($modifiers as $m) {
|
||||
$stmt->execute($m);
|
||||
}
|
||||
|
||||
echo "Migration for modifiers completed successfully.\n";
|
||||
|
||||
@ -1,88 +1,34 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
$db = db();
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
// 1. Create celestial_object_types table
|
||||
$db->exec("CREATE TABLE IF NOT EXISTS celestial_object_types (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
slug VARCHAR(50) NOT NULL UNIQUE,
|
||||
icon VARCHAR(50) NOT NULL,
|
||||
description TEXT
|
||||
)");
|
||||
|
||||
// 2. Create celestial_object_statuses table
|
||||
$db->exec("CREATE TABLE IF NOT EXISTS celestial_object_statuses (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
slug VARCHAR(50) NOT NULL UNIQUE,
|
||||
color VARCHAR(20) NOT NULL,
|
||||
description TEXT
|
||||
)");
|
||||
|
||||
// 3. Create settlement_types table
|
||||
$db->exec("CREATE TABLE IF NOT EXISTS settlement_types (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
slug VARCHAR(50) NOT NULL UNIQUE,
|
||||
description TEXT
|
||||
)");
|
||||
|
||||
// 4. Seed initial data
|
||||
$object_types = [
|
||||
['Planète', 'planet', 'fa-earth-europe', 'Une planète habitable ou non.'],
|
||||
['Champ d\'astéroïdes', 'asteroid', 'fa-mountain', 'Riche en minerais.'],
|
||||
['Trou noir', 'black_hole', 'fa-circle-dot', 'Phénomène gravitationnel extrême.'],
|
||||
['Pulsar', 'pulsar', 'fa-bolt', 'Étoile à neutrons hautement magnétisée.'],
|
||||
['Étoile', 'star', 'fa-sun', 'Étoile centrale d\'un système.'],
|
||||
['Comète', 'comet', 'fa-comet', 'Petit corps céleste de glace et de poussière.'],
|
||||
['Vaisseau abandonné', 'wreckage', 'fa-ship', 'Épave dérivant dans l\'espace.'],
|
||||
['Champ de bataille', 'battlefield', 'fa-burst', 'Vestiges d\'un affrontement spatial.'],
|
||||
['Vortex', 'vortex', 'fa-whirlpool', 'Anomalie spatio-temporelle.'],
|
||||
];
|
||||
|
||||
$stmt = $db->prepare("INSERT IGNORE INTO celestial_object_types (name, slug, icon, description) VALUES (?, ?, ?, ?)");
|
||||
foreach ($object_types as $ot) {
|
||||
$stmt->execute($ot);
|
||||
$db = db();
|
||||
|
||||
// Check current column types for 'type' and 'status' in 'planets' table
|
||||
$stmt = $db->query("DESCRIBE planets");
|
||||
$columns = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
echo "Current schema for 'planets' table:\n";
|
||||
foreach ($columns as $column) {
|
||||
if ($column['Field'] === 'type' || $column['Field'] === 'status') {
|
||||
echo "- {$column['Field']}: {$column['Type']}\n";
|
||||
}
|
||||
}
|
||||
|
||||
$statuses = [
|
||||
['Inhabité / Vide', 'empty', 'rgba(255,255,255,0.05)', 'Aucune présence détectée.'],
|
||||
['Hostile', 'hostile', '#ef4444', 'Zone contrôlée par des ennemis.'],
|
||||
['Stable / Allié', 'stable', '#a3be8c', 'Zone sûre et amicale.'],
|
||||
['Contrôlé', 'controlled', '#5e81ac', 'Zone sous contrôle total.'],
|
||||
['Contesté', 'contested', '#ebcb8b', 'Zone de conflit actif.'],
|
||||
['Ressources', 'resource', '#f59e0b', 'Zone riche en ressources exploitables.'],
|
||||
['PNA', 'pna', '#d08770', 'Pacte de Non-Agression en vigueur.'],
|
||||
['Vortex', 'vortex', '#8b5cf6', 'Zone instable.'],
|
||||
['Inhabité (Neutre)', 'inhabited', '#eceff4', 'Présence neutre ou civile.'],
|
||||
];
|
||||
echo "\nConverting 'type' and 'status' columns to VARCHAR(50) to allow dynamic values...\n";
|
||||
|
||||
$stmt = $db->prepare("INSERT IGNORE INTO celestial_object_statuses (name, slug, color, description) VALUES (?, ?, ?, ?)");
|
||||
foreach ($statuses as $s) {
|
||||
$stmt->execute($s);
|
||||
}
|
||||
// Convert 'type' to VARCHAR(50)
|
||||
$db->exec("ALTER TABLE planets MODIFY COLUMN type VARCHAR(50) NOT NULL DEFAULT 'planet'");
|
||||
echo "Column 'type' converted successfully.\n";
|
||||
|
||||
$settlement_types = [
|
||||
['Avant-poste', 'avant-poste', 'Petite base avancée.'],
|
||||
['Petite ville', 'petite', 'Établissement mineur.'],
|
||||
['Moyenne ville', 'moyenne', 'Établissement standard.'],
|
||||
['Grande ville', 'grande', 'Métropole importante.'],
|
||||
['Mégacité', 'mégacité', 'Centre urbain colossal.'],
|
||||
];
|
||||
// Convert 'status' to VARCHAR(50)
|
||||
$db->exec("ALTER TABLE planets MODIFY COLUMN status VARCHAR(50) NOT NULL DEFAULT 'stable'");
|
||||
echo "Column 'status' converted successfully.\n";
|
||||
|
||||
$stmt = $db->prepare("INSERT IGNORE INTO settlement_types (name, slug, description) VALUES (?, ?, ?)");
|
||||
foreach ($settlement_types as $st) {
|
||||
$stmt->execute($st);
|
||||
}
|
||||
echo "\nMigration completed successfully. New types and statuses will now be accepted.\n";
|
||||
|
||||
// 5. Update planets and cities tables to use IDs (optional but better for integrity)
|
||||
// For now, let's just make sure the tables exist and can be managed.
|
||||
// We will update the code to use these tables for the select options.
|
||||
|
||||
echo "Migration completed successfully.";
|
||||
} catch (PDOException $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
echo "Error during migration: " . $e->getMessage() . "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
?>
|
||||
55
db/migrate_settlements_v2.php
Normal file
55
db/migrate_settlements_v2.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
$db = db();
|
||||
|
||||
try {
|
||||
// 1. Create settlement_sizes table
|
||||
$db->exec("CREATE TABLE IF NOT EXISTS settlement_sizes (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
slug VARCHAR(50) NOT NULL,
|
||||
description TEXT
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
|
||||
|
||||
// 2. Insert default sizes if empty
|
||||
$count = $db->query("SELECT COUNT(*) FROM settlement_sizes")->fetchColumn();
|
||||
if ($count == 0) {
|
||||
$db->exec("INSERT INTO settlement_sizes (name, slug, description) VALUES
|
||||
('Minuscule', 'minuscule', 'Très petit établissement.'),
|
||||
('Petit', 'petit', 'Établissement mineur.'),
|
||||
('Moyen', 'moyen', 'Établissement standard.'),
|
||||
('Grand', 'grand', 'Métropole importante.'),
|
||||
('Gigantesque', 'gigantesque', 'Centre urbain colossal.')");
|
||||
}
|
||||
|
||||
// 3. Ensure settlement_types has better data (just types)
|
||||
// We'll keep existing but maybe add more
|
||||
$count = $db->query("SELECT COUNT(*) FROM settlement_types")->fetchColumn();
|
||||
if ($count <= 5) { // If it only has the old mixed ones
|
||||
$db->exec("INSERT INTO settlement_types (name, slug, description) VALUES
|
||||
('Base Militaire', 'base_militaire', 'Installation de défense.'),
|
||||
('Station de Recherche', 'station_recherche', 'Laboratoire scientifique.')");
|
||||
}
|
||||
|
||||
// 4. Update cities table
|
||||
// First, add new columns
|
||||
$db->exec("ALTER TABLE cities ADD COLUMN settlement_type_id INT NULL AFTER planet_id;");
|
||||
$db->exec("ALTER TABLE cities ADD COLUMN settlement_size_id INT NULL AFTER settlement_type_id;");
|
||||
|
||||
// Try to migrate old data if any
|
||||
// Map old enum strings to IDs (rough estimation)
|
||||
$db->exec("UPDATE cities SET settlement_type_id = 1 WHERE type = 'avant-poste'");
|
||||
$db->exec("UPDATE cities SET settlement_type_id = 2 WHERE type != 'avant-poste'");
|
||||
$db->exec("UPDATE cities SET settlement_size_id = 2 WHERE type = 'petite'");
|
||||
$db->exec("UPDATE cities SET settlement_size_id = 3 WHERE type = 'moyenne'");
|
||||
$db->exec("UPDATE cities SET settlement_size_id = 4 WHERE type = 'grande'");
|
||||
$db->exec("UPDATE cities SET settlement_size_id = 5 WHERE type = 'mégacité'");
|
||||
|
||||
// Drop old type column
|
||||
$db->exec("ALTER TABLE cities DROP COLUMN type;");
|
||||
|
||||
echo "Migration successful!\n";
|
||||
} catch (Exception $e) {
|
||||
echo "Error during migration: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
19
db/remove_settlement_sizes.php
Normal file
19
db/remove_settlement_sizes.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
$db = db();
|
||||
|
||||
try {
|
||||
// 1. Remove foreign key column from cities
|
||||
$db->exec("ALTER TABLE cities DROP COLUMN settlement_size_id;");
|
||||
echo "Removed settlement_size_id from cities table.\n";
|
||||
|
||||
// 2. Drop settlement_sizes table
|
||||
$db->exec("DROP TABLE IF EXISTS settlement_sizes;");
|
||||
echo "Dropped settlement_sizes table.\n";
|
||||
|
||||
echo "Migration completed successfully.\n";
|
||||
} catch (PDOException $e) {
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
189
gm_console.php
189
gm_console.php
@ -20,10 +20,10 @@ if (!$current_user || ($current_user['role'] !== 'admin' && $current_user['role'
|
||||
|
||||
$is_admin = ($current_user['role'] === 'admin');
|
||||
|
||||
// Fetch Dynamic Types and Statuses
|
||||
$object_types_db = $db->query("SELECT * FROM celestial_object_types ORDER BY id ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$statuses_db = $db->query("SELECT * FROM celestial_object_statuses ORDER BY id ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$settlement_types_db = $db->query("SELECT * FROM settlement_types ORDER BY id ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||
// Fetch Dynamic Types, Statuses, and Settlement Types - Sorted Alphabetically
|
||||
$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);
|
||||
|
||||
$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;
|
||||
@ -42,6 +42,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
|
||||
if ($type === 'empty') {
|
||||
if ($slot_id > 0) {
|
||||
$db->prepare("DELETE FROM cities WHERE planet_id = ?")->execute([$slot_id]);
|
||||
$db->prepare("DELETE FROM planets WHERE id = ?")->execute([$slot_id]);
|
||||
}
|
||||
} else {
|
||||
@ -55,18 +56,36 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
$planet_id = $db->lastInsertId();
|
||||
}
|
||||
|
||||
// Handle Settlement (City)
|
||||
if (!empty($_POST['city_name'])) {
|
||||
$c_name = $_POST['city_name'];
|
||||
$c_type = $_POST['city_type'];
|
||||
// Simple check if city exists for this planet
|
||||
$stmt = $db->prepare("SELECT id FROM cities WHERE planet_id = ?");
|
||||
$stmt->execute([$planet_id]);
|
||||
$city = $stmt->fetch();
|
||||
if ($city) {
|
||||
$db->prepare("UPDATE cities SET name = ?, type = ? WHERE id = ?")->execute([$c_name, $c_type, $city['id']]);
|
||||
// Handle Multiple Settlements
|
||||
$sent_city_ids = [];
|
||||
if (isset($_POST['cities']) && is_array($_POST['cities'])) {
|
||||
foreach ($_POST['cities'] as $city_data) {
|
||||
if (empty($city_data['name'])) continue;
|
||||
|
||||
$c_id = (int)($city_data['id'] ?? 0);
|
||||
$c_name = $city_data['name'];
|
||||
$c_type_id = (int)$city_data['type_id'];
|
||||
|
||||
if ($c_id > 0) {
|
||||
$stmt = $db->prepare("UPDATE cities SET name = ?, settlement_type_id = ? WHERE id = ? AND planet_id = ?");
|
||||
$stmt->execute([$c_name, $c_type_id, $c_id, $planet_id]);
|
||||
$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]);
|
||||
$sent_city_ids[] = $db->lastInsertId();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Delete cities that were removed in the UI
|
||||
if ($planet_id > 0) {
|
||||
if (empty($sent_city_ids)) {
|
||||
$db->prepare("DELETE FROM cities WHERE planet_id = ?")->execute([$planet_id]);
|
||||
} else {
|
||||
$db->prepare("INSERT INTO cities (planet_id, name, type) VALUES (?, ?, ?)")->execute([$planet_id, $c_name, $c_type]);
|
||||
$placeholders = implode(',', array_fill(0, count($sent_city_ids), '?'));
|
||||
$stmt = $db->prepare("DELETE FROM cities WHERE planet_id = ? AND id NOT IN ($placeholders)");
|
||||
$params = array_merge([$planet_id], $sent_city_ids);
|
||||
$stmt->execute($params);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,7 +105,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
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([$sector_id, $s_name, $s_status, $galaxy_id]);
|
||||
$db->prepare("INSERT INTO sectors (id, name, status, galaxy_id) VALUES (?, ?, ?, ?)")->execute([$s_name, $s_status, $sector_id, $galaxy_id]);
|
||||
}
|
||||
header("Location: gm_console.php?view=sector&galaxy_id=$galaxy_id§or_id=$sector_id&success=1");
|
||||
exit;
|
||||
@ -98,14 +117,34 @@ $sector_id = isset($_GET['sector_id']) ? (int)$_GET['sector_id'] : 1;
|
||||
$grid_size = 36;
|
||||
|
||||
if ($view === 'sector') {
|
||||
// Fetch planets AND their cities
|
||||
$stmt = $db->prepare("SELECT p.*, c.name as city_name, c.type as city_type FROM planets p LEFT JOIN cities c ON p.id = c.planet_id WHERE p.galaxy_id = ? AND p.sector_id = ? AND p.slot BETWEEN 1 AND ?");
|
||||
// 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;
|
||||
$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)");
|
||||
$stmt->execute($planet_ids);
|
||||
$all_cities = $stmt->fetchAll();
|
||||
foreach ($all_cities as $city) {
|
||||
foreach ($grid as &$slot_data) {
|
||||
if ($slot_data && $slot_data['id'] == $city['planet_id']) {
|
||||
$slot_data['cities'][] = $city;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT * FROM sectors WHERE id = ?");
|
||||
$stmt->execute([$sector_id]);
|
||||
$sector_info = $stmt->fetch();
|
||||
@ -156,13 +195,23 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
.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: 30px; border: 2px solid #88c0d0; width: 450px; box-shadow: 0 0 50px rgba(136, 192, 208, 0.2); max-height: 90vh; overflow-y: auto; }
|
||||
.modal-content h3 { margin-top: 0; color: #88c0d0; }
|
||||
.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: 12px; color: #8c92a3; margin-bottom: 5px; }
|
||||
.form-group input, .form-group select { width: 100%; background: #0f172a; border: 1px solid #334155; color: #fff; padding: 10px; box-sizing: border-box; }
|
||||
.btn-save { background: #a3be8c; color: #000; border: none; padding: 10px 20px; font-weight: bold; cursor: pointer; width: 100%; font-size: 16px; margin-top: 10px; }
|
||||
.btn-cancel { background: #bf616a; color: #fff; border: none; padding: 10px 20px; font-weight: bold; cursor: pointer; width: 100%; margin-top: 10px; }
|
||||
.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; }
|
||||
|
||||
.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); }
|
||||
|
||||
.compact-row { display: flex; gap: 12px; align-items: flex-end; }
|
||||
.compact-row .form-group { margin-bottom: 0; flex: 1; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -247,19 +296,20 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
<input type="hidden" name="galaxy_id" value="<?php echo $galaxy_id; ?>">
|
||||
<input type="hidden" name="sector_id" value="<?php echo $sector_id; ?>">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Nom de l'objet / Planète</label>
|
||||
<input type="text" name="name" id="form_name" placeholder="Ex: Terra Nova..." required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Type d'objet céleste</label>
|
||||
<select name="type" id="form_type">
|
||||
<option value="empty">VIDE (Supprimer)</option>
|
||||
<?php foreach($object_types_db as $ot): ?>
|
||||
<option value="<?php echo $ot['slug']; ?>"><?php echo $ot['name']; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div style="display: flex; gap: 15px;">
|
||||
<div class="form-group" style="flex: 2;">
|
||||
<label>Nom de l'objet / Planète</label>
|
||||
<input type="text" name="name" id="form_name" placeholder="Ex: Terra Nova..." required>
|
||||
</div>
|
||||
<div class="form-group" style="flex: 1;">
|
||||
<label>Type d'objet</label>
|
||||
<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>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@ -271,23 +321,15 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style="background: rgba(0,0,0,0.2); padding: 15px; border: 1px dashed #4c566a; margin-bottom: 15px;">
|
||||
<label style="font-size: 11px; color: #88c0d0; font-weight: bold; display: block; margin-bottom: 10px;">GESTION VILLE / AVANT-POSTE</label>
|
||||
<div class="form-group">
|
||||
<label>Nom de l'établissement</label>
|
||||
<input type="text" name="city_name" id="form_city_name" placeholder="Laisser vide si aucun">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Taille / Type</label>
|
||||
<select name="city_type" id="form_city_type">
|
||||
<?php foreach($settlement_types_db as $set): ?>
|
||||
<option value="<?php echo $set['slug']; ?>"><?php echo $set['name']; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div style="background: rgba(0,0,0,0.1); padding: 15px; border-radius: 6px; border: 1px solid #334155; margin-bottom: 20px;">
|
||||
<label style="font-size: 11px; color: #88c0d0; font-weight: bold; display: block; margin-bottom: 15px; text-align: center; border-bottom: 1px solid #334155; padding-bottom: 8px;">ÉTABLISSEMENTS</label>
|
||||
<div id="settlementsContainer">
|
||||
<!-- Settlements will be injected here -->
|
||||
</div>
|
||||
<button type="button" class="btn-add-settlement" onclick="addSettlementRow()"><i class="fa-solid fa-plus"></i> AJOUTER UN ÉTABLISSEMENT</button>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 10px;">
|
||||
<div style="display: flex; gap: 15px;">
|
||||
<div class="form-group" style="flex: 1;">
|
||||
<label>Contrôle Orbital (%)</label>
|
||||
<input type="number" name="orbital_control" id="form_orbital" min="0" max="100" value="0">
|
||||
@ -298,7 +340,7 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn-save">ENREGISTRER LES MODIFICATIONS</button>
|
||||
<button type="submit" class="btn-save">ENREGISTRER</button>
|
||||
<button type="button" class="btn-cancel" onclick="closeModal()">ANNULER</button>
|
||||
</form>
|
||||
</div>
|
||||
@ -335,9 +377,42 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let settlementIndex = 0;
|
||||
const settlementTypes = <?php echo json_encode($settlement_types_db); ?>;
|
||||
|
||||
function addSettlementRow(data = null) {
|
||||
const container = document.getElementById('settlementsContainer');
|
||||
const index = settlementIndex++;
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.className = 'settlement-item';
|
||||
div.id = 'settlement_row_' + index;
|
||||
|
||||
let html = `<button type="button" class="btn-remove-settlement" onclick="document.getElementById('settlement_row_${index}').remove()" title="Supprimer">×</button>`;
|
||||
html += `<input type="hidden" name="cities[${index}][id]" value="${data ? data.id : 0}">`;
|
||||
|
||||
html += `<div class="compact-row">`;
|
||||
html += `<div class="form-group" style="flex: 2;"><label>Nom</label>`;
|
||||
html += `<input type="text" name="cities[${index}][name]" value="${data ? data.name : ''}" placeholder="Ex: New Hope" required></div>`;
|
||||
|
||||
html += `<div class="form-group" style="flex: 1;"><label>Type</label><select name="cities[${index}][type_id]">`;
|
||||
settlementTypes.forEach(t => {
|
||||
const sel = (data && data.settlement_type_id == t.id) ? 'selected' : '';
|
||||
html += `<option value="${t.id}" ${sel}>${t.name}</option>`;
|
||||
});
|
||||
html += `</select></div>`;
|
||||
html += `</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;
|
||||
|
||||
if (data) {
|
||||
document.getElementById('form_slot_id').value = data.id;
|
||||
document.getElementById('form_name').value = data.name;
|
||||
@ -345,8 +420,10 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
document.getElementById('form_status').value = data.status;
|
||||
document.getElementById('form_orbital').value = data.orbital_control;
|
||||
document.getElementById('form_terrestrial').value = data.terrestrial_control;
|
||||
document.getElementById('form_city_name').value = data.city_name || '';
|
||||
document.getElementById('form_city_type').value = data.city_type || 'avant-poste';
|
||||
|
||||
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;
|
||||
@ -354,8 +431,6 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
document.getElementById('form_status').value = 'empty';
|
||||
document.getElementById('form_orbital').value = 0;
|
||||
document.getElementById('form_terrestrial').value = 0;
|
||||
document.getElementById('form_city_name').value = '';
|
||||
document.getElementById('form_city_type').value = 'avant-poste';
|
||||
}
|
||||
document.getElementById('editModal').style.display = 'flex';
|
||||
}
|
||||
@ -369,4 +444,4 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) {
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
97
index.php
97
index.php
@ -19,7 +19,15 @@ $sector_id = isset($_GET['sector_id']) ? (int)$_GET['sector_id'] : 1;
|
||||
$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);
|
||||
|
||||
$object_types_map = []; foreach($object_types_db as $ot) $object_types_map[$ot['slug']] = $ot;
|
||||
$object_types_map = [];
|
||||
foreach($object_types_db as $ot) {
|
||||
// Get modifiers for this type
|
||||
$stmt = $db->prepare("SELECT m.* FROM modifiers m JOIN celestial_object_type_modifiers cotm ON m.id = cotm.modifier_id WHERE cotm.celestial_object_type_id = ?");
|
||||
$stmt->execute([$ot['id']]);
|
||||
$ot['modifiers'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$object_types_map[$ot['slug']] = $ot;
|
||||
}
|
||||
|
||||
$statuses_map = []; foreach($statuses_db as $s) $statuses_map[$s['slug']] = $s;
|
||||
|
||||
// Grid size: 6x6 = 36 slots per sector
|
||||
@ -35,11 +43,34 @@ $resources = [
|
||||
];
|
||||
|
||||
if ($view === 'sector') {
|
||||
$stmt = $db->prepare("SELECT p.*, c.name as city_name, c.type as city_type FROM planets p LEFT JOIN cities c ON p.id = c.planet_id WHERE p.galaxy_id = ? AND p.sector_id = ? AND p.slot BETWEEN 1 AND ?");
|
||||
$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);
|
||||
foreach ($objects_raw as $obj) { $grid[$obj['slot']] = $obj; }
|
||||
$planet_ids = [];
|
||||
foreach ($objects_raw as $obj) {
|
||||
$grid[$obj['slot']] = $obj;
|
||||
$planet_ids[] = $obj['id'];
|
||||
$grid[$obj['slot']]['cities'] = [];
|
||||
}
|
||||
|
||||
if (!empty($planet_ids)) {
|
||||
$placeholders = implode(',', array_fill(0, count($planet_ids), '?'));
|
||||
$stmt = $db->prepare("SELECT c.*, st.name as type_name
|
||||
FROM cities c
|
||||
LEFT JOIN settlement_types st ON c.settlement_type_id = st.id
|
||||
WHERE c.planet_id IN ($placeholders)");
|
||||
$stmt->execute($planet_ids);
|
||||
$all_cities = $stmt->fetchAll();
|
||||
foreach ($all_cities as $city) {
|
||||
foreach ($grid as &$slot_data) {
|
||||
if ($slot_data && $slot_data['id'] == $city['planet_id']) {
|
||||
$slot_data['cities'][] = $city;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT name FROM sectors WHERE id = ?");
|
||||
$stmt->execute([$sector_id]);
|
||||
@ -101,12 +132,26 @@ function getStatusColor($status, $statuses_map) {
|
||||
.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: 10; }
|
||||
.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; }
|
||||
.city-label { font-size: 8px; color: #ebcb8b; margin-top: 2px; display: block; width: 90%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
|
||||
/* 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; }
|
||||
.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); }
|
||||
|
||||
.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; }
|
||||
|
||||
.legend { margin-top: 20px; background: rgba(10, 15, 30, 0.95); border: 1px solid #2d3545; padding: 10px 20px; display: flex; gap: 15px; font-size: 10px; flex-wrap: wrap; max-width: 1000px; justify-content: center; }
|
||||
.legend-item { display: flex; align-items: center; gap: 5px; }
|
||||
.dot { width: 8px; height: 8px; border-radius: 1px; }
|
||||
@ -166,18 +211,50 @@ function getStatusColor($status, $statuses_map) {
|
||||
<?php for($i=1; $i<=$grid_size; $i++): ?>
|
||||
<div class="slot">
|
||||
<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;
|
||||
?>
|
||||
<div class="tooltip-box">
|
||||
<div class="tooltip-title"><?php echo htmlspecialchars($obj['name']); ?></div>
|
||||
<div class="tooltip-desc"><?php echo htmlspecialchars($type_info['description'] ?? ''); ?></div>
|
||||
|
||||
<?php if (!empty($obj['cities'])): ?>
|
||||
<div class="settlement-title"><i class="fa-solid fa-city"></i> Établissements:</div>
|
||||
<?php foreach ($obj['cities'] as $c): ?>
|
||||
<div class="settlement-item-tool">
|
||||
<strong><?php echo htmlspecialchars($c['name']); ?></strong>
|
||||
<span style="color: #8c92a3; font-size: 8px;">(<?php echo htmlspecialchars($c['type_name']); ?>)</span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($type_info['modifiers'])): ?>
|
||||
<div class="mod-list">
|
||||
<?php foreach ($type_info['modifiers'] as $m): ?>
|
||||
<div class="mod-item <?php echo $m['type'] === 'bonus' ? 'mod-bonus' : 'mod-malus'; ?>">
|
||||
<i class="fa-solid <?php echo $m['type'] === 'bonus' ? 'fa-circle-up' : 'fa-circle-down'; ?>"></i>
|
||||
<strong><?php echo htmlspecialchars($m['name']); ?>:</strong> <?php echo htmlspecialchars($m['description']); ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="object-icon">
|
||||
<?php
|
||||
$icon = $object_types_map[$obj['type']]['icon'] ?? 'fa-earth-europe';
|
||||
$icon = $type_info['icon'] ?? 'fa-earth-europe';
|
||||
$color = getStatusColor($obj['status'], $statuses_map);
|
||||
?>
|
||||
<i class="fa-solid <?php echo $icon; ?>" style="color: <?php echo $color; ?>;"></i>
|
||||
</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>
|
||||
<?php if (!empty($obj['city_name'])): ?>
|
||||
<span class="city-label"><i class="fa-solid fa-city"></i> <?php echo htmlspecialchars($obj['city_name']); ?></span>
|
||||
<?php if (!empty($obj['cities'])): ?>
|
||||
<span class="city-label"><i class="fa-solid fa-city"></i>
|
||||
<?php
|
||||
$c_names = array_map(function($c) { return $c['name']; }, $obj['cities']);
|
||||
echo htmlspecialchars(implode(', ', $c_names));
|
||||
?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
<div style="opacity: 0.05;"><i class="fa-solid fa-circle fa-sm"></i></div>
|
||||
@ -224,4 +301,4 @@ function getStatusColor($status, $statuses_map) {
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user