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

4.1 KiB

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

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

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