new.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. /**
  3. * Vue de création d'un nouveau projet
  4. */
  5. include __DIR__ . '/../partials/header.php';
  6. ?>
  7. <main class="main-content">
  8. <div class="container-fluid">
  9. <div class="row justify-content-center">
  10. <div class="col-lg-8 col-xl-6">
  11. <!-- En-tête de la page -->
  12. <div class="d-flex align-items-center mb-4">
  13. <div>
  14. <h1 class="h3 mb-0">
  15. <i class="bi bi-plus-circle me-2"></i>Nouveau projet
  16. </h1>
  17. <p class="text-muted mb-0">Créez une nouvelle carte personnalisée</p>
  18. </div>
  19. </div>
  20. <!-- Formulaire de création -->
  21. <div class="card">
  22. <div class="card-header">
  23. <h5 class="card-title mb-0">
  24. <i class="bi bi-pencil-square me-2"></i>Configuration du projet
  25. </h5>
  26. </div>
  27. <div class="card-body">
  28. <form id="newProjectForm" action="/projects/create" method="POST">
  29. <!-- Nom de la carte -->
  30. <div class="mb-3">
  31. <label for="mapName" class="form-label">
  32. <i class="bi bi-tag me-1"></i>Nom de la carte <span class="text-danger">*</span>
  33. </label>
  34. <input type="text" class="form-control" id="mapName" name="name" required
  35. placeholder="Ex: Ma belle carte" maxlength="100">
  36. <div class="form-text">Choisissez un nom descriptif pour votre carte</div>
  37. </div>
  38. <!-- Taille de la carte (en cases, orientation hexagonale) -->
  39. <div class="mb-3">
  40. <label class="form-label">
  41. <i class="bi bi-grid-3x3 me-1"></i>Taille de la carte (en cases) <span class="text-danger">*</span>
  42. </label>
  43. <!-- Presets hexagonaux (rayons 1..12) uniquement -->
  44. <!-- Presets hexagonaux -->
  45. <div id="hexPresets" class="mb-2">
  46. <label for="hexRadius" class="form-label small">Choisir une taille hexagonale</label>
  47. <select id="hexRadius" class="form-select" aria-label="Préréglages hexagonaux">
  48. <?php
  49. // Générer dynamiquement les presets rayon 1..15
  50. for ($r = 1; $r <= 15; $r++) {
  51. $count = 1 + 3 * $r * ($r + 1);
  52. $sel = $r === 2 ? ' selected' : '';
  53. // Affichage inversé : 'Rayon N (X cases)'
  54. echo "<option value=\"{$r}\"{$sel}>Rayon {$r} ({$count} cases)</option>\n";
  55. }
  56. ?>
  57. </select>
  58. <div id="hexInfo" class="form-text">Ex: 19 cases pour rayon 2. Les presets utilisent la formule 1 + 3R(R+1).</div>
  59. </div>
  60. <!-- Aperçu visuel simple -->
  61. <div id="hexPreviewContainer" class="mb-3" aria-hidden="false">
  62. <label class="form-label small">Aperçu</label>
  63. <div id="hexPreview" style="width:100%;height:160px;border:1px solid #e9ecef;background:#fafafa;display:flex;align-items:center;justify-content:center;">
  64. <!-- SVG dessiné par JS -->
  65. </div>
  66. </div>
  67. <!-- Valeurs cachées synchronisées pour compatibilité backend -->
  68. <input type="hidden" id="radiusInput" name="radius" value="2">
  69. </div>
  70. <!-- Description -->
  71. <div class="mb-3">
  72. <label for="mapDescription" class="form-label">
  73. <i class="bi bi-textarea me-1"></i>Description
  74. </label>
  75. <textarea class="form-control" id="mapDescription" name="description" rows="3"
  76. placeholder="Décrivez votre carte (optionnel)" maxlength="500"></textarea>
  77. <div class="form-text">Ajoutez une description pour vous souvenir du but de cette carte</div>
  78. </div>
  79. <!-- Modèles -->
  80. <div class="mb-4">
  81. <label for="mapTemplate" class="form-label">
  82. <i class="bi bi-palette me-1"></i>Modèle de départ <span class="text-danger">*</span>
  83. </label>
  84. <select class="form-select" id="mapTemplate" name="template" required>
  85. <option value="" disabled selected>Choisissez un modèle</option>
  86. <?php
  87. // Si le contrôleur a passé la liste des templates, utiliser celle-ci
  88. if (!empty($templates) && is_array($templates)) {
  89. foreach ($templates as $tid => $tmeta) {
  90. // n'afficher que les templates neutral, rural, urban selon demande
  91. if (!in_array($tid, ['neutral', 'rural', 'urban'])) continue;
  92. $label = htmlspecialchars($tmeta['name']);
  93. $desc = htmlspecialchars($tmeta['description'] ?? '');
  94. echo "<option value=\"{$tmeta['id']}\" title=\"{$desc}\">{$label}</option>\n";
  95. }
  96. } else {
  97. // Fallbacks
  98. echo "<option value=\"neutral\">Neutre</option>\n";
  99. echo "<option value=\"rural\">Paysage rural</option>\n";
  100. echo "<option value=\"urban\">Paysage urbain</option>\n";
  101. }
  102. ?>
  103. </select>
  104. <div class="form-text">Le modèle définit l'apparence de base de votre carte</div>
  105. </div>
  106. <!-- Définitions de tuiles (export JSON caché pour JS) -->
  107. <?php
  108. // Préparer les définitions de tuiles côté serveur pour les templates chargés
  109. $tilesExport = [];
  110. if (!empty($templates) && is_array($templates)) {
  111. foreach ($templates as $tid => $tmeta) {
  112. if (empty($tmeta['class'])) continue; // pas de code chargé
  113. $class = $tmeta['class'];
  114. try {
  115. if (method_exists($class, 'tileDefinitions')) {
  116. $defs = $class::tileDefinitions();
  117. $tilesExport[$tid] = $defs;
  118. }
  119. } catch (Throwable $e) {
  120. // ignore
  121. $tilesExport[$tid] = [];
  122. }
  123. }
  124. }
  125. ?>
  126. <script id="templateTilesData" type="application/json">
  127. <?= json_encode($tilesExport, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>
  128. </script>
  129. </div>
  130. <!-- Aperçu du modèle sélectionné -->
  131. <div id="templatePreview" class="mb-4" style="display: none;">
  132. <div class="card bg-light">
  133. <div class="card-body text-center">
  134. <div id="templateImage" class="mb-2">
  135. <!-- L'image du modèle sera chargée ici via JavaScript -->
  136. </div>
  137. <h6 id="templateTitle"></h6>
  138. <p id="templateDescription" class="text-muted small mb-2"></p>
  139. <div id="templateTiles" class="d-flex gap-2 justify-content-center flex-wrap">
  140. <!-- Les tuiles (petits carrés) seront injectées ici par JS -->
  141. </div>
  142. </div>
  143. </div>
  144. </div>
  145. <!-- Boutons d'action -->
  146. <div class="d-flex gap-2 justify-content-end">
  147. <a href="/" class="btn btn-outline-secondary">
  148. <i class="bi bi-x-circle me-1"></i>Annuler
  149. </a>
  150. <button type="submit" class="btn btn-primary">
  151. <i class="bi bi-check-circle me-1"></i>Créer le projet
  152. </button>
  153. </div>
  154. </form>
  155. </div>
  156. </div>
  157. </div>
  158. </div>
  159. </div>
  160. </main>
  161. <script src="/assets/js/pages/new-project.js"></script>
  162. <?php
  163. include __DIR__ . '/../partials/footer.php';
  164. ?>