Projects/3BIT/winter-semester/IIS/xnecasr00/app/Http/Controllers/VineyardMapController.php
2026-04-14 19:28:46 +02:00

182 lines
6.1 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\VarietyVariation;
use App\Models\VineyardRow;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Carbon;
class VineyardMapController extends Controller
{
/**
* Display a read-only vineyard map with available actions.
*/
public function index()
{
$rows = VineyardRow::with([
'varietyVariation.grapeVariety',
'treatments' => function ($query) {
$query->latest('created_at');
},
'sprayings' => function ($query) {
$query->with('plannedTask')->orderByDesc('created_at');
},
'harvests' => function ($query) {
$query->with('plannedTask')->orderByDesc('date');
},
])->get();
$actionGroups = [
'Treatment' => [
'watering',
'pruning',
'fertilisation',
'pesticide',
],
'Manage Crops' => [
'harvest',
'add-plants',
'discard-plants',
],
];
return view('vineyard.map.index', [
'rows' => $this->formatRows($rows),
'actions' => array_merge(...array_values($actionGroups)),
'actionGroups' => $actionGroups,
]);
}
/**
* Display the editable vineyard map.
*/
public function edit()
{
$rows = VineyardRow::with(['varietyVariation.grapeVariety'])->get();
$variations = VarietyVariation::with('grapeVariety')
->orderBy('grape_variety_id')
->get()
->map(function (VarietyVariation $variation) {
$grape = $variation->grapeVariety;
$label = $grape
? sprintf('%s — %s', $grape->variety_name, ucfirst($variation->color))
: ucfirst($variation->color);
return [
'id' => $variation->getKey(),
'label' => $label,
];
});
return view('vineyard.map.edit', [
'rows' => $this->formatRows($rows),
'statuses' => ['active', 'inactive', 'replanting', 'discarded'],
'variationOptions' => $variations,
]);
}
/**
* Transform rows into a structure suitable for the front-end map.
*/
protected function formatRows(Collection $rows): Collection
{
return $rows->map(function (VineyardRow $row) {
[$x, $y] = $this->parseLocation($row->location);
$variation = $row->varietyVariation;
$grapeVariety = $variation?->grapeVariety;
$lastTreatmentDate = optional($row->treatments->first())->created_at;
$pesticideCompleted = $row->sprayings->map(function ($spraying) {
$executionDate = optional($spraying->plannedTask)->execution_date;
if ($executionDate) {
return Carbon::parse($executionDate)->toDateString();
}
return optional($spraying->created_at)?->toDateString();
})->filter()->unique()->sort()->values()->all();
$pesticidePlanned = $row->sprayings->map(function ($spraying) {
$plannedDate = optional($spraying->plannedTask)->planned_date;
if ($plannedDate) {
return Carbon::parse($plannedDate)->toDateString();
}
return null;
})->filter()->unique()->sort()->values()->all();
$harvestCompleted = $row->harvests->map(function ($harvest) {
$executionDate = optional($harvest->plannedTask)->execution_date;
if ($executionDate) {
return Carbon::parse($executionDate)->toDateString();
}
$harvestDate = $harvest->date;
return $harvestDate ? Carbon::parse($harvestDate)->toDateString() : null;
})->filter()->unique()->sort()->values()->all();
$harvestPlanned = $row->harvests->map(function ($harvest) {
$plannedDate = optional($harvest->plannedTask)->planned_date;
if ($plannedDate) {
return Carbon::parse($plannedDate)->toDateString();
}
return null;
})->filter()->unique()->sort()->values()->all();
return [
'id' => $row->getKey(),
'location' => [
'x' => $x,
'y' => $y,
],
'dimensions' => [
'width' => 1,
'height' => 1,
],
'vine_count' => $row->vine_count,
'status' => $row->status,
'notes' => $row->notes,
'planting_year' => $row->planting_year,
'variety' => $variation ? [
'id' => $variation->getKey(),
'color' => $variation->color,
'label' => $grapeVariety
? sprintf('%s — %s', $grapeVariety->variety_name, ucfirst($variation->color))
: ucfirst($variation->color),
] : null,
'last_treatment_at' => $lastTreatmentDate,
'timeline' => [
'pesticide' => [
'completed' => $pesticideCompleted,
'planned' => $pesticidePlanned,
],
'harvest' => [
'completed' => $harvestCompleted,
'planned' => $harvestPlanned,
],
],
];
});
}
/**
* Parse the "x,y" string stored on vineyard rows.
*/
protected function parseLocation(?string $location): array
{
if (blank($location)) {
return [0, 0];
}
$parts = Str::of($location)->explode(',')->map(fn ($fragment) => (int) trim($fragment));
return [
$parts->get(0, 0),
$parts->get(1, 0),
];
}
}