196 lines
5.9 KiB
Markdown
196 lines
5.9 KiB
Markdown
# Story 4.3: Timeline Archiving
|
|
|
|
## Epic Reference
|
|
**Epic 4:** Case Timeline System
|
|
|
|
## User Story
|
|
As an **admin**,
|
|
I want **to archive completed cases and unarchive if needed**,
|
|
So that **I can organize active and completed case timelines**.
|
|
|
|
## Story Context
|
|
|
|
### Existing System Integration
|
|
- **Integrates with:** timelines table (status field from Story 4.1)
|
|
- **Technology:** Livewire Volt
|
|
- **Follows pattern:** Soft state change pattern
|
|
- **Touch points:** Timeline list views, timeline detail view
|
|
|
|
### Prerequisites (from Story 4.1)
|
|
The `timelines` table includes:
|
|
```php
|
|
$table->enum('status', ['active', 'archived'])->default('active');
|
|
```
|
|
|
|
### Files to Modify
|
|
- `app/Models/Timeline.php` - add archive/unarchive methods and scopes
|
|
- `resources/views/livewire/admin/timelines/show.blade.php` - add archive/unarchive button
|
|
- `resources/views/livewire/admin/timelines/index.blade.php` - add status filter dropdown
|
|
- `resources/views/livewire/client/timelines/index.blade.php` - separate archived timelines display
|
|
|
|
## Acceptance Criteria
|
|
|
|
### Archive Timeline
|
|
- [ ] Archive button on timeline detail view (admin only)
|
|
- [ ] Confirmation modal before archiving ("Are you sure?")
|
|
- [ ] Status changes to 'archived'
|
|
- [ ] Timeline remains visible to client (read-only as always)
|
|
- [ ] No further updates can be added (show disabled state with tooltip)
|
|
- [ ] Visual indicator shows archived status (badge + muted styling)
|
|
|
|
### Unarchive Timeline
|
|
- [ ] Unarchive button on archived timelines
|
|
- [ ] Status returns to 'active'
|
|
- [ ] Updates can be added again
|
|
|
|
### List Filtering
|
|
- [ ] Filter dropdown with options: Active (default), Archived, All
|
|
- [ ] Archived timelines shown in separate section in client view (below active)
|
|
- [ ] Bulk archive via checkbox selection + "Archive Selected" button
|
|
- [ ] Bulk archive shows count confirmation ("Archive 3 timelines?")
|
|
|
|
### Edge Cases
|
|
- [ ] Archiving already-archived timeline: No-op, no error shown
|
|
- [ ] Unarchiving already-active timeline: No-op, no error shown
|
|
- [ ] Adding update to archived timeline: Prevented with error message
|
|
- [ ] Bulk archive mixed selection: Skip already-archived, archive only active ones
|
|
- [ ] Empty bulk selection: "Archive Selected" button disabled
|
|
|
|
### Quality Requirements
|
|
- [ ] Audit log for status changes (action_type: 'archive' or 'unarchive')
|
|
- [ ] Bilingual labels (AR/EN for buttons, messages, filters)
|
|
- [ ] Feature tests covering all scenarios below
|
|
|
|
### Test Scenarios
|
|
```
|
|
tests/Feature/Timeline/TimelineArchivingTest.php
|
|
- test_admin_can_archive_active_timeline
|
|
- test_admin_can_unarchive_archived_timeline
|
|
- test_archiving_archived_timeline_is_noop
|
|
- test_unarchiving_active_timeline_is_noop
|
|
- test_cannot_add_update_to_archived_timeline
|
|
- test_client_can_view_archived_timeline
|
|
- test_admin_can_filter_by_active_status
|
|
- test_admin_can_filter_by_archived_status
|
|
- test_admin_can_filter_all_statuses
|
|
- test_bulk_archive_updates_multiple_timelines
|
|
- test_bulk_archive_skips_already_archived
|
|
- test_audit_log_created_on_archive
|
|
- test_audit_log_created_on_unarchive
|
|
- test_guest_cannot_archive_timeline
|
|
```
|
|
|
|
## Technical Notes
|
|
|
|
### Timeline Model Methods
|
|
```php
|
|
class Timeline extends Model
|
|
{
|
|
public function archive(): void
|
|
{
|
|
$this->update(['status' => 'archived']);
|
|
}
|
|
|
|
public function unarchive(): void
|
|
{
|
|
$this->update(['status' => 'active']);
|
|
}
|
|
|
|
public function isArchived(): bool
|
|
{
|
|
return $this->status === 'archived';
|
|
}
|
|
|
|
public function scopeActive($query)
|
|
{
|
|
return $query->where('status', 'active');
|
|
}
|
|
|
|
public function scopeArchived($query)
|
|
{
|
|
return $query->where('status', 'archived');
|
|
}
|
|
}
|
|
```
|
|
|
|
### Volt Component Actions
|
|
```php
|
|
public function archive(): void
|
|
{
|
|
if ($this->timeline->isArchived()) {
|
|
return;
|
|
}
|
|
|
|
$this->timeline->archive();
|
|
|
|
AdminLog::create([
|
|
'admin_id' => auth()->id(),
|
|
'action_type' => 'archive',
|
|
'target_type' => 'timeline',
|
|
'target_id' => $this->timeline->id,
|
|
'ip_address' => request()->ip(),
|
|
]);
|
|
|
|
session()->flash('success', __('messages.timeline_archived'));
|
|
}
|
|
|
|
public function unarchive(): void
|
|
{
|
|
if (!$this->timeline->isArchived()) {
|
|
return;
|
|
}
|
|
|
|
$this->timeline->unarchive();
|
|
|
|
AdminLog::create([
|
|
'admin_id' => auth()->id(),
|
|
'action_type' => 'unarchive',
|
|
'target_type' => 'timeline',
|
|
'target_id' => $this->timeline->id,
|
|
'ip_address' => request()->ip(),
|
|
]);
|
|
|
|
session()->flash('success', __('messages.timeline_unarchived'));
|
|
}
|
|
|
|
public function bulkArchive(array $ids): void
|
|
{
|
|
Timeline::whereIn('id', $ids)->update(['status' => 'archived']);
|
|
|
|
foreach ($ids as $id) {
|
|
AdminLog::create([
|
|
'admin_id' => auth()->id(),
|
|
'action_type' => 'archive',
|
|
'target_type' => 'timeline',
|
|
'target_id' => $id,
|
|
'ip_address' => request()->ip(),
|
|
]);
|
|
}
|
|
|
|
session()->flash('success', __('messages.timelines_archived', ['count' => count($ids)]));
|
|
}
|
|
```
|
|
|
|
## Definition of Done
|
|
|
|
- [ ] Archive button on timeline detail view works with confirmation modal
|
|
- [ ] Unarchive button on archived timelines works
|
|
- [ ] Update form disabled/hidden on archived timelines with clear messaging
|
|
- [ ] Status filter dropdown functional (Active/Archived/All)
|
|
- [ ] Bulk archive with checkbox selection works
|
|
- [ ] Visual indicators (badge + muted styling) display correctly
|
|
- [ ] Client can still view archived timelines in separate section
|
|
- [ ] Audit log entries created for all archive/unarchive actions
|
|
- [ ] All test scenarios in `tests/Feature/Timeline/TimelineArchivingTest.php` pass
|
|
- [ ] Code formatted with Pint
|
|
|
|
## Dependencies
|
|
|
|
- **Story 4.1:** Timeline creation (`docs/stories/story-4.1-timeline-creation.md`) - provides Timeline model and schema
|
|
- **Story 4.2:** Timeline updates (`docs/stories/story-4.2-timeline-updates-management.md`) - provides update blocking context
|
|
|
|
## Estimation
|
|
|
|
**Complexity:** Low
|
|
**Estimated Effort:** 2 hours
|