htmlspecialchars((string)($v ?? ''), ENT_QUOTES, 'UTF-8'); // ── Load paddock ───────────────────────────────────────────────────────────── $stmt = $pdo->prepare('SELECT * FROM block_info WHERE id = ? AND modx_user_id = ? LIMIT 1'); $stmt->execute([$rid, $userId]); $block = $stmt->fetch(PDO::FETCH_ASSOC); if (!$block) { http_response_code(404); die('Paddock not found or access denied'); } $areaHa = number_format((float)$block['area'], 1); $areaAc = number_format((float)$block['area'] * 2.47105, 1); // ── Crop name(s) for this paddock ──────────────────────────────────────────── $stmtCrops = $pdo->prepare( 'SELECT name FROM crop_info WHERE modx_user_id = ? AND paddock_id = ? ORDER BY id DESC' ); $stmtCrops->execute([$userId, $block['block_id']]); $crops = $stmtCrops->fetchAll(PDO::FETCH_COLUMN); // ── Recent soil tests ───────────────────────────────────────────────────────── // Linked via site_id until migration 003 adds/confirms block_id column $stmtSoil = $pdo->prepare( 'SELECT id, rand, date, site_id, analysis_type, crop_type, client_name FROM soil_records WHERE modx_user_id = ? AND site_id = ? ORDER BY date DESC LIMIT 5' ); $stmtSoil->execute([$userId, $block['block_id']]); $soilTests = $stmtSoil->fetchAll(PDO::FETCH_ASSOC); // ── Recent plant tests ──────────────────────────────────────────────────────── // Linked via site_id until migration 003 adds block_id column to plant_records $stmtPlant = $pdo->prepare( 'SELECT id, rand, date_sampled AS date, site_id, crop_type, client_name FROM plant_records WHERE modx_user_id = ? AND site_id = ? ORDER BY date_sampled DESC LIMIT 5' ); $stmtPlant->execute([$userId, $block['block_id']]); $plantTests = $stmtPlant->fetchAll(PDO::FETCH_ASSOC); // ── Recent water tests ──────────────────────────────────────────────────────── // Linked via site_id until migration 003 adds block_id column to water_records $stmtWater = $pdo->prepare( 'SELECT id, rand, date_sampled AS date, site_id, analysis_type, client_name FROM water_records WHERE modx_user_id = ? AND site_id = ? ORDER BY date_sampled DESC LIMIT 5' ); $stmtWater->execute([$userId, $block['block_id']]); $waterTests = $stmtWater->fetchAll(PDO::FETCH_ASSOC); // ── Sensor readings (latest per sensor) ────────────────────────────────────── $stmtSensors = $pdo->prepare( 'SELECT fs.sensor_id, fs.sensor_name, fs.value, fs.DATEUTC FROM field_sensors fs INNER JOIN ( SELECT sensor_id, MAX(DATEUTC) AS latest FROM field_sensors WHERE modx_user_id = ? GROUP BY sensor_id ) latest ON fs.sensor_id = latest.sensor_id AND fs.DATEUTC = latest.latest WHERE fs.modx_user_id = ? ORDER BY fs.sensor_name' ); $stmtSensors->execute([$userId, $userId]); $sensors = $stmtSensors->fetchAll(PDO::FETCH_ASSOC); // ── GPS lat/lng for weather override ───────────────────────────────────────── $weatherLat = $weatherLng = null; if (!empty($block['gps'])) { if (preg_match('/(-?\d+\.?\d*)\s*,\s*(-?\d+\.?\d*)/', $block['gps'], $m)) { $weatherLat = (float)$m[1]; $weatherLng = (float)$m[2]; } } $weatherUrl = '/api/weather.php' . ($weatherLat ? '?lat=' . $weatherLat . '&lng=' . $weatherLng : ''); $pageTitle = $h($block['name']) . ' — Paddock Dashboard'; $siteName = 'Crop Monitor'; include __DIR__ . '/../../layouts/header.php'; include __DIR__ . '/../../layouts/navbar.php'; ?>

Paddock Details
Block ID
Location
Area ha  /  ac
GPS
Crops None recorded
Soil Type —' ?>
Added
Current Weather
Loading weather…
Live Sensor Readings
Analysis Records

No soil tests recorded for block ID .

Date Site ID Client Soil Type Crop Actions

No plant tissue tests recorded for block ID .

Date Site ID Client Crop Actions

No water quality tests recorded for block ID .

Date Site ID Client Analysis Type Actions