libra/docs/stories/story-4.5-client-timeline-v...

175 lines
4.8 KiB
Markdown

# Story 4.5: Client Timeline View
## Epic Reference
**Epic 4:** Case Timeline System
## User Story
As a **client**,
I want **to view my case timelines and updates**,
So that **I can track the progress of my legal matters**.
## Story Context
### Existing System Integration
- **Integrates with:** timelines, timeline_updates tables
- **Technology:** Livewire Volt (read-only)
- **Follows pattern:** Client dashboard pattern
- **Touch points:** Client portal navigation
## Acceptance Criteria
### Timeline List
- [ ] Display all client's timelines
- [ ] Active timelines prominently displayed
- [ ] Archived timelines clearly separated
- [ ] Visual distinction (color/icon) for status
- [ ] Show for each:
- Case name and reference
- Status indicator
- Last update date
- Update count
### Individual Timeline View
- [ ] Case name and reference
- [ ] Status indicator
- [ ] All updates in chronological order
- [ ] Each update shows:
- Date and time
- Update content (formatted)
### Restrictions
- [ ] Read-only (no edit/comment)
- [ ] No ability to archive/delete
- [ ] Only see own timelines
### UX Features
- [ ] Recent updates indicator (new since last view, optional)
- [ ] Responsive design for mobile
- [ ] Bilingual labels and dates
## Technical Notes
### Volt Component for List
```php
<?php
use Livewire\Volt\Component;
new class extends Component {
public function with(): array
{
return [
'activeTimelines' => auth()->user()
->timelines()
->active()
->withCount('updates')
->with(['updates' => fn($q) => $q->latest()->limit(1)])
->latest('updated_at')
->get(),
'archivedTimelines' => auth()->user()
->timelines()
->archived()
->withCount('updates')
->latest('updated_at')
->get(),
];
}
};
```
### Timeline Detail View
```php
<?php
use App\Models\Timeline;
use Livewire\Volt\Component;
new class extends Component {
public Timeline $timeline;
public function mount(Timeline $timeline): void
{
// Ensure client owns this timeline
abort_unless($timeline->user_id === auth()->id(), 403);
$this->timeline = $timeline->load(['updates' => fn($q) => $q->oldest()]);
}
};
```
### Template
```blade
<div class="max-w-3xl mx-auto">
<!-- Header -->
<div class="flex justify-between items-start mb-6">
<div>
<flux:heading>{{ $timeline->case_name }}</flux:heading>
@if($timeline->case_reference)
<p class="text-charcoal/70">{{ __('client.reference') }}: {{ $timeline->case_reference }}</p>
@endif
</div>
<flux:badge :variant="$timeline->status === 'active' ? 'success' : 'secondary'">
{{ __('client.' . $timeline->status) }}
</flux:badge>
</div>
<!-- Timeline Updates -->
<div class="relative">
<!-- Vertical line -->
<div class="absolute {{ app()->getLocale() === 'ar' ? 'right-4' : 'left-4' }} top-0 bottom-0 w-0.5 bg-gold/30"></div>
<div class="space-y-6">
@forelse($timeline->updates as $update)
<div class="relative {{ app()->getLocale() === 'ar' ? 'pr-12' : 'pl-12' }}">
<!-- Dot -->
<div class="absolute {{ app()->getLocale() === 'ar' ? 'right-2' : 'left-2' }} top-2 w-4 h-4 rounded-full bg-gold border-4 border-cream"></div>
<div class="bg-white p-4 rounded-lg shadow-sm">
<div class="text-sm text-charcoal/70 mb-2">
{{ $update->created_at->translatedFormat('l, d M Y - g:i A') }}
</div>
<div class="prose prose-sm">
{!! $update->update_text !!}
</div>
</div>
</div>
@empty
<p class="text-center text-charcoal/70 py-8">
{{ __('client.no_updates_yet') }}
</p>
@endforelse
</div>
</div>
<div class="mt-6">
<flux:button href="{{ route('client.timelines.index') }}">
{{ __('client.back_to_cases') }}
</flux:button>
</div>
</div>
```
## Definition of Done
- [ ] Client can view list of their timelines
- [ ] Active/archived clearly separated
- [ ] Can view individual timeline details
- [ ] All updates displayed chronologically
- [ ] Read-only (no edit capabilities)
- [ ] Cannot view other clients' timelines
- [ ] Mobile responsive
- [ ] RTL support
- [ ] Tests pass
- [ ] Code formatted with Pint
## Dependencies
- **Story 4.1-4.3:** Timeline management
- **Epic 7:** Client dashboard structure
## Estimation
**Complexity:** Medium
**Estimated Effort:** 3-4 hours