mappings.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <?php
  2. require_once __DIR__ . '/auth.php';
  3. require_once __DIR__ . '/layout.php';
  4. require_admin();
  5. $pdo = get_pdo();
  6. // Handle add/remove mapping
  7. if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  8. $action = $_POST['action'] ?? '';
  9. $aid = (int)($_POST['activityID'] ?? 0);
  10. $iid = (int)($_POST['itemID'] ?? 0);
  11. if ($action === 'add' && $aid > 0 && $iid > 0) {
  12. $qty = max(1, (int)($_POST['quantity'] ?? 1));
  13. try {
  14. $pdo->prepare("INSERT IGNORE INTO activity_item_map (activityID,itemID,quantity) VALUES (?,?,?)")
  15. ->execute([$aid, $iid, $qty]);
  16. flash('success', 'Mapping added.');
  17. } catch (Exception $e) {
  18. flash('error', 'Could not add mapping.');
  19. }
  20. }
  21. if ($action === 'update' && $aid > 0 && $iid > 0) {
  22. $qty = max(1, (int)($_POST['quantity'] ?? 1));
  23. $pdo->prepare("UPDATE activity_item_map SET quantity=? WHERE activityID=? AND itemID=?")
  24. ->execute([$qty, $aid, $iid]);
  25. flash('success', 'Quantity updated.');
  26. }
  27. if ($action === 'remove' && $aid > 0 && $iid > 0) {
  28. $pdo->prepare("DELETE FROM activity_item_map WHERE activityID=? AND itemID=?")
  29. ->execute([$aid, $iid]);
  30. flash('success', 'Mapping removed.');
  31. }
  32. header('Location: mappings.php' . (isset($_GET['aid']) ? '?aid=' . (int)$_GET['aid'] : ''));
  33. exit;
  34. }
  35. // Load all activities and items for selects
  36. $activities = $pdo->query("
  37. SELECT a.activityID, a.activityName, ag.groupName
  38. FROM activities a
  39. JOIN activity_groups ag ON ag.groupID = a.groupID
  40. ORDER BY ag.sortOrder, a.sortOrder, a.activityID
  41. ")->fetchAll();
  42. $allItems = $pdo->query("
  43. SELECT i.itemID, i.itemName, ig.groupName
  44. FROM items i
  45. JOIN item_groups ig ON ig.groupID = i.groupID
  46. ORDER BY ig.sortOrder, i.sortOrder, i.itemID
  47. ")->fetchAll();
  48. // Selected activity filter
  49. $selectedAid = isset($_GET['aid']) ? (int)$_GET['aid'] : 0;
  50. if (!$selectedAid && !empty($activities)) {
  51. $selectedAid = $activities[0]['activityID'];
  52. }
  53. // Get current mappings for selected activity
  54. $mappedItemIds = [];
  55. $mappedItems = [];
  56. if ($selectedAid) {
  57. $stmt = $pdo->prepare("
  58. SELECT i.itemID, i.itemName, ig.groupName, aim.quantity
  59. FROM activity_item_map aim
  60. JOIN items i ON i.itemID = aim.itemID
  61. JOIN item_groups ig ON ig.groupID = i.groupID
  62. WHERE aim.activityID = ?
  63. ORDER BY ig.sortOrder, i.sortOrder
  64. ");
  65. $stmt->execute([$selectedAid]);
  66. $mappedItems = $stmt->fetchAll();
  67. $mappedItemIds = array_column($mappedItems, 'itemID');
  68. }
  69. admin_head('Mappings', 'mappings.php');
  70. show_alerts();
  71. ?>
  72. <h1>Activity ↔ Item Mappings</h1>
  73. <div style="display:flex;gap:1.5rem;flex-wrap:wrap;align-items:flex-start;">
  74. <!-- Activity selector -->
  75. <div class="card" style="min-width:220px;flex:0 0 220px;">
  76. <h2>Select Activity</h2>
  77. <?php foreach ($activities as $a): ?>
  78. <a href="?aid=<?= $a['activityID'] ?>"
  79. style="display:block;padding:.45rem .6rem;border-radius:6px;margin-bottom:.25rem;font-size:.85rem;text-decoration:none;
  80. background:<?= $selectedAid==$a['activityID'] ? 'rgba(232,197,71,.1)' : 'transparent' ?>;
  81. color:<?= $selectedAid==$a['activityID'] ? 'var(--accent)' : 'var(--muted)' ?>;
  82. border:1px solid <?= $selectedAid==$a['activityID'] ? 'rgba(232,197,71,.3)' : 'transparent' ?>;">
  83. <?= htmlspecialchars($a['activityName']) ?>
  84. <span style="float:right;font-size:.72rem;color:var(--muted)"><?= htmlspecialchars($a['groupName']) ?></span>
  85. </a>
  86. <?php endforeach; ?>
  87. </div>
  88. <!-- Mapping manager -->
  89. <div style="flex:1;min-width:300px;">
  90. <?php if ($selectedAid):
  91. // Get the activity name
  92. $actName = '';
  93. foreach ($activities as $a) { if ($a['activityID'] == $selectedAid) $actName = $a['activityName']; }
  94. ?>
  95. <div class="card">
  96. <h2 style="margin-bottom:1rem">Items for: <span style="color:var(--accent)"><?= htmlspecialchars($actName) ?></span></h2>
  97. <!-- Add new mapping -->
  98. <form method="POST" style="display:flex;gap:.5rem;align-items:flex-end;margin-bottom:1.25rem;flex-wrap:wrap;">
  99. <input type="hidden" name="action" value="add">
  100. <input type="hidden" name="activityID" value="<?= $selectedAid ?>">
  101. <div style="flex:1;min-width:200px;">
  102. <label>Add Item</label>
  103. <select name="itemID" required style="margin-bottom:0;">
  104. <option value="">– choose item –</option>
  105. <?php
  106. // Group items in optgroups
  107. $optGroups = [];
  108. foreach ($allItems as $it) {
  109. if (in_array($it['itemID'], $mappedItemIds)) continue; // already mapped
  110. $optGroups[$it['groupName']][] = $it;
  111. }
  112. foreach ($optGroups as $grpName => $grpItems):
  113. ?>
  114. <optgroup label="<?= htmlspecialchars($grpName) ?>">
  115. <?php foreach ($grpItems as $it): ?>
  116. <option value="<?= $it['itemID'] ?>"><?= htmlspecialchars($it['itemName']) ?></option>
  117. <?php endforeach; ?>
  118. </optgroup>
  119. <?php endforeach; ?>
  120. </select>
  121. </div>
  122. <div style="width:90px;">
  123. <label>Qty</label>
  124. <input type="number" name="quantity" value="1" min="1" style="margin-bottom:0;width:100%;">
  125. </div>
  126. <button type="submit" class="btn btn-primary">➕ Add</button>
  127. </form>
  128. <!-- Current mapped items -->
  129. <?php if (empty($mappedItems)): ?>
  130. <p style="color:var(--muted);font-size:.85rem">No items mapped yet.</p>
  131. <?php else: ?>
  132. <table class="tbl">
  133. <thead><tr><th>#</th><th>Item</th><th>Group</th><th>Qty</th><th></th></tr></thead>
  134. <tbody>
  135. <?php foreach ($mappedItems as $it): ?>
  136. <tr>
  137. <td style="color:var(--muted)"><?= $it['itemID'] ?></td>
  138. <td><?= htmlspecialchars($it['itemName']) ?></td>
  139. <td><span class="badge badge-group"><?= htmlspecialchars($it['groupName']) ?></span></td>
  140. <td>
  141. <form method="POST" style="display:flex;gap:.3rem;align-items:center;">
  142. <input type="hidden" name="action" value="update">
  143. <input type="hidden" name="activityID" value="<?= $selectedAid ?>">
  144. <input type="hidden" name="itemID" value="<?= $it['itemID'] ?>">
  145. <input type="number" name="quantity" value="<?= (int)$it['quantity'] ?>" min="1" style="margin:0;width:70px;">
  146. <button class="btn btn-sm btn-primary">💾</button>
  147. </form>
  148. </td>
  149. <td style="text-align:right">
  150. <form method="POST" onsubmit="return confirm('Remove this mapping?')">
  151. <input type="hidden" name="action" value="remove">
  152. <input type="hidden" name="activityID" value="<?= $selectedAid ?>">
  153. <input type="hidden" name="itemID" value="<?= $it['itemID'] ?>">
  154. <button class="btn btn-sm btn-danger">Remove</button>
  155. </form>
  156. </td>
  157. </tr>
  158. <?php endforeach; ?>
  159. </tbody>
  160. </table>
  161. <?php endif; ?>
  162. </div>
  163. <?php endif; ?>
  164. </div>
  165. </div>
  166. <?php admin_foot(); ?>