# Story 5.3: Post Deletion ## Epic Reference **Epic 5:** Posts/Blog System ## User Story As an **admin**, I want **to permanently delete posts**, So that **I can remove outdated or incorrect content from the website**. ## Story Context ### Existing System Integration - **Integrates with:** posts table - **Technology:** Livewire Volt - **Follows pattern:** Permanent delete pattern - **Touch points:** Post management dashboard - **Files to modify:** Post management Volt component from Story 5.2 ## Acceptance Criteria ### Delete Functionality - [ ] Delete button on post list (primary location) - [ ] Delete button on post edit page (secondary location) - [ ] Confirmation modal dialog before deletion - [ ] Permanent deletion (no soft delete per PRD) - [ ] Success message after deletion - [ ] Redirect to post list after deletion from edit page ### Restrictions - [ ] Admin-only access (middleware protection) ### Audit Trail - [ ] Audit log entry preserved - [ ] Old values stored in log ### Quality Requirements - [ ] Clear warning in confirmation - [ ] Bilingual messages - [ ] Tests for deletion ## Technical Notes ### Delete Confirmation Modal ```blade {{ __('admin.delete_post') }} {{ __('admin.delete_post_warning') }}

{{ __('admin.deleting_post', ['title' => $postToDelete?->title]) }}

{{ __('common.cancel') }} {{ __('admin.delete_permanently') }}
``` ### Delete Button on Edit Page Add delete button to the post edit form (from Story 5.1) when editing an existing post: ```blade @if($post?->exists) {{ __('admin.delete_post') }} @endif ``` ### Delete Logic ```php public ?Post $postToDelete = null; public bool $showDeleteModal = false; public function delete(int $id): void { $this->postToDelete = Post::findOrFail($id); $this->showDeleteModal = true; } public function confirmDelete(): void { if (!$this->postToDelete) { return; } // Create audit log BEFORE deletion AdminLog::create([ 'admin_id' => auth()->id(), 'action_type' => 'delete', 'target_type' => 'post', 'target_id' => $this->postToDelete->id, 'old_values' => $this->postToDelete->toArray(), 'ip_address' => request()->ip(), ]); // Permanently delete $this->postToDelete->delete(); $this->showDeleteModal = false; $this->postToDelete = null; session()->flash('success', __('messages.post_deleted')); } ``` ### Testing ```php use App\Models\Post; use App\Models\AdminLog; use App\Models\User; use Livewire\Volt\Volt; it('permanently deletes post', function () { $admin = User::factory()->create(); $post = Post::factory()->create(); Volt::test('admin.posts.index') ->actingAs($admin) ->call('delete', $post->id) ->call('confirmDelete'); expect(Post::find($post->id))->toBeNull(); }); it('shows confirmation modal before deletion', function () { $admin = User::factory()->create(); $post = Post::factory()->create(); Volt::test('admin.posts.index') ->actingAs($admin) ->call('delete', $post->id) ->assertSet('showDeleteModal', true) ->assertSet('postToDelete.id', $post->id); }); it('creates audit log on deletion with old values', function () { $admin = User::factory()->create(); $post = Post::factory()->create(['title_en' => 'Test Title']); Volt::test('admin.posts.index') ->actingAs($admin) ->call('delete', $post->id) ->call('confirmDelete'); $log = AdminLog::where('target_type', 'post') ->where('target_id', $post->id) ->where('action_type', 'delete') ->first(); expect($log)->not->toBeNull() ->and($log->old_values)->toHaveKey('title_en', 'Test Title'); }); it('requires admin authentication to delete', function () { $post = Post::factory()->create(); $this->delete(route('admin.posts.destroy', $post)) ->assertRedirect(route('login')); }); ``` ## Definition of Done - [ ] Delete button shows confirmation - [ ] Confirmation explains permanence - [ ] Post deleted from database - [ ] Audit log created with old values - [ ] Success message displayed - [ ] Tests pass - [ ] Code formatted with Pint ## Dependencies - **Story 5.1:** Post creation - **Story 5.2:** Post management dashboard ## Estimation **Complexity:** Low **Estimated Effort:** 1-2 hours