reviewed epic 4
This commit is contained in:
@@ -11,15 +11,20 @@ So that **I can track and communicate progress on their legal matters**.
|
||||
## Story Context
|
||||
|
||||
### Existing System Integration
|
||||
- **Integrates with:** timelines table, users table
|
||||
- **Integrates with:** timelines table, timeline_updates table, users table, admin_logs table
|
||||
- **Technology:** Livewire Volt, Flux UI
|
||||
- **Follows pattern:** Admin CRUD pattern
|
||||
- **Touch points:** User relationship, client dashboard
|
||||
- **Follows pattern:** Admin CRUD pattern (see existing admin components)
|
||||
- **Touch points:** User relationship, client dashboard, audit logging
|
||||
|
||||
### Reference Documents
|
||||
- **Epic:** `docs/epics/epic-4-case-timeline.md`
|
||||
- **Database Schema:** `docs/stories/story-1.1-project-setup-database-schema.md#database-schema-reference`
|
||||
- **User Model:** Requires users with `user_type` of 'individual' or 'company' (from Epic 2)
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### Timeline Creation Form
|
||||
- [ ] Select client (search by name/email)
|
||||
- [ ] Select client (search by name/email) - only users with user_type 'individual' or 'company'
|
||||
- [ ] Case name/title (required)
|
||||
- [ ] Case reference number (optional, unique if provided)
|
||||
- [ ] Initial notes (optional)
|
||||
@@ -38,15 +43,30 @@ So that **I can track and communicate progress on their legal matters**.
|
||||
- [ ] Client must exist
|
||||
|
||||
### Quality Requirements
|
||||
- [ ] Audit log entry created
|
||||
- [ ] Audit log entry created via AdminLog model
|
||||
- [ ] Bilingual labels and messages
|
||||
- [ ] Tests for creation flow
|
||||
|
||||
## Technical Notes
|
||||
|
||||
### File Structure
|
||||
```
|
||||
Routes:
|
||||
GET /admin/timelines/create -> admin.timelines.create
|
||||
POST handled by Livewire component
|
||||
|
||||
Files to Create:
|
||||
resources/views/livewire/pages/admin/timelines/create.blade.php (Volt component)
|
||||
|
||||
Models Required (from Story 1.1):
|
||||
app/Models/Timeline.php
|
||||
app/Models/TimelineUpdate.php
|
||||
app/Models/AdminLog.php
|
||||
```
|
||||
|
||||
### Database Schema
|
||||
```php
|
||||
// timelines table
|
||||
// timelines table (from Story 1.1)
|
||||
Schema::create('timelines', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
|
||||
@@ -55,13 +75,49 @@ Schema::create('timelines', function (Blueprint $table) {
|
||||
$table->enum('status', ['active', 'archived'])->default('active');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// timeline_updates table (from Story 1.1)
|
||||
Schema::create('timeline_updates', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('timeline_id')->constrained()->cascadeOnDelete();
|
||||
$table->foreignId('admin_id')->constrained('users')->cascadeOnDelete();
|
||||
$table->text('update_text');
|
||||
$table->timestamps();
|
||||
});
|
||||
```
|
||||
|
||||
### Required Translation Keys
|
||||
```php
|
||||
// resources/lang/en/messages.php
|
||||
'timeline_created' => 'Timeline created successfully.',
|
||||
|
||||
// resources/lang/ar/messages.php
|
||||
'timeline_created' => 'تم إنشاء الجدول الزمني بنجاح.',
|
||||
|
||||
// resources/lang/en/labels.php
|
||||
'case_name' => 'Case Name',
|
||||
'case_reference' => 'Case Reference',
|
||||
'initial_notes' => 'Initial Notes',
|
||||
'select_client' => 'Select Client',
|
||||
'search_client' => 'Search by name or email...',
|
||||
'create_timeline' => 'Create Timeline',
|
||||
|
||||
// resources/lang/ar/labels.php
|
||||
'case_name' => 'اسم القضية',
|
||||
'case_reference' => 'رقم مرجع القضية',
|
||||
'initial_notes' => 'ملاحظات أولية',
|
||||
'select_client' => 'اختر العميل',
|
||||
'search_client' => 'البحث بالاسم أو البريد الإلكتروني...',
|
||||
'create_timeline' => 'إنشاء جدول زمني',
|
||||
```
|
||||
|
||||
### Volt Component
|
||||
```php
|
||||
<?php
|
||||
|
||||
use App\Models\{Timeline, User};
|
||||
use App\Models\AdminLog;
|
||||
use App\Models\Timeline;
|
||||
use App\Models\User;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
@@ -72,10 +128,37 @@ new class extends Component {
|
||||
public string $caseReference = '';
|
||||
public string $initialNotes = '';
|
||||
|
||||
public function updatedSearch(): void
|
||||
{
|
||||
// Reset selection when search changes
|
||||
if ($this->selectedUser && ! str_contains(strtolower($this->selectedUser->name), strtolower($this->search))) {
|
||||
$this->selectedUserId = null;
|
||||
$this->selectedUser = null;
|
||||
}
|
||||
}
|
||||
|
||||
public function getClientsProperty()
|
||||
{
|
||||
if (strlen($this->search) < 2) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
return User::query()
|
||||
->whereIn('user_type', ['individual', 'company'])
|
||||
->where('status', 'active')
|
||||
->where(function ($query) {
|
||||
$query->where('name', 'like', "%{$this->search}%")
|
||||
->orWhere('email', 'like', "%{$this->search}%");
|
||||
})
|
||||
->limit(10)
|
||||
->get();
|
||||
}
|
||||
|
||||
public function selectUser(int $userId): void
|
||||
{
|
||||
$this->selectedUserId = $userId;
|
||||
$this->selectedUser = User::find($userId);
|
||||
$this->search = $this->selectedUser->name;
|
||||
}
|
||||
|
||||
public function create(): void
|
||||
@@ -113,27 +196,63 @@ new class extends Component {
|
||||
session()->flash('success', __('messages.timeline_created'));
|
||||
$this->redirect(route('admin.timelines.show', $timeline));
|
||||
}
|
||||
};
|
||||
}; ?>
|
||||
|
||||
<div>
|
||||
{{-- Component template here using Flux UI --}}
|
||||
</div>
|
||||
```
|
||||
|
||||
## Test Scenarios
|
||||
|
||||
All tests should use Pest and be placed in `tests/Feature/Admin/TimelineCreationTest.php`.
|
||||
|
||||
### Happy Path Tests
|
||||
- [ ] `test_admin_can_view_timeline_creation_form` - Admin can access /admin/timelines/create
|
||||
- [ ] `test_admin_can_search_clients_by_name` - Search returns matching users
|
||||
- [ ] `test_admin_can_search_clients_by_email` - Search returns matching users
|
||||
- [ ] `test_admin_can_create_timeline_with_required_fields` - Timeline created with case_name only
|
||||
- [ ] `test_admin_can_create_timeline_with_case_reference` - Timeline created with optional reference
|
||||
- [ ] `test_initial_notes_creates_first_timeline_update` - TimelineUpdate record created
|
||||
- [ ] `test_audit_log_created_on_timeline_creation` - AdminLog entry exists
|
||||
|
||||
### Validation Tests
|
||||
- [ ] `test_case_name_is_required` - Validation error without case_name
|
||||
- [ ] `test_case_reference_must_be_unique` - Validation error on duplicate reference
|
||||
- [ ] `test_case_reference_allows_multiple_nulls` - Multiple timelines without reference allowed
|
||||
- [ ] `test_client_selection_is_required` - Validation error without selecting client
|
||||
- [ ] `test_selected_client_must_exist` - Validation error for non-existent user_id
|
||||
|
||||
### Authorization Tests
|
||||
- [ ] `test_non_admin_cannot_access_timeline_creation` - Redirect or 403 for non-admin users
|
||||
- [ ] `test_guest_cannot_access_timeline_creation` - Redirect to login
|
||||
|
||||
### Edge Case Tests
|
||||
- [ ] `test_search_only_returns_individual_and_company_users` - Admin users not in results
|
||||
- [ ] `test_search_only_returns_active_users` - Deactivated users not in results
|
||||
- [ ] `test_can_create_multiple_timelines_for_same_client` - No unique constraint on user_id
|
||||
|
||||
## Definition of Done
|
||||
|
||||
- [ ] Can search and select client
|
||||
- [ ] Volt component created at `resources/views/livewire/pages/admin/timelines/create.blade.php`
|
||||
- [ ] Route registered for admin timeline creation
|
||||
- [ ] Can search and select client (individual/company only)
|
||||
- [ ] Can enter case name and reference
|
||||
- [ ] Timeline created with correct data
|
||||
- [ ] Initial notes saved as first update
|
||||
- [ ] Unique reference validation works
|
||||
- [ ] Client can view timeline immediately
|
||||
- [ ] Client can view timeline immediately (verified via client dashboard)
|
||||
- [ ] Audit log created
|
||||
- [ ] Tests pass
|
||||
- [ ] All translation keys added (AR/EN)
|
||||
- [ ] All tests pass
|
||||
- [ ] Code formatted with Pint
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **Epic 1:** Database schema, authentication
|
||||
- **Epic 2:** User accounts
|
||||
- **Story 1.1:** Database schema (timelines, timeline_updates, admin_logs tables and models)
|
||||
- **Story 1.2:** Authentication & role system (admin role check)
|
||||
- **Story 2.1/2.2:** User accounts exist to assign timelines to
|
||||
|
||||
## Estimation
|
||||
|
||||
**Complexity:** Low-Medium
|
||||
**Estimated Effort:** 2-3 hours
|
||||
|
||||
Reference in New Issue
Block a user