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';
?>
| Block ID |
= $h($block['block_id']) ?> |
| Location |
= $h($block['location']) ?: '—' ?> |
| Area |
= $areaHa ?> ha / = $areaAc ?> ac |
| GPS |
= $h($block['gps']) ?>
—
|
| Crops |
= $h(implode(', ', $crops)) ?>
None recorded
|
| Soil Type |
= !empty($block['analysis_type'] ?? '') ? ucfirst($h($block['analysis_type'])) : '—' ?> |
| Added |
= $h($block['date_added']) ?: '—' ?> |
Loading weather…
—% humidity
— km/h wind
— mm now
Feels —°
Live Sensor Readings
= $h($sensor['sensor_name'] ?: $sensor['sensor_id']) ?>
= number_format((float)$sensor['value'], 1) ?>
= $h(date('j M H:i', strtotime($sensor['DATEUTC']))) ?>
Analysis Records
No soil tests recorded for block ID = $h($block['block_id']) ?>.
| Date |
Site ID |
Client |
Soil Type |
Crop |
Actions |
| = $h($t['date'] ? date('j M Y', strtotime($t['date'])) : '—') ?> |
= $h($t['site_id']) ?> |
= $h($t['client_name']) ?> |
= $h($t['analysis_type']) ?> |
= $h($t['crop_type']) ?> |
|
No plant tissue tests recorded for block ID = $h($block['block_id']) ?>.
| Date |
Site ID |
Client |
Crop |
Actions |
| = $h($t['date'] ? date('j M Y', strtotime($t['date'])) : '—') ?> |
= $h($t['site_id']) ?> |
= $h($t['client_name']) ?> |
= $h($t['crop_type']) ?> |
|
No water quality tests recorded for block ID = $h($block['block_id']) ?>.
| Date |
Site ID |
Client |
Analysis Type |
Actions |
| = $h($t['date'] ? date('j M Y', strtotime($t['date'])) : '—') ?> |
= $h($t['site_id']) ?> |
= $h($t['client_name']) ?> |
= $h($t['analysis_type']) ?> |
|