generated sotries
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user