From e75a846a976b724c3a726f2e7571626ad799572e Mon Sep 17 00:00:00 2001 From: Doar Mihai Date: Sat, 18 Jul 2026 14:57:47 +0300 Subject: [PATCH] feat: add Sites Livewire CRUD page --- app/Livewire/Sites/Index.php | 72 +++++++++++++++++++ .../views/livewire/sites/index.blade.php | 60 ++++++++++++++++ routes/web.php | 6 ++ tests/Feature/Livewire/SitesTest.php | 50 +++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 app/Livewire/Sites/Index.php create mode 100644 resources/views/livewire/sites/index.blade.php create mode 100644 tests/Feature/Livewire/SitesTest.php diff --git a/app/Livewire/Sites/Index.php b/app/Livewire/Sites/Index.php new file mode 100644 index 0000000..9b9906f --- /dev/null +++ b/app/Livewire/Sites/Index.php @@ -0,0 +1,72 @@ + Site::orderBy('name')->get(), + ]); + } + + public function create(): void + { + $this->resetForm(); + $this->showForm = true; + } + + public function edit(int $id): void + { + $site = Site::findOrFail($id); + $this->editingId = $site->id; + $this->name = $site->name; + $this->url = $site->url; + $this->description = $site->description; + $this->showForm = true; + } + + public function save(): void + { + $validated = $this->validate([ + 'name' => ['required', 'string', 'max:255'], + 'url' => ['required', 'string', 'max:255'], + 'description' => ['nullable', 'string'], + ]); + + Site::updateOrCreate(['id' => $this->editingId], $validated); + + $this->resetForm(); + $this->showForm = false; + } + + public function delete(int $id): void + { + Site::findOrFail($id)->delete(); + } + + public function resetForm(): void + { + $this->editingId = null; + $this->name = ''; + $this->url = ''; + $this->description = null; + $this->resetValidation(); + } +} diff --git a/resources/views/livewire/sites/index.blade.php b/resources/views/livewire/sites/index.blade.php new file mode 100644 index 0000000..b0223dd --- /dev/null +++ b/resources/views/livewire/sites/index.blade.php @@ -0,0 +1,60 @@ +
+
+

Sites

+ +
+ + + + + + + + + + + + @foreach ($sites as $site) + + + + + + + @endforeach + +
NameURLDescription
{{ $site->name }}{{ $site->url }}{{ $site->description }} + + +
+ + @if ($showForm) +
+
+

{{ $editingId ? 'Edit Site' : 'Add Site' }}

+ +
+ + + @error('name') {{ $message }} @enderror +
+ +
+ + + @error('url') {{ $message }} @enderror +
+ +
+ + +
+ +
+ + +
+
+
+ @endif +
diff --git a/routes/web.php b/routes/web.php index 86a06c5..4520504 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,7 +1,13 @@ name('sites.index'); + +// placeholder, replaced in Task 6 +Route::get('/social-accounts', SitesIndex::class)->name('social-accounts.index'); diff --git a/tests/Feature/Livewire/SitesTest.php b/tests/Feature/Livewire/SitesTest.php new file mode 100644 index 0000000..8055b5b --- /dev/null +++ b/tests/Feature/Livewire/SitesTest.php @@ -0,0 +1,50 @@ +create(['name' => 'Example Site']); + + $this->get(route('sites.index')) + ->assertOk() + ->assertSee('Example Site'); +}); + +test('a new site can be created', function () { + Livewire::test(Index::class) + ->set('name', 'New Site') + ->set('url', 'https://newsite.test') + ->set('description', 'Some description') + ->call('save'); + + expect(Site::where('name', 'New Site')->exists())->toBeTrue(); +}); + +test('name and url are required to create a site', function () { + Livewire::test(Index::class) + ->set('name', '') + ->set('url', '') + ->call('save') + ->assertHasErrors(['name', 'url']); +}); + +test('an existing site can be edited', function () { + $site = Site::factory()->create(['name' => 'Old Name']); + + Livewire::test(Index::class) + ->call('edit', $site->id) + ->set('name', 'Updated Name') + ->call('save'); + + expect($site->fresh()->name)->toBe('Updated Name'); +}); + +test('a site can be deleted', function () { + $site = Site::factory()->create(); + + Livewire::test(Index::class)->call('delete', $site->id); + + expect(Site::find($site->id))->toBeNull(); +});