soil-analysis.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. <?php
  2. /**
  3. * dashboard/crop-analysis/soil-test-data/soil-analysis.php
  4. *
  5. * Soil Analysis Results Display Page
  6. */
  7. require_once __DIR__.'/../../../config/database.php';
  8. require_once __DIR__.'/../../../lib/auth.php';
  9. require_once __DIR__.'/../../../lib/print_auth.php';
  10. require_once __DIR__.'/../../../lib/validation.php';
  11. require_once __DIR__.'/../../../lib/soil_calculations.php';
  12. if (session_status() === PHP_SESSION_NONE) {
  13. session_start();
  14. }
  15. $record_id = (int) ($_GET['rid'] ?? 0);
  16. $rand_id = trim( $_GET['rand'] ?? '');
  17. $client_id = (int) ($_GET['cid'] ?? 0);
  18. $print_mode = isset($_GET['print']);
  19. if ($print_mode) {
  20. authenticatePrintPage($record_id, $rand_id);
  21. } else {
  22. requireLogin();
  23. }
  24. if (!$record_id || $rand_id === '') {
  25. die('Invalid request parameters');
  26. }
  27. try {
  28. $pdo = getDBConnection();
  29. // Load soil record
  30. $stmt = $pdo->prepare("SELECT * FROM soil_records WHERE id = ? AND rand = ?");
  31. $stmt->execute([$record_id, $rand_id]);
  32. $row = $stmt->fetch(PDO::FETCH_ASSOC);
  33. if (!$row) {
  34. die('Soil record not found');
  35. }
  36. // Load matching specifications row for this soil type
  37. $spec = [];
  38. if (!empty($row['soil_type'])) {
  39. $stmtSpec = $pdo->prepare("SELECT * FROM soil_specifications WHERE soil_type = ? LIMIT 1");
  40. $stmtSpec->execute([$row['soil_type']]);
  41. $spec = $stmtSpec->fetch(PDO::FETCH_ASSOC) ?: [];
  42. }
  43. } catch (PDOException $e) {
  44. error_log("Database error in soil-analysis.php: " . $e->getMessage());
  45. die('Database error occurred');
  46. }
  47. // ── Page setup ─────────────────────────────────────────────────────────────
  48. $client = htmlspecialchars($row['client_name'] ?? '', ENT_QUOTES, 'UTF-8');
  49. $address = htmlspecialchars($row['site_address'] ?? '', ENT_QUOTES, 'UTF-8');
  50. $state = htmlspecialchars($row['state_postcode'] ?? '', ENT_QUOTES, 'UTF-8');
  51. $email = htmlspecialchars($row['email'] ?? '', ENT_QUOTES, 'UTF-8');
  52. $labNo = htmlspecialchars($row['lab_no'] ?? '', ENT_QUOTES, 'UTF-8');
  53. $sampleDate = htmlspecialchars($row['date_sampled'] ?? '', ENT_QUOTES, 'UTF-8');
  54. $sample = htmlspecialchars($row['site_id'] ?? '', ENT_QUOTES, 'UTF-8');
  55. $crop = htmlspecialchars($row['sample_id'] ?? '', ENT_QUOTES, 'UTF-8');
  56. $today = date('jS F Y');
  57. $pageTitle = 'Soil Analysis Results' . ($client !== '' ? ' - ' . $client : '');
  58. include __DIR__.'/../../../layouts/header.php';
  59. ?>
  60. <link rel="stylesheet" href="/client-assets/home/css/graphPrint.css" media="print">
  61. <style>
  62. .progress { border-radius: 0 !important; }
  63. @media print {
  64. .section + .section {
  65. break-before: page;
  66. page-break-before: always;
  67. }
  68. }
  69. </style>
  70. <div class="container" id="content">
  71. <div class="row align-items-center mb-1 mt-3">
  72. <div class="col-3">
  73. <img class="img-fluid" src="/client-assets/images/crop-monitor.png" alt="Crop Monitor" style="max-height:55px;">
  74. </div>
  75. <div class="col-9 text-end">
  76. <div class="fw-bold h5 mb-0">Soil Analysis</div>
  77. <div class="text-muted small"></div>
  78. </div>
  79. </div>
  80. <table class="title w-100 mb-3 small">
  81. <tbody>
  82. <tr>
  83. <th class="col-20"></th><th class="col-20"></th><th class="col-20"></th>
  84. <th class="col-20"></th><th class="col-20"></th>
  85. </tr>
  86. <tr>
  87. <td class="right"><b>DATE:</b></td>
  88. <td class="left"><?= $today ?></td>
  89. <td></td>
  90. <td class="right"><b>SAMPLE ID:</b></td>
  91. <td class="left"><?= $sample ?></td>
  92. </tr>
  93. <tr>
  94. <td class="right"><b>CLIENT:</b></td>
  95. <td class="left"><?= $client ?></td>
  96. <td></td>
  97. <td class="right"><b>DATE SAMPLED:</b></td>
  98. <td class="left"><?= $sampleDate ?></td>
  99. </tr>
  100. <tr>
  101. <td class="right"><b>ADDRESS:</b></td>
  102. <td class="left"><?= $address ?></td>
  103. <td></td>
  104. <td class="right"><b>LAB NUMBER:</b></td>
  105. <td class="left"><?= $labNo ?></td>
  106. </tr>
  107. <tr>
  108. <td class="right"></td>
  109. <td class="left"><?= $state ?></td>
  110. <td></td>
  111. <td class="right"><b>CROP:</b></td>
  112. <td class="left"><?= $crop ?></td>
  113. </tr>
  114. <tr>
  115. <td class="right"></td>
  116. <td class="left"><?= $email ?></td>
  117. <td></td><td></td><td></td>
  118. </tr>
  119. </tbody>
  120. </table>
  121. <?php if (!$print_mode): ?>
  122. <div class="d-print-none">
  123. <div class="row p-2 align-items-center">
  124. <div class="col d-flex gap-2 flex-wrap">
  125. <a href="/dashboard/crop-analysis/soil-test-data/soil-report.php?rid=<?= (int)$record_id ?>&rand=<?= urlencode((string)$rand_id) ?>&cid=<?= (int)$client_id ?>"
  126. class="btn btn-outline-primary btn-sm">
  127. <i class="fas fa-file-alt me-1"></i>View Report
  128. </a>
  129. <a href="/pdf-files/headlessChrome_pdf.php?type=soil-analysis&rid=<?= (int)$record_id ?>&rand=<?= urlencode((string)$rand_id) ?>&cid=<?= (int)$client_id ?>"
  130. class="btn btn-outline-secondary btn-sm">
  131. <i class="fas fa-file-pdf me-1"></i>PDF — Analysis
  132. </a>
  133. <a href="/pdf-files/headlessChrome_pdf.php?type=soil&rid=<?= (int)$record_id ?>&rand=<?= urlencode((string)$rand_id) ?>&cid=<?= (int)$client_id ?>"
  134. class="btn btn-success btn-sm">
  135. <i class="fas fa-file-pdf me-1"></i>PDF — Analysis &amp; Report
  136. </a>
  137. </div>
  138. <div class="col-auto">
  139. <div class="form-status-holder small text-muted"></div>
  140. </div>
  141. </div>
  142. </div>
  143. <?php endif; ?>
  144. <div class="row">
  145. <div class="col-md-12 text-center fw-bold h4">Soil Analysis Summary</div>
  146. </div>
  147. <div class="section" id="page-1">
  148. <table class="chart mb-0">
  149. <tbody>
  150. <!-- ── CHART HEADER ──────────────────────────────────────────── -->
  151. <tr class="chart-header">
  152. <th colspan="3" class="text-center col-md-6 border-left border-right border-top">ELEMENT</th>
  153. <th colspan="3" class="text-center col-md-6 border-right border-top">STATUS</th>
  154. </tr>
  155. <tr class="chart-header-sub">
  156. <th class="text-center col-18 border-left"></th>
  157. <th class="text-center col-15">DESIRED</th>
  158. <th class="text-center col-15">FOUND</th>
  159. <th class="text-center col-16 stripe-1">LIGHT</th>
  160. <th class="text-center col-16 stripe-1">MEDIUM</th>
  161. <th class="text-center col-16 border-right stripe-1">HEAVY</th>
  162. </tr>
  163. <tr>
  164. <td class="border-left"></td>
  165. <td class="border-left"></td>
  166. <td class="border-left nutrient-balance"></td>
  167. <td class="border-left"></td>
  168. <td class="border-left"></td>
  169. <td class="border-left border-right"></td>
  170. </tr>
  171. <?php
  172. soilRow($row, $spec, ['element'=>'cec', 'nutrient'=>'CEC', 'recV'=>'n', 'decimal'=>2, 'graph'=>'lightorangeGraph']);
  173. soilRow($row, $spec, ['element'=>'tec', 'nutrient'=>'TEC', 'max'=>'soil_type', 'recV'=>'max', 'rec_text'=>'c', 'decimal'=>2, 'graph'=>'lightorangeGraph']);
  174. ?>
  175. <tr class="chart-header-sub">
  176. <th class="text-center col-18 border-left text-dark bg-white"></th>
  177. <th class="text-center col-15 border-left text-dark bg-white"></th>
  178. <th class="text-center col-15 border-left nutrient-balance"></th>
  179. <th class="text-center col-16 border-left stripe-1">DEFICIT</th>
  180. <th class="text-center col-16 stripe-1">IDEAL</th>
  181. <th class="text-center col-16 border-right stripe-1">HIGH</th>
  182. </tr>
  183. <?php
  184. soilRow($row, $spec, ['element'=>'ph_h2o', 'nutrient'=>'pH-level (H20)', 'type'=>'pH', 'recV'=>'ph', 'decimal'=>1, 'graph'=>'lightorangeGraph']);
  185. soilRow($row, $spec, ['element'=>'ph_cacl2', 'nutrient'=>'pH-level (CaCl2)', 'type'=>'pH', 'recV'=>'n', 'decimal'=>1, 'graph'=>'lightorangeGraph']);
  186. soilRow($row, $spec, ['element'=>'ec', 'nutrient'=>'Conductivity (EC)','type'=>'mS/cm', 'decimal'=>2, 'graph'=>'lightorangeGraph']);
  187. soilRow($row, $spec, ['element'=>'ocarbon', 'nutrient'=>'Organic Carbon', 'type'=>'%', 'decimal'=>1, 'graph'=>'lightorangeGraph']);
  188. soilRow($row, $spec, ['element'=>'omatter', 'nutrient'=>'Organic Matter', 'type'=>'%', 'decimal'=>1, 'graph'=>'lightorangeGraph']);
  189. ?>
  190. <!-- ── MAJOR ELEMENTS ─────────────────────────────────────────── -->
  191. <tr class="chart-header-sub">
  192. <th colspan="3" class="col-16 border-left text-center lightgreen">MAJOR ELEMENTS</th>
  193. <th class="text-center col-16 stripe-1"></th>
  194. <th class="text-center col-16 stripe-1"></th>
  195. <th class="text-center col-16 border-right stripe-1"></th>
  196. </tr>
  197. <?php
  198. soilRow($row, $spec, ['element'=>'NO3_N', 'sbl'=>'NO<sub>3</sub>-N', 'nutrient'=>'Nitrate <small class="d-print-none">Nitrogen</small>', 'min'=>'10', 'max'=>'20', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreenGraph']);
  199. soilRow($row, $spec, ['element'=>'NH3_N', 'sbl'=>'NH<sub>3</sub>-N', 'nutrient'=>'Ammonium <small class="d-print-none">Nitrogen</small>', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreenGraph']);
  200. // p_mehlick, p_bray2, p_morgan excluded (commented in original)
  201. soilRow($row, $spec, ['element'=>'p_colwell', 'sbl'=>'P', 'nutrient'=>'Phosphate <small>(colwell)</small>', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreenGraph']);
  202. soilRow($row, $spec, ['element'=>'BS_ca_ppm', 'sbl'=>'Ca', 'nutrient'=>'Calcium', 'min'=>'ca_ppm_min', 'max'=>'ca_ppm_max', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>0, 'graph'=>'lightgreenGraph']);
  203. soilRow($row, $spec, ['element'=>'BS_mg_ppm', 'sbl'=>'Mg', 'nutrient'=>'Magnesium', 'min'=>'mg_ppm_min', 'max'=>'mg_ppm_max', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>0, 'graph'=>'lightgreenGraph']);
  204. soilRow($row, $spec, ['element'=>'BS_k_ppm', 'sbl'=>'K', 'nutrient'=>'Potassium', 'min'=>'k_ppm_min', 'max'=>'k_ppm_max', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>0, 'graph'=>'lightgreenGraph']);
  205. soilRow($row, $spec, ['element'=>'BS_na_ppm', 'sbl'=>'Na', 'nutrient'=>'Sodium', 'min'=>'na_ppm_min', 'max'=>'na_ppm_max', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>0, 'graph'=>'lightgreenGraph']);
  206. ?>
  207. <!-- ── TRACE ELEMENTS ─────────────────────────────────────────── -->
  208. <tr class="chart-header-sub">
  209. <th colspan="3" class="col-16 border-left text-center lightred">TRACE ELEMENTS</th>
  210. <th class="text-center col-16 stripe-1"></th>
  211. <th class="text-center col-16 stripe-1"></th>
  212. <th class="text-center col-16 border-right stripe-1"></th>
  213. </tr>
  214. <?php
  215. soilRow($row, $spec, ['element'=>'s_morgan', 'sbl'=>'S', 'nutrient'=>'Sulfur', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']);
  216. soilRow($row, $spec, ['element'=>'b_cacl2', 'sbl'=>'B', 'nutrient'=>'Boron', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']);
  217. soilRow($row, $spec, ['element'=>'mn_dtpa', 'sbl'=>'Mn', 'nutrient'=>'Manganese', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']);
  218. soilRow($row, $spec, ['element'=>'cu_dtpa', 'sbl'=>'Cu', 'nutrient'=>'Copper', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']);
  219. soilRow($row, $spec, ['element'=>'zn_dtpa', 'sbl'=>'Zn', 'nutrient'=>'Zinc', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']);
  220. soilRow($row, $spec, ['element'=>'fe_dtpa', 'sbl'=>'Fe', 'nutrient'=>'Iron', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']);
  221. soilRow($row, $spec, ['element'=>'al', 'sbl'=>'Al', 'nutrient'=>'Aluminium', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']);
  222. soilRow($row, $spec, ['element'=>'sl_cacl2', 'sbl'=>'Si', 'nutrient'=>'Silicon', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']);
  223. ?>
  224. </tbody>
  225. </table>
  226. </div>
  227. <div class="section" id="page-2">
  228. <div class="row">
  229. <table class="title w-100 mb-3 small">
  230. <tbody>
  231. <tr>
  232. <th class="col-20"></th>
  233. <th class="col-20"></th>
  234. <th class="col-20"></th>
  235. <th class="col-20"></th>
  236. </tr>
  237. <tr>
  238. <td class="right"><b>DATE SAMPLED:</b></td>
  239. <td class="left"><?= $sampleDate ?></td>
  240. <td class="right"><b>CROP:</b></td>
  241. <td class="left"><?= $crop ?></td>
  242. </tr>
  243. </tbody>
  244. </table>
  245. </div>
  246. <table class="chart mb-0">
  247. <tbody>
  248. <!-- ── CHART HEADER ──────────────────────────────────────────── -->
  249. <tr class="chart-header">
  250. <th colspan="3" class="text-center col-md-6 border-left border-right border-top">ELEMENT</th>
  251. <th colspan="3" class="text-center col-md-6 border-right border-top">STATUS</th>
  252. </tr>
  253. <tr class="chart-header-sub">
  254. <th class="text-center col-18 border-left"></th>
  255. <th class="text-center col-15">DESIRED</th>
  256. <th class="text-center col-15">FOUND</th>
  257. <th class="text-center col-16 stripe-1">LIGHT</th>
  258. <th class="text-center col-16 stripe-1">MEDIUM</th>
  259. <th class="text-center col-16 border-right stripe-1">HEAVY</th>
  260. </tr>
  261. <tr>
  262. <td class="border-left"></td>
  263. <td class="border-left"></td>
  264. <td class="border-left nutrient-balance"></td>
  265. <td class="border-left"></td>
  266. <td class="border-left"></td>
  267. <td class="border-left border-right"></td>
  268. </tr>
  269. <!-- ── BASE SATURATION ────────────────────────────────────────── -->
  270. <tr class="chart-header-sub">
  271. <th colspan="3" class="col-16 border-left text-center lightpurple">BASE SATURATION</th>
  272. <th class="text-center col-16 stripe-1"></th>
  273. <th class="text-center col-16 stripe-1"></th>
  274. <th class="text-center col-16 border-right stripe-1"></th>
  275. </tr>
  276. <?php
  277. soilRow($row, $spec, ['element'=>'BS_ca2', 'sbl'=>'Ca', 'nutrient'=>'Calcium', 'min'=>'cabs_min', 'max'=>'cabs_max', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>2, 'graph'=>'lightpurpleGraph']);
  278. soilRow($row, $spec, ['element'=>'BS_mg2', 'sbl'=>'Mg', 'nutrient'=>'Magnesium', 'min'=>'mgbs_min', 'max'=>'mgbs_max', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>2, 'graph'=>'lightpurpleGraph']);
  279. soilRow($row, $spec, ['element'=>'BS_k', 'sbl'=>'K', 'nutrient'=>'Potassium', 'min'=>'kbs_min', 'max'=>'kbs_max', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>2, 'graph'=>'lightpurpleGraph']);
  280. soilRow($row, $spec, ['element'=>'BS_na', 'sbl'=>'Na', 'nutrient'=>'Sodium', 'min'=>'nabs_min', 'max'=>'nabs_max', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>2, 'graph'=>'lightpurpleGraph']);
  281. soilRow($row, $spec, ['element'=>'BS_ob', 'nutrient'=>'Other Bases', 'max'=>'ob_rec', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>2, 'graph'=>'lightpurpleGraph']);
  282. soilRow($row, $spec, ['element'=>'BS_h', 'nutrient'=>'Hydrogen', 'max'=>'h_rec', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>2, 'graph'=>'lightpurpleGraph']);
  283. ?>
  284. <!-- ── SOLUBLE MORGAN 2 EXTRACT ───────────────────────────────── -->
  285. <tr class="chart-header-sub">
  286. <th colspan="3" class="col-16 border-left text-center lightgrey">SOLUBLE MORGAN 2 EXTRACT</th>
  287. <th class="text-center col-16 stripe-1"></th>
  288. <th class="text-center col-16 stripe-1"></th>
  289. <th class="text-center col-16 border-right stripe-1"></th>
  290. </tr>
  291. <?php
  292. soilRow($row, $spec, ['element'=>'s_morgan', 'sbl'=>'Ca', 'nutrient'=>'Calcium', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreyGraph']);
  293. soilRow($row, $spec, ['element'=>'b_cacl2', 'sbl'=>'Mg', 'nutrient'=>'Magnesium', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreyGraph']);
  294. soilRow($row, $spec, ['element'=>'mn_dtpa', 'sbl'=>'K', 'nutrient'=>'Potassium', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreyGraph']);
  295. ?>
  296. <!-- ── ADDITIONAL DATA ────────────────────────────────────────── -->
  297. <tr class="chart-header-sub">
  298. <th colspan="3" class="col-16 border-left text-center lightgrey">ADDITIONAL DATA</th>
  299. <th class="text-center col-16 stripe-1">LOW</th>
  300. <th class="text-center col-16 stripe-1">IDEAL</th>
  301. <th class="text-center col-16 border-right stripe-1">EXCELLENT</th>
  302. </tr>
  303. <?php
  304. soilRow($row, $spec, ['element'=>'s_morgan', 'sbl'=>'Ca', 'nutrient'=>'Calcium', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreyGraph']);
  305. ?>
  306. <!-- ── RATIOS ─────────────────────────────────────────────────── -->
  307. <tr class="chart-header-sub">
  308. <th colspan="3" class="col-16 border-left text-center lightblue">RATIOS</th>
  309. <th class="text-center col-16 stripe-1"></th>
  310. <th class="text-center col-16 stripe-1"></th>
  311. <th class="text-center col-16 border-right stripe-1"></th>
  312. </tr>
  313. <?php
  314. soilRatio($row, $spec, ['element'=>'ca_mehlick3', 'elementTwo'=>'mg_mehlick3', 'rec'=>'ca_mg_ratio', 'nutrient'=>'Ca:Mg Ratio', 'rec_text'=>'r', 'decimal'=>1, 'graph'=>'lightblueGraph']);
  315. soilRow ($row, $spec, ['element'=>'NH3_N', 'nutrient'=>'Total Nitrogen', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>1, 'graph'=>'lightblueGraph']);
  316. soilRow ($row, $spec, ['element'=>'ocarbon', 'nutrient'=>'Total Carbon', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>1, 'graph'=>'lightblueGraph']);
  317. soilRatio($row, $spec, ['element'=>'ocarbon', 'elementTwo'=>'NO3_N', 'rec'=>'c_n_ratio', 'nutrient'=>'C:N Ratio', 'type'=>':1', 'rec_text'=>'r', 'decimal'=>1, 'graph'=>'lightblueGraph']);
  318. ?>
  319. <tr>
  320. <td class="border-bottom border-left"></td>
  321. <td class="border-bottom border-left"></td>
  322. <td class="border-bottom border-left nutrient-balance"></td>
  323. <td class="border-bottom border-left"></td>
  324. <td class="border-bottom border-left"></td>
  325. <td class="border-bottom border-left border-right"></td>
  326. </tr>
  327. </tbody>
  328. </table>
  329. <footer class="py-4 mt-auto mb-0">
  330. <div class="container-fluid px-4">
  331. <div class="d-flex align-items-center justify-content-between small">
  332. <div class="text-muted">&copy; <?= date('Y') ?> Crop Management Platform. All Rights Reserved.</div>
  333. </div>
  334. </div>
  335. </footer>
  336. </div><!-- /.container -->
  337. <script>
  338. (function () {
  339. // Set #page-1 height to exactly one A4 page so the print break falls cleanly.
  340. // A4 at 96 dpi = 1122px tall; subtract ~60px for the container top margin/padding.
  341. var A4_PX = 1300;
  342. var OFFSET = 60;
  343. var page1 = document.getElementById('page-1');
  344. if (page1) {
  345. page1.style.minHeight = (A4_PX - OFFSET) + 'px';
  346. page1.style.overflow = 'hidden';
  347. }
  348. })();
  349. </script>
  350. <script>
  351. $(document).ready(function () {
  352. var timeoutId;
  353. $('form textarea, form input').on('input propertychange change', function () {
  354. clearTimeout(timeoutId);
  355. timeoutId = setTimeout(saveToDB, 1000);
  356. });
  357. function saveToDB() {
  358. var form = $('.report-form');
  359. $.ajax({
  360. url: '/controllers/save_soil_analysis.php',
  361. type: 'POST',
  362. data: form.serialize(),
  363. beforeSend: function () { $('.form-status-holder').html('Saving...'); },
  364. success: function () {
  365. var d = new Date();
  366. $('.form-status-holder').html('Saved! Last: ' + d.toLocaleTimeString());
  367. }
  368. });
  369. }
  370. $('.report-form').submit(function (e) {
  371. saveToDB();
  372. e.preventDefault();
  373. });
  374. });
  375. </script>