| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- <?php
- /**
- * dashboard/crop-analysis/coverpage.php
- *
- * Printable cover page for any analysis report type.
- *
- * Query params:
- * type — soil | plant | water | animal | compost
- * rid — record id
- * rand — auth token
- * cid — client_records.id (optional)
- */
- 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();
- $type = trim($_GET['type'] ?? 'soil');
- $recordId = (int) ($_GET['rid'] ?? 0);
- $randId = trim( $_GET['rand'] ?? '');
- $clientId = (int) ($_GET['cid'] ?? 0);
- $printMode = isset($_GET['print']);
- $allowedTypes = ['soil', 'plant', 'water', 'animal', 'compost'];
- if (!in_array($type, $allowedTypes, true)) {
- http_response_code(400);
- die('Invalid type');
- }
- if (!$recordId || $randId === '') {
- http_response_code(400);
- die('Invalid request parameters');
- }
- if ($printMode) {
- authenticatePrintPage($recordId, $randId);
- } else {
- requireLogin();
- }
- // ── Fetch record from the appropriate table ─────────────────────────────────
- $tableMap = [
- 'soil' => 'soil_records',
- 'plant' => 'plant_records',
- 'water' => 'water_records',
- 'animal' => 'animal_records',
- 'compost' => 'soil_records', // compost uses soil_records with analysis_type
- ];
- try {
- $pdo = getDBConnection();
- $table = $tableMap[$type];
- $stmt = $pdo->prepare("SELECT * FROM {$table} WHERE id = ? AND rand = ?");
- $stmt->execute([$recordId, $randId]);
- $row = $stmt->fetch(PDO::FETCH_ASSOC);
- if (!$row) {
- http_response_code(404);
- die('Record not found');
- }
- } catch (PDOException $e) {
- error_log('DB error in coverpage.php: ' . $e->getMessage());
- die('Database error');
- }
- $h = fn($v) => htmlspecialchars((string)($v ?? ''), ENT_QUOTES, 'UTF-8');
- // ── Common fields (shared column names across all tables) ───────────────────
- $clientName = $h($row['client_name'] ?? '');
- $siteAddress = $h($row['site_address'] ?? '');
- $statePost = $h($row['state_postcode'] ?? '');
- $email = $h($row['email'] ?? '');
- $labNo = $h($row['lab_no'] ?? '');
- $batchNo = $h($row['batch_no'] ?? '');
- $sampleId = $h($row['sample_id'] ?? '');
- $siteId = $h($row['site_id'] ?? '');
- $dateSampled = $h($row['date_sampled'] ?? '');
- $analysisType = $h($row['analysis_type'] ?? '');
- // Type-specific fields
- $subjectLine = '';
- if ($type === 'soil' || $type === 'compost') {
- $subjectLine = $h($row['crop_type'] ?? $row['soil_type'] ?? '');
- } elseif ($type === 'plant') {
- $subjectLine = $h($row['crop_type'] ?? '');
- } elseif ($type === 'water') {
- $subjectLine = $h($row['water_source'] ?? $row['analysis_type'] ?? '');
- } elseif ($type === 'animal') {
- $subjectLine = $h($row['animal'] ?? $row['analysis_type'] ?? '');
- }
- // Report type label and accent colour
- $typeConfig = [
- 'soil' => ['label' => 'Soil Analysis', 'accent' => '#4a7c4e', 'bg' => 'Vineyard-Soil.jpg'],
- 'plant' => ['label' => 'Plant Tissue Analysis', 'accent' => '#2e6b3e', 'bg' => 'grass.jpg'],
- 'water' => ['label' => 'Water Analysis', 'accent' => '#1a5f8a', 'bg' => 'irrigation-water.jpg'],
- 'animal' => ['label' => 'Animal Dietary Balance', 'accent' => '#7a5230', 'bg' => 'grass.jpg'],
- 'compost' => ['label' => 'Compost Analysis', 'accent' => '#5a4a1e', 'bg' => 'Vineyard-Soil.jpg'],
- ];
- $cfg = $typeConfig[$type];
- $label = $cfg['label'];
- $accent = $cfg['accent'];
- $bgImg = '/client-assets/images/' . $cfg['bg'];
- $today = date('jS F Y');
- ?>
- <!doctype html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title><?= $label ?><?= $clientName !== '' ? ' — ' . $clientName : '' ?></title>
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
- <style>
- * { margin: 0; padding: 0; box-sizing: border-box; }
- html, body {
- width: 100%;
- min-width: 1030px;
- height: 100%;
- font-family: 'Segoe UI', Arial, sans-serif;
- background: #fff;
- color: #1a1a1a;
- }
- /* ── Full-page cover layout ── */
- .cover {
- position: relative;
- width: 100%;
- min-width: 1030px;
- /* A4 aspect ratio at the 1030px combined viewport: 1030 * (297/210) = 1457px */
- height: calc(100vw * 297 / 210);
- min-height: 1457px;
- display: flex;
- flex-direction: column;
- }
- /* ── Top photo banner ── */
- .cover-photo {
- flex: 1;
- background: url('<?= $bgImg ?>') center center / cover no-repeat;
- position: relative;
- }
- .cover-photo::after {
- content: '';
- position: absolute;
- inset: 0;
- background: linear-gradient(
- to bottom,
- rgba(0,0,0,0.08) 0%,
- rgba(0,0,0,0.35) 100%
- );
- }
- /* ── Accent stripe ── */
- .accent-stripe {
- height: 8px;
- background: <?= $accent ?>;
- }
- /* ── Bottom info panel ── */
- .cover-footer {
- background: #fff;
- padding: 28px 36px 32px;
- display: flex;
- align-items: flex-end;
- justify-content: space-between;
- gap: 24px;
- min-height: 148mm;
- }
- /* ── Logo + report type (left) ── */
- .cover-left {
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- height: 100%;
- flex: 1;
- }
- .cover-logo {
- height: auto;
- width: 50%;
- }
- .cover-type-label {
- font-size: 11px;
- font-weight: 600;
- letter-spacing: 0.18em;
- text-transform: uppercase;
- color: <?= $accent ?>;
- margin-bottom: 6px;
- }
- .cover-report-title {
- font-size: 28px;
- font-weight: 700;
- line-height: 1.15;
- color: #1a1a1a;
- border-left: 4px solid <?= $accent ?>;
- padding-left: 14px;
- }
- .cover-date {
- font-size: 11px;
- color: #888;
- margin-top: 10px;
- padding-left: 18px;
- }
- /* ── Client details (right) ── */
- .cover-client {
- text-align: right;
- min-width: 200px;
- max-width: 240px;
- flex-shrink: 0;
- }
- .cover-client-name {
- font-size: 17px;
- font-weight: 700;
- color: #1a1a1a;
- margin-bottom: 10px;
- line-height: 1.2;
- }
- .detail-row {
- display: flex;
- justify-content: flex-end;
- align-items: baseline;
- gap: 8px;
- margin-bottom: 4px;
- font-size: 11px;
- }
- .detail-label {
- color: #999;
- font-weight: 600;
- letter-spacing: 0.06em;
- text-transform: uppercase;
- white-space: nowrap;
- flex-shrink: 0;
- }
- .detail-value {
- color: #2a2a2a;
- font-weight: 500;
- }
- .detail-divider {
- border: none;
- border-top: 1px solid #e8e8e8;
- margin: 10px 0;
- }
- @media print {
- @page { size: A4 portrait; margin: 0; }
- }
- </style>
- </head>
- <body>
- <div class="cover">
- <!-- ── Photo banner ── -->
- <div class="cover-photo"></div>
- <!-- ── Accent stripe ── -->
- <div class="accent-stripe"></div>
- <!-- ── Footer info panel ── -->
- <div class="cover-footer">
- <!-- Left: logo + report type -->
- <div class="cover-left">
- <img class="cover-logo" src="/client-assets/images/crop-monitor.png" alt="Crop Monitor">
- <div style="margin-top: auto;">
- <div class="cover-type-label">Report Type</div>
- <div class="cover-report-title"><?= $label ?></div>
- <div class="cover-date">Prepared: <?= $today ?></div>
- </div>
- </div>
- <!-- Right: client details -->
- <div class="cover-client">
- <?php if ($clientName !== ''): ?>
- <div class="cover-client-name"><?= $clientName ?></div>
- <?php endif; ?>
- <?php if ($siteAddress !== '' || $statePost !== ''): ?>
- <div class="detail-row">
- <span class="detail-label">Site</span>
- <span class="detail-value"><?= $siteAddress ?><?= ($siteAddress && $statePost) ? ', ' : '' ?><?= $statePost ?></span>
- </div>
- <?php endif; ?>
- <?php if ($dateSampled !== ''): ?>
- <div class="detail-row">
- <span class="detail-label">Sampled</span>
- <span class="detail-value"><?= $dateSampled ?></span>
- </div>
- <?php endif; ?>
- <?php if ($sampleId !== ''): ?>
- <div class="detail-row">
- <span class="detail-label">Sample ID</span>
- <span class="detail-value"><?= $sampleId ?></span>
- </div>
- <?php endif; ?>
- <?php if ($siteId !== ''): ?>
- <div class="detail-row">
- <span class="detail-label">Site ID</span>
- <span class="detail-value"><?= $siteId ?></span>
- </div>
- <?php endif; ?>
- <?php if ($subjectLine !== ''): ?>
- <hr class="detail-divider">
- <div class="detail-row">
- <span class="detail-label"><?= $type === 'water' ? 'Source' : ($type === 'animal' ? 'Animal' : 'Crop / Type') ?></span>
- <span class="detail-value"><?= $subjectLine ?></span>
- </div>
- <?php endif; ?>
- <?php if ($analysisType !== ''): ?>
- <div class="detail-row">
- <span class="detail-label">Analysis</span>
- <span class="detail-value"><?= $analysisType ?></span>
- </div>
- <?php endif; ?>
- <?php if ($labNo !== ''): ?>
- <hr class="detail-divider">
- <div class="detail-row">
- <span class="detail-label">Lab No</span>
- <span class="detail-value"><?= $labNo ?></span>
- </div>
- <?php endif; ?>
- <?php if ($batchNo !== ''): ?>
- <div class="detail-row">
- <span class="detail-label">Batch</span>
- <span class="detail-value"><?= $batchNo ?></span>
- </div>
- <?php endif; ?>
- <?php if ($email !== ''): ?>
- <div class="detail-row" style="margin-top: 8px;">
- <span class="detail-label">Email</span>
- <span class="detail-value" style="font-size:10px;"><?= $email ?></span>
- </div>
- <?php endif; ?>
- </div>
- </div><!-- /.cover-footer -->
- </div><!-- /.cover -->
- </body>
- </html>
|