3.4 KiB
3.4 KiB
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
Acceptance Criteria
Delete Functionality
- Delete button on post list and edit page
- Confirmation dialog before deletion
- Permanent deletion (no soft delete per PRD)
- Success message after deletion
Restrictions
- Cannot delete while post is being viewed publicly (edge case)
- Admin-only access
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
<flux:modal wire:model="showDeleteModal">
<flux:heading>{{ __('admin.delete_post') }}</flux:heading>
<flux:callout variant="danger">
{{ __('admin.delete_post_warning') }}
</flux:callout>
<p class="my-4">
{{ __('admin.deleting_post', ['title' => $postToDelete?->title]) }}
</p>
<div class="flex gap-3">
<flux:button wire:click="$set('showDeleteModal', false)">
{{ __('common.cancel') }}
</flux:button>
<flux:button variant="danger" wire:click="confirmDelete">
{{ __('admin.delete_permanently') }}
</flux:button>
</div>
</flux:modal>
Delete Logic
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
it('permanently deletes post', function () {
$post = Post::factory()->create();
$this->actingAs($admin)
->delete(route('admin.posts.destroy', $post));
expect(Post::find($post->id))->toBeNull();
});
it('creates audit log on deletion', function () {
$post = Post::factory()->create();
$this->actingAs($admin)
->delete(route('admin.posts.destroy', $post));
expect(AdminLog::where('target_type', 'post')
->where('target_id', $post->id)
->where('action_type', 'delete')
->exists()
)->toBeTrue();
});
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