libra/docs/stories/story-4.2-timeline-updates-...

158 lines
4.1 KiB
Markdown

# Story 4.2: Timeline Updates Management
## Epic Reference
**Epic 4:** Case Timeline System
## User Story
As an **admin**,
I want **to add and edit updates within a timeline**,
So that **I can keep clients informed about their case progress**.
## Story Context
### Existing System Integration
- **Integrates with:** timeline_updates table, timelines table
- **Technology:** Livewire Volt, rich text editor
- **Follows pattern:** Nested CRUD pattern
- **Touch points:** Client notifications, timeline view
## Acceptance Criteria
### Add Update
- [ ] Add new update to timeline
- [ ] Update text content (required)
- [ ] Rich text formatting supported:
- Bold, italic, underline
- Bullet/numbered lists
- Links
- [ ] Timestamp automatically recorded
- [ ] Admin name automatically recorded
- [ ] Client notified via email on new update
### Edit Update
- [ ] Edit existing update text
- [ ] Edit history preserved (updated_at changes)
- [ ] Cannot change timestamp or admin
### Display
- [ ] Updates displayed in chronological order
- [ ] Each update shows:
- Date/timestamp
- Admin name
- Update content
- [ ] Visual timeline representation
### Quality Requirements
- [ ] HTML sanitization for security
- [ ] Audit log for edits
- [ ] Tests for add/edit operations
## Technical Notes
### Database Schema
```php
Schema::create('timeline_updates', function (Blueprint $table) {
$table->id();
$table->foreignId('timeline_id')->constrained()->cascadeOnDelete();
$table->foreignId('admin_id')->constrained('users');
$table->text('update_text');
$table->timestamps();
});
```
### Volt Component
```php
<?php
use App\Models\{Timeline, TimelineUpdate};
use App\Notifications\TimelineUpdateNotification;
use Livewire\Volt\Component;
new class extends Component {
public Timeline $timeline;
public string $updateText = '';
public ?TimelineUpdate $editingUpdate = null;
public function addUpdate(): void
{
$this->validate([
'updateText' => ['required', 'string', 'min:10'],
]);
$update = $this->timeline->updates()->create([
'admin_id' => auth()->id(),
'update_text' => clean($this->updateText), // Sanitize HTML
]);
// Notify client
$this->timeline->user->notify(new TimelineUpdateNotification($update));
AdminLog::create([
'admin_id' => auth()->id(),
'action_type' => 'create',
'target_type' => 'timeline_update',
'target_id' => $update->id,
'ip_address' => request()->ip(),
]);
$this->updateText = '';
session()->flash('success', __('messages.update_added'));
}
public function editUpdate(TimelineUpdate $update): void
{
$this->editingUpdate = $update;
$this->updateText = $update->update_text;
}
public function saveEdit(): void
{
$this->validate([
'updateText' => ['required', 'string', 'min:10'],
]);
$oldText = $this->editingUpdate->update_text;
$this->editingUpdate->update([
'update_text' => clean($this->updateText),
]);
AdminLog::create([
'admin_id' => auth()->id(),
'action_type' => 'update',
'target_type' => 'timeline_update',
'target_id' => $this->editingUpdate->id,
'old_values' => ['update_text' => $oldText],
'new_values' => ['update_text' => $this->updateText],
'ip_address' => request()->ip(),
]);
$this->editingUpdate = null;
$this->updateText = '';
session()->flash('success', __('messages.update_edited'));
}
};
```
## Definition of Done
- [ ] Can add new updates with rich text
- [ ] Can edit existing updates
- [ ] Updates display chronologically
- [ ] Admin name and timestamp shown
- [ ] Client notification sent
- [ ] HTML properly sanitized
- [ ] Audit log created
- [ ] Tests pass
- [ ] Code formatted with Pint
## Dependencies
- **Story 4.1:** Timeline creation
- **Epic 8:** Email notifications
## Estimation
**Complexity:** Medium
**Estimated Effort:** 3-4 hours