report.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <?php
  2. error_reporting(E_ALL);
  3. ini_set('display_errors', 1);
  4. require_once __DIR__ . '/../config/database.php';
  5. require_once __DIR__ . '/../lib/auth.php';
  6. if (session_status() === PHP_SESSION_NONE) {
  7. session_start();
  8. }
  9. requireLogin();
  10. $pageTitle = 'Report History';
  11. $siteName = 'Crop Monitor';
  12. $pdo = getDBConnection();
  13. $userId = getCurrentUserId();
  14. function countRecords(\PDO $pdo, string $table, int $userId, int $status = 0): int {
  15. try {
  16. $stmt = $pdo->prepare("SELECT COUNT(*) FROM `$table` WHERE modx_user_id = ? AND status = ?");
  17. $stmt->execute([$userId, $status]);
  18. return (int) $stmt->fetchColumn();
  19. } catch (\PDOException $e) {
  20. error_log("countRecords error on $table: " . $e->getMessage());
  21. return 0;
  22. }
  23. }
  24. $counts = [
  25. 'soil' => countRecords($pdo, 'soil_records', $userId, 0),
  26. 'plant' => countRecords($pdo, 'plant_records', $userId, 0),
  27. 'water' => countRecords($pdo, 'water_records', $userId, 0),
  28. 'animal' => countRecords($pdo, 'animal_records', $userId, 0),
  29. 'archived'=> countRecords($pdo, 'soil_records', $userId, 2),
  30. 'deleted' => countRecords($pdo, 'soil_records', $userId, 3),
  31. ];
  32. function fetchHistory(\PDO $pdo, string $table, int $userId, string $select = 'id, rand, lab_no, sample_id, site_id, crop_type, date_sampled'): array {
  33. try {
  34. $stmt = $pdo->prepare(
  35. "SELECT {$select}
  36. FROM `{$table}`
  37. WHERE modx_user_id = ? AND status = 0
  38. ORDER BY id DESC LIMIT 100"
  39. );
  40. $stmt->execute([$userId]);
  41. return $stmt->fetchAll();
  42. } catch (\PDOException $e) {
  43. error_log("fetchHistory error on $table: " . $e->getMessage());
  44. return [];
  45. }
  46. }
  47. $soilRows = fetchHistory($pdo, 'soil_records', $userId);
  48. $plantRows = fetchHistory($pdo, 'plant_records', $userId);
  49. $waterRows = fetchHistory($pdo, 'water_records', $userId, 'id, rand, lab_no, sample_id, site_id, date_sampled');
  50. $animalRows = fetchHistory($pdo, 'animal_records', $userId, "id, rand, lab_no, sample_id, '' AS site_id, date_sampled");
  51. $h = fn($v) => htmlspecialchars((string) $v, ENT_QUOTES, 'UTF-8');
  52. include __DIR__ . '/../layouts/header.php';
  53. include __DIR__ . '/../layouts/navbar.php';
  54. ?>
  55. <div id="layoutSidenav">
  56. <div id="layoutSidenav_nav">
  57. <?php include __DIR__ . '/../layouts/sidebar.php'; ?>
  58. </div>
  59. <div id="layoutSidenav_content">
  60. <main>
  61. <div class="container-fluid px-4">
  62. <h1 class="mt-4"><?= $h($pageTitle) ?></h1>
  63. <ol class="breadcrumb mb-4">
  64. <li class="breadcrumb-item"><a href="/dashboard/dashboard.php">Dashboard</a></li>
  65. <li class="breadcrumb-item active">Report History</li>
  66. </ol>
  67. <div class="row inbox-mail">
  68. <!-- Left sidebar -->
  69. <div class="col-12 col-md-3">
  70. <div class="input-group mb-3">
  71. <input type="text" class="form-control" placeholder="Search...">
  72. <span class="input-group-text"><i class="fa fa-search"></i></span>
  73. </div>
  74. <div class="alert alert-danger py-0"><h4>Reports</h4></div>
  75. <div class="list-group" id="v-pills-tab" role="tablist">
  76. <a id="soil-reports-tab" data-bs-toggle="list" href="#soil-reports"
  77. role="tab" aria-controls="soil-reports"
  78. class="text-secondary list-group-item list-group-item-action list-group-item-light active">
  79. <i class="fas fa-icicles fa-rotate-180"></i> Soil Analysis
  80. <span class="badge bg-secondary float-end"><?= $counts['soil'] ?></span>
  81. </a>
  82. <a id="plant-reports-tab" data-bs-toggle="list" href="#plant-reports"
  83. role="tab" aria-controls="plant-reports"
  84. class="text-secondary list-group-item list-group-item-action list-group-item-light">
  85. <i class="fab fa-pagelines"></i> Plant Analysis
  86. <span class="badge bg-success float-end"><?= $counts['plant'] ?></span>
  87. </a>
  88. <a id="water-reports-tab" data-bs-toggle="list" href="#water-reports"
  89. role="tab" aria-controls="water-reports"
  90. class="text-secondary list-group-item list-group-item-action list-group-item-light">
  91. <i class="fa fa-tint"></i> Water Analysis
  92. <span class="badge bg-primary float-end"><?= $counts['water'] ?></span>
  93. </a>
  94. <a id="dietary-reports-tab" data-bs-toggle="list" href="#dietary-reports"
  95. role="tab" aria-controls="dietary-reports"
  96. class="text-secondary list-group-item list-group-item-action list-group-item-light">
  97. <i class="fas fa-dog"></i> Animal Dietary Balance
  98. <span class="badge bg-warning text-dark float-end"><?= $counts['animal'] ?></span>
  99. </a>
  100. <a id="compost-reports-tab" data-bs-toggle="list" href="#compost-reports"
  101. role="tab" aria-controls="compost-reports"
  102. class="text-secondary list-group-item list-group-item-action list-group-item-light">
  103. <i class="fas fa-cloud"></i> Compost Test Data
  104. <span class="badge bg-secondary float-end">0</span>
  105. </a>
  106. </div>
  107. <br>
  108. <div class="list-group">
  109. <span class="list-group-item fw-bold">Folders</span>
  110. <a href="#" class="list-group-item list-group-item-action list-group-item-light text-warning">
  111. <i class="fa fa-folder text-warning"></i> Archived
  112. <span class="badge bg-warning text-dark float-end"><?= $counts['archived'] ?></span>
  113. </a>
  114. <a href="#" class="list-group-item list-group-item-action list-group-item-light text-danger">
  115. <i class="fa fa-folder text-danger"></i> Deleted
  116. <span class="badge bg-danger float-end"><?= $counts['deleted'] ?></span>
  117. </a>
  118. </div>
  119. </div>
  120. <!-- Tab content -->
  121. <div class="col-12 col-md-9 tab-content">
  122. <!-- Soil -->
  123. <div class="tab-pane fade show active" id="soil-reports" role="tabpanel">
  124. <h5 class="mt-2">Soil Analysis Records</h5>
  125. <table class="table table-hover table-sm">
  126. <thead class="table-dark">
  127. <tr>
  128. <th>Lab No</th><th>Sample ID</th><th>Site ID</th>
  129. <th>Crop</th><th>Date Sampled</th><th class="text-end">Actions</th>
  130. </tr>
  131. </thead>
  132. <tbody>
  133. <?php if (empty($soilRows)): ?>
  134. <tr><td colspan="6" class="text-center text-muted">No records found.</td></tr>
  135. <?php else: foreach ($soilRows as $r): ?>
  136. <tr>
  137. <td><?= $h($r['lab_no']) ?></td>
  138. <td><?= $h($r['sample_id']) ?></td>
  139. <td><?= $h($r['site_id']) ?></td>
  140. <td><?= $h($r['crop_type']) ?></td>
  141. <td><?= $h($r['date_sampled']) ?></td>
  142. <td class="text-end">
  143. <a href="/dashboard/crop-analysis/soil-test-data/soil-analysis.php?rid=<?= (int)$r['id'] ?>&rand=<?= (float)$r['rand'] ?>"
  144. class="btn btn-sm btn-outline-success">View</a>
  145. </td>
  146. </tr>
  147. <?php endforeach; endif; ?>
  148. </tbody>
  149. </table>
  150. </div>
  151. <!-- Plant -->
  152. <div class="tab-pane fade" id="plant-reports" role="tabpanel">
  153. <h5 class="mt-2">Plant Analysis Records</h5>
  154. <table class="table table-hover table-sm">
  155. <thead class="table-dark">
  156. <tr>
  157. <th>Lab No</th><th>Sample ID</th><th>Site ID</th>
  158. <th>Crop</th><th>Date Sampled</th><th class="text-end">Actions</th>
  159. </tr>
  160. </thead>
  161. <tbody>
  162. <?php if (empty($plantRows)): ?>
  163. <tr><td colspan="6" class="text-center text-muted">No records found.</td></tr>
  164. <?php else: foreach ($plantRows as $r): ?>
  165. <tr>
  166. <td><?= $h($r['lab_no']) ?></td>
  167. <td><?= $h($r['sample_id']) ?></td>
  168. <td><?= $h($r['site_id']) ?></td>
  169. <td><?= $h($r['crop_type']) ?></td>
  170. <td><?= $h($r['date_sampled']) ?></td>
  171. <td class="text-end">
  172. <a href="/dashboard/crop-analysis/plant-test-data/plant-analysis.php?rid=<?= (int)$r['id'] ?>&rand=<?= (float)$r['rand'] ?>"
  173. class="btn btn-sm btn-outline-success">View</a>
  174. </td>
  175. </tr>
  176. <?php endforeach; endif; ?>
  177. </tbody>
  178. </table>
  179. </div>
  180. <!-- Water -->
  181. <div class="tab-pane fade" id="water-reports" role="tabpanel">
  182. <h5 class="mt-2">Water Analysis Records</h5>
  183. <table class="table table-hover table-sm">
  184. <thead class="table-dark">
  185. <tr>
  186. <th>Lab No</th><th>Sample ID</th><th>Site ID</th>
  187. <th>Date Sampled</th><th class="text-end">Actions</th>
  188. </tr>
  189. </thead>
  190. <tbody>
  191. <?php if (empty($waterRows)): ?>
  192. <tr><td colspan="5" class="text-center text-muted">No records found.</td></tr>
  193. <?php else: foreach ($waterRows as $r): ?>
  194. <tr>
  195. <td><?= $h($r['lab_no']) ?></td>
  196. <td><?= $h($r['sample_id']) ?></td>
  197. <td><?= $h($r['site_id']) ?></td>
  198. <td><?= $h($r['date_sampled']) ?></td>
  199. <td class="text-end">
  200. <a href="/dashboard/crop-analysis/water-test-data/water-analysis-pdf.php?rid=<?= (int)$r['id'] ?>&rand=<?= (float)$r['rand'] ?>"
  201. class="btn btn-sm btn-outline-success">View</a>
  202. </td>
  203. </tr>
  204. <?php endforeach; endif; ?>
  205. </tbody>
  206. </table>
  207. </div>
  208. <!-- Animal Dietary -->
  209. <div class="tab-pane fade" id="dietary-reports" role="tabpanel">
  210. <h5 class="mt-2">Animal Dietary Balance Records</h5>
  211. <table class="table table-hover table-sm">
  212. <thead class="table-dark">
  213. <tr>
  214. <th>Lab No</th><th>Sample ID</th><th>Site ID</th>
  215. <th>Date Sampled</th><th class="text-end">Actions</th>
  216. </tr>
  217. </thead>
  218. <tbody>
  219. <?php if (empty($animalRows)): ?>
  220. <tr><td colspan="5" class="text-center text-muted">No records found.</td></tr>
  221. <?php else: foreach ($animalRows as $r): ?>
  222. <tr>
  223. <td><?= $h($r['lab_no']) ?></td>
  224. <td><?= $h($r['sample_id']) ?></td>
  225. <td><?= $h($r['site_id']) ?></td>
  226. <td><?= $h($r['date_sampled']) ?></td>
  227. <td class="text-end">
  228. <a href="/dashboard/crop-analysis/animal-dietary-balance/animal-dietary-balance.php?rid=<?= (int)$r['id'] ?>&rand=<?= (float)$r['rand'] ?>"
  229. class="btn btn-sm btn-outline-success">View</a>
  230. </td>
  231. </tr>
  232. <?php endforeach; endif; ?>
  233. </tbody>
  234. </table>
  235. </div>
  236. <!-- Compost -->
  237. <div class="tab-pane fade" id="compost-reports" role="tabpanel">
  238. <h5 class="mt-2">Compost Test Records</h5>
  239. <p class="text-muted">Compost records pending migration.</p>
  240. </div>
  241. </div>
  242. </div>
  243. </div>
  244. </main>
  245. <?php include __DIR__ . '/../layouts/footer.php'; ?>
  246. </div>
  247. </div>