| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- <?php
- /**
- * dashboard/crop-analysis/plant-test-data/plant-analysis.php
- *
- * Plant tissue analysis results display page.
- */
- require_once __DIR__ . '/../../../config/database.php';
- require_once __DIR__ . '/../../../lib/auth.php';
- require_once __DIR__ . '/../../../lib/print_auth.php';
- if (session_status() === PHP_SESSION_NONE) {
- session_start();
- }
- $recordId = (int) ($_GET['rid'] ?? 0);
- $randId = trim( $_GET['rand'] ?? '');
- $clientId = (int) ($_GET['cid'] ?? 0);
- $printMode = isset($_GET['print']) || isset($_GET['ptoken']);
- if ($printMode) {
- authenticatePrintPage($recordId, $randId);
- } else {
- requireLogin();
- }
- $pdo = getDBConnection();
- $userId = $printMode ? null : getCurrentUserId();
- $row = null;
- $specs = [];
- if ($recordId > 0 && $randId !== '') {
- $stmt = $pdo->prepare('SELECT * FROM plant_records WHERE id = ? AND rand = ? LIMIT 1');
- $stmt->execute([$recordId, $randId]);
- $row = $stmt->fetch(PDO::FETCH_ASSOC);
- }
- if ($row) {
- // Column is plant_type, not crop
- $plantType = $row['crop_type'] ?? '';
- if ($plantType !== '') {
- $stmtSpec = $pdo->prepare('SELECT * FROM plant_specifications WHERE plant_type = ? LIMIT 1');
- $stmtSpec->execute([$plantType]);
- $specs = $stmtSpec->fetch(PDO::FETCH_ASSOC) ?: [];
- }
- }
- // ── Spec column name map ──────────────────────────────────────────────────────
- // The plant_specifications table has inconsistent column casing — map each
- // element key to its actual min/max column names in the DB.
- $specCols = [
- 'n' => ['n_min', 'n_max'],
- 'p' => ['P_Min', 'P_Max'],
- 'k' => ['K_Min', 'K_Max'],
- 's' => ['S_Min', 'S_Max'],
- 'mg' => ['Mg_Min', 'Mg_Max'],
- 'ca' => ['Ca_Min', 'Ca_Max'],
- 'na' => ['Na_Min', 'Na_Max'],
- 'fe' => ['Fe_Min', 'Fe_Max'],
- 'mn' => ['Mn_Min', 'Mn_Max'],
- 'zn' => ['Zn_Min', 'Zn_Max'],
- 'cu' => ['Cu_Min', 'Cu_Max'],
- 'b' => ['B_Min', 'B_Max'],
- 'm' => ['M_Min', 'M_Max'],
- 'co' => ['Co_min', 'Co_max'],
- 'se' => ['se_min', 'se_max'],
- 'cl' => ['cl_min', 'cl_max'],
- 'c' => ['c_min', 'c_max'],
- ];
- $h = fn($v) => htmlspecialchars((string)($v ?? ''), ENT_QUOTES, 'UTF-8');
- function statusBar(float $found, float $min, float $max): string {
- if ($max <= 0) return '<td colspan="3" class="text-muted text-center small">N/A</td>';
- if ($found < $min) {
- return '<td class="text-center"><div class="progress"><div class="progress-bar bg-danger" style="width:100%"></div></div></td><td></td><td></td>';
- }
- if ($found > $max) {
- return '<td></td><td></td><td class="text-center"><div class="progress"><div class="progress-bar bg-warning" style="width:100%"></div></div></td>';
- }
- $pct = ($max > $min) ? round(min(100, ($found - $min) / ($max - $min) * 100)) : 50;
- return '<td></td><td class="text-center"><div class="progress"><div class="progress-bar bg-success" style="width:' . $pct . '%"></div></div></td><td></td>';
- }
- $today = date('jS F Y');
- $pageTitle = 'Plant Analysis' . (!empty($row['client_name']) ? ' — ' . $row['client_name'] : '');
- $siteName = 'Crop Monitor';
- if (!$printMode) {
- include __DIR__ . '/../../../layouts/header.php';
- }
- ?>
- <link rel="stylesheet" href="/client-assets/home/css/graphPrint.css" media="print">
- <style>
- @media print {
- @page {
- size: A4 portrait;
- }
- @page :left {
- margin-left: 0.5cm;
- }
- @page :right {
- margin-right: 0.5cm;
- }
- @page :top {
- margin-top: 0cm;
- }
- @page :bottom {
- margin-bottom: 0cm;
- }
- body {
- min-width: 992px !important;
- }
- .container {
- min-width: 992px !important;
- }
- }
- .progress { border-radius: 0 !important; }
- .lightgreen { background: #d4edda !important; color: #155724 !important; }
- .lightred { background: #f8d7da !important; color: #721c24 !important; }
- .lightpurple { background: #e2d9f3 !important; color: #432874 !important; }
- .stripe-1 { background: #f8f9fa; }
- .border-left { border-left: 1px solid #dee2e6; }
- .border-right { border-right: 1px solid #dee2e6; }
- .border-bottom { border-bottom: 1px solid #dee2e6; }
- .border-top { border-top: 1px solid #dee2e6; }
- </style>
- <div class="container" id="content">
- <?php if (!$row): ?>
- <div class="alert alert-danger mt-4">Record not found or access denied.</div>
- <?php else: ?>
- <!-- ── Header ──────────────────────────────────────────────────────────── -->
- <div class="row mb-2">
- <div class="col-md-3">
- <img class="img-fluid" src="/client-assets/images/crop-monitor.png" alt="Crop Monitor">
- </div>
- </div>
- <table class="title w-100 mb-3 small">
- <tbody>
- <tr>
- <td class="text-end fw-bold text-nowrap">DATE:</td>
- <td><?= $h($today) ?></td>
- <td></td>
- <td class="text-end fw-bold text-nowrap">SAMPLE ID:</td>
- <td><?= $h($row['site_id']) ?></td>
- </tr>
- <tr>
- <td class="text-end fw-bold text-nowrap">CLIENT:</td>
- <td><?= $h($row['client_name']) ?></td>
- <td></td>
- <td class="text-end fw-bold text-nowrap">DATE SAMPLED:</td>
- <td><?= $h($row['date_sampled']) ?></td>
- </tr>
- <tr>
- <td class="text-end fw-bold text-nowrap">ADDRESS:</td>
- <td><?= $h($row['site_address']) ?></td>
- <td></td>
- <td class="text-end fw-bold text-nowrap">LAB NUMBER:</td>
- <td><?= $h($row['lab_no']) ?></td>
- </tr>
- <tr>
- <td></td>
- <td><?= $h($row['state_postcode']) ?></td>
- <td></td>
- <td class="text-end fw-bold text-nowrap">CROP TYPE:</td>
- <td><?= $h($row['crop_type']) ?></td>
- </tr>
- </tbody>
- </table>
- <!-- ── Action buttons ──────────────────────────────────────────────────── -->
- <?php if (!$printMode): ?>
- <div class="d-print-none mb-3 d-flex gap-2 flex-wrap">
- <a href="/dashboard/crop-analysis/plant-test-data/plant-report.php?rid=<?= $recordId ?>&rand=<?= urlencode($randId) ?>&cid=<?= $clientId ?>"
- class="btn btn-outline-primary btn-sm">
- <i class="fas fa-file-alt me-1"></i>View Report
- </a>
- <a href="/pdf-files/headlessChrome_pdf.php?type=plant-analysis&rid=<?= $recordId ?>&rand=<?= urlencode($randId) ?>&cid=<?= $clientId ?>"
- class="btn btn-outline-secondary btn-sm">
- <i class="fas fa-file-pdf me-1"></i>PDF — Analysis
- </a>
- <a href="/pdf-files/headlessChrome_pdf.php?type=plant&rid=<?= $recordId ?>&rand=<?= urlencode($randId) ?>&cid=<?= $clientId ?>"
- class="btn btn-success btn-sm">
- <i class="fas fa-file-pdf me-1"></i>PDF — Analysis & Report
- </a>
- </div>
- <?php endif; ?>
- <div class="row">
- <div class="col-md-12 text-center fw-bold h4">Plant Tissue Analysis Results</div>
- </div>
- <table class="chart">
- <tbody>
- <tr class="chart-header">
- <th colspan="3" class="text-center col-md-6 border-left border-right border-top">ELEMENT</th>
- <th colspan="3" class="text-center col-md-6 border-right border-top">STATUS</th>
- </tr>
- <tr class="chart-header-sub">
- <th class="text-center col-18 border-left"></th>
- <th class="text-center col-15">DESIRED</th>
- <th class="text-center col-15">FOUND</th>
- <th class="text-center col-16 stripe-1">Deficient</th>
- <th class="text-center col-16 stripe-1">Ideal</th>
- <th class="text-center col-16 border-right stripe-1">High</th>
- </tr>
- <tr>
- <td class="border-left"></td>
- <td class="border-left"></td>
- <td class="border-left"></td>
- <td class="border-left"></td>
- <td class="border-left"></td>
- <td class="border-left border-right"></td>
- </tr>
- <!-- Major Elements -->
- <tr class="chart-header-sub">
- <th colspan="6" class="border-left text-center lightgreen">MAJOR ELEMENTS (%)</th>
- </tr>
- <?php
- $majorElements = [
- ['n', 'Nitrogen', '%', 3],
- ['p', 'Phosphorus', '%', 3],
- ['k', 'Potassium', '%', 3],
- ['s', 'Sulfur', '%', 3],
- ['mg', 'Magnesium', '%', 3],
- ['ca', 'Calcium', '%', 3],
- ['na', 'Sodium', '%', 3],
- ];
- foreach ($majorElements as [$el, $nutrient, $unit, $dp]):
- $found = (float)($row[$el] ?? 0);
- [$minCol, $maxCol] = $specCols[$el];
- $min = (float)($specs[$minCol] ?? 0);
- $max = (float)($specs[$maxCol] ?? 0);
- $desired = ($min > 0 || $max > 0) ? number_format($min, $dp) . '–' . number_format($max, $dp) : '—';
- ?>
- <tr>
- <td class="border-left"><?= $h($nutrient) ?> (<?= $h($unit) ?>)</td>
- <td class="text-center"><?= $h($desired) ?></td>
- <td class="text-center"><?= $found > 0 ? number_format($found, $dp) : '—' ?></td>
- <?= statusBar($found, $min, $max) ?>
- </tr>
- <?php endforeach; ?>
- <tr><td colspan="6" class="border-left"></td></tr>
- <!-- Trace Elements -->
- <tr class="chart-header-sub">
- <th colspan="6" class="border-left text-center lightred">TRACE ELEMENTS (ppm)</th>
- </tr>
- <?php
- $traceElements = [
- ['fe', 'Iron', 'ppm', 1],
- ['mn', 'Manganese', 'ppm', 1],
- ['zn', 'Zinc', 'ppm', 1],
- ['cu', 'Copper', 'ppm', 1],
- ['b', 'Boron', 'ppm', 1],
- ];
- foreach ($traceElements as [$el, $nutrient, $unit, $dp]):
- $found = (float)($row[$el] ?? 0);
- [$minCol, $maxCol] = $specCols[$el];
- $min = (float)($specs[$minCol] ?? 0);
- $max = (float)($specs[$maxCol] ?? 0);
- $desired = ($min > 0 || $max > 0) ? number_format($min, $dp) . '–' . number_format($max, $dp) : '—';
- ?>
- <tr>
- <td class="border-left"><?= $h($nutrient) ?> (<?= $h($unit) ?>)</td>
- <td class="text-center"><?= $h($desired) ?></td>
- <td class="text-center"><?= $found > 0 ? number_format($found, $dp) : '—' ?></td>
- <?= statusBar($found, $min, $max) ?>
- </tr>
- <?php endforeach; ?>
- <tr><td colspan="6" class="border-left"></td></tr>
- <!-- Other Elements -->
- <tr class="chart-header-sub">
- <th colspan="6" class="border-left text-center lightpurple">OTHER ELEMENTS (ppm)</th>
- </tr>
- <?php
- $otherElements = [
- ['m', 'Molybdenum', 'ppm', 2],
- ['co', 'Cobalt', 'ppm', 2],
- ['se', 'Selenium', 'ppm', 2],
- ['cl', 'Chloride', 'ppm', 2],
- ['c', 'Carbon', '%', 2],
- ];
- foreach ($otherElements as [$el, $nutrient, $unit, $dp]):
- $found = (float)($row[$el] ?? 0);
- [$minCol, $maxCol] = $specCols[$el];
- $min = (float)($specs[$minCol] ?? 0);
- $max = (float)($specs[$maxCol] ?? 0);
- $desired = ($min > 0 || $max > 0) ? number_format($min, $dp) . '–' . number_format($max, $dp) : '—';
- ?>
- <tr>
- <td class="border-left"><?= $h($nutrient) ?> (<?= $h($unit) ?>)</td>
- <td class="text-center"><?= $h($desired) ?></td>
- <td class="text-center"><?= $found > 0 ? number_format($found, $dp) : '—' ?></td>
- <?= statusBar($found, $min, $max) ?>
- </tr>
- <?php endforeach; ?>
- <tr>
- <td class="border-bottom border-left"></td>
- <td class="border-bottom"></td>
- <td class="border-bottom"></td>
- <td class="border-bottom"></td>
- <td class="border-bottom"></td>
- <td class="border-bottom border-right"></td>
- </tr>
- </tbody>
- </table>
- <div class="mt-4 small text-muted">
- <p><i class="fa fa-leaf" style="color:green"></i> It is always an advantage to assess tissue analysis results along with a corresponding soil analysis for more accurate diagnosis of plant nutrient status.</p>
- <p><i class="fa fa-leaf" style="color:green"></i> Trace element levels — manganese, copper and zinc — can all be affected by fungicide spray residues, giving misleading results.</p>
- <p><i class="fa fa-leaf" style="color:green"></i> Talk to your qualified consultant to make a plan for correction or maintenance of the found nutrient levels.</p>
- <p class="fst-italic" style="font-size:9px;">Desired ranges indexed from: CSIRO Plant Analysis Handbook 2nd Ed. Hill Laboratories consultants guide. PIRSA Soil and Plant Analysis.</p>
- <p class="fst-italic" style="font-size:9px;">Any recommendations provided by Cropmonitor are advice only. We are not paid consultants and accept no responsibility for any of our suggestions.</p>
- </div>
- <?php endif; ?>
- </div><!-- /.container -->
|