mirror of
https://github.com/pacnpal/thrillwiki_laravel.git
synced 2025-12-21 13:31:10 -05:00
Add models, enums, and services for user roles, theme preferences, slug history, and ID generation
This commit is contained in:
125
app/Livewire/ParkAreaReorderComponent.php
Normal file
125
app/Livewire/ParkAreaReorderComponent.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Models\Park;
|
||||
use App\Models\ParkArea;
|
||||
use Livewire\Component;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class ParkAreaReorderComponent extends Component
|
||||
{
|
||||
public Park $park;
|
||||
public ?int $parentId = null;
|
||||
public array $areas = [];
|
||||
|
||||
public function mount(Park $park, ?int $parentId = null): void
|
||||
{
|
||||
$this->park = $park;
|
||||
$this->parentId = $parentId;
|
||||
$this->loadAreas();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load areas for the current context (either top-level or within a parent).
|
||||
*/
|
||||
protected function loadAreas(): void
|
||||
{
|
||||
$query = $this->park->areas()
|
||||
->where('parent_id', $this->parentId)
|
||||
->orderBy('position')
|
||||
->select(['id', 'name', 'position', 'closing_date']);
|
||||
|
||||
$this->areas = $query->get()
|
||||
->map(fn ($area) => [
|
||||
'id' => $area->id,
|
||||
'name' => $area->name,
|
||||
'position' => $area->position,
|
||||
'is_closed' => !is_null($area->closing_date),
|
||||
'has_children' => $area->hasChildren(),
|
||||
])
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle reordering of areas.
|
||||
*/
|
||||
public function reorder(array $orderedIds): void
|
||||
{
|
||||
// Validate that all IDs belong to this park and parent context
|
||||
$validIds = $this->park->areas()
|
||||
->where('parent_id', $this->parentId)
|
||||
->pluck('id')
|
||||
->toArray();
|
||||
|
||||
$orderedIds = array_values(array_intersect($orderedIds, $validIds));
|
||||
|
||||
// Update positions
|
||||
foreach ($orderedIds as $position => $id) {
|
||||
ParkArea::where('id', $id)->update(['position' => $position]);
|
||||
}
|
||||
|
||||
$this->loadAreas();
|
||||
$this->dispatch('areas-reordered');
|
||||
}
|
||||
|
||||
/**
|
||||
* Move an area to a new parent.
|
||||
*/
|
||||
public function moveToParent(int $areaId, ?int $newParentId): void
|
||||
{
|
||||
$area = $this->park->areas()->findOrFail($areaId);
|
||||
|
||||
// Prevent circular references
|
||||
if ($newParentId === $area->id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If moving to a new parent, validate it exists and belongs to this park
|
||||
if ($newParentId) {
|
||||
$newParent = $this->park->areas()->findOrFail($newParentId);
|
||||
|
||||
// Prevent moving to own descendant
|
||||
$ancestorIds = Collection::make();
|
||||
$current = $newParent;
|
||||
while ($current) {
|
||||
if ($ancestorIds->contains($current->id)) {
|
||||
return; // Circular reference detected
|
||||
}
|
||||
$ancestorIds->push($current->id);
|
||||
if ($current->id === $area->id) {
|
||||
return; // Would create circular reference
|
||||
}
|
||||
$current = $current->parent;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the next position in the new parent context
|
||||
$maxPosition = $this->park->areas()
|
||||
->where('parent_id', $newParentId)
|
||||
->max('position');
|
||||
|
||||
$area->update([
|
||||
'parent_id' => $newParentId,
|
||||
'position' => ($maxPosition ?? -1) + 1,
|
||||
]);
|
||||
|
||||
// Reorder the old parent's remaining areas to close gaps
|
||||
$this->park->areas()
|
||||
->where('parent_id', $this->parentId)
|
||||
->where('position', '>', $area->position)
|
||||
->decrement('position');
|
||||
|
||||
$this->loadAreas();
|
||||
$this->dispatch('area-moved');
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.park-area-reorder-component', [
|
||||
'parentArea' => $this->parentId
|
||||
? $this->park->areas()->find($this->parentId)
|
||||
: null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user