258 lines
8.1 KiB
Markdown
258 lines
8.1 KiB
Markdown
# Story 2.1: Individual Client Account Management
|
|
|
|
## Epic Reference
|
|
**Epic 2:** User Management System
|
|
|
|
## User Story
|
|
As an **admin**,
|
|
I want **to create, view, edit, and search individual client accounts**,
|
|
So that **I can manage client information and provide them platform access**.
|
|
|
|
## Story Context
|
|
|
|
### Existing System Integration
|
|
- **Integrates with:** Users table, Fortify authentication
|
|
- **Technology:** Livewire Volt, Flux UI forms
|
|
- **Follows pattern:** Admin CRUD patterns, class-based Volt components
|
|
- **Touch points:** User model, admin dashboard
|
|
- **PRD Reference:** Section 5.3 (User Management System), Section 16.1 (Database Schema)
|
|
|
|
### Prerequisites from Epic 1
|
|
- Users table with fields: `name`, `email`, `password`, `user_type`, `national_id`, `phone`, `preferred_language`, `status`
|
|
- AdminLog model and `admin_logs` table for audit logging
|
|
- Bilingual infrastructure (lang files, `__()` helper)
|
|
|
|
## Acceptance Criteria
|
|
|
|
### Create Individual Client
|
|
- [ ] Form with required fields:
|
|
- Full Name (required)
|
|
- National ID Number (required, unique)
|
|
- Email Address (required, unique)
|
|
- Phone Number (required)
|
|
- Password (admin-set, required)
|
|
- Preferred Language (Arabic/English dropdown)
|
|
- [ ] Validation for all required fields
|
|
- [ ] Duplicate email/National ID prevention with clear error message
|
|
- [ ] Password strength indicator (optional)
|
|
- [ ] Success message on creation
|
|
|
|
### List View
|
|
- [ ] Display all individual clients (user_type = 'individual')
|
|
- [ ] Columns: Name, Email, National ID, Phone, Status, Created Date
|
|
- [ ] Pagination (10/25/50 per page)
|
|
- [ ] Default sort by created date (newest first)
|
|
|
|
### Search & Filter
|
|
- [ ] Search by name, email, or National ID
|
|
- [ ] Filter by status (active/deactivated/all)
|
|
- [ ] Real-time search with debounce (300ms)
|
|
- [ ] Clear filters button
|
|
|
|
### Edit Client
|
|
- [ ] Edit all client information
|
|
- [ ] Cannot change user_type from this form
|
|
- [ ] Validation same as create
|
|
- [ ] Success message on update
|
|
|
|
### View Client Profile
|
|
- [ ] Display all client information
|
|
- [ ] Show consultation history summary
|
|
- [ ] Show timeline history summary
|
|
- [ ] Quick links to related records
|
|
|
|
### Quality Requirements
|
|
- [ ] Bilingual form labels and messages
|
|
- [ ] Proper form validation with error display
|
|
- [ ] Audit log entries for all operations
|
|
- [ ] Tests for CRUD operations
|
|
|
|
## Technical Notes
|
|
|
|
### Files to Create
|
|
```
|
|
resources/views/livewire/admin/clients/individual/
|
|
├── index.blade.php # List view with search/filter/pagination
|
|
├── create.blade.php # Create form
|
|
├── edit.blade.php # Edit form
|
|
└── show.blade.php # View profile page
|
|
```
|
|
|
|
### User Model Scope
|
|
```php
|
|
// In User model
|
|
public function scopeIndividual($query)
|
|
{
|
|
return $query->where('user_type', 'individual');
|
|
}
|
|
```
|
|
|
|
### Volt Component Structure
|
|
```php
|
|
<?php
|
|
|
|
use App\Models\User;
|
|
use Livewire\Volt\Component;
|
|
use Livewire\WithPagination;
|
|
|
|
new class extends Component {
|
|
use WithPagination;
|
|
|
|
public string $search = '';
|
|
public string $statusFilter = '';
|
|
|
|
public function updatedSearch()
|
|
{
|
|
$this->resetPage();
|
|
}
|
|
|
|
public function with(): array
|
|
{
|
|
return [
|
|
'clients' => User::individual()
|
|
->when($this->search, fn($q) => $q->where(function($q) {
|
|
$q->where('name', 'like', "%{$this->search}%")
|
|
->orWhere('email', 'like', "%{$this->search}%")
|
|
->orWhere('national_id', 'like', "%{$this->search}%");
|
|
}))
|
|
->when($this->statusFilter, fn($q) => $q->where('status', $this->statusFilter))
|
|
->latest()
|
|
->paginate(10),
|
|
];
|
|
}
|
|
};
|
|
```
|
|
|
|
### Validation Rules
|
|
```php
|
|
public function rules(): array
|
|
{
|
|
return [
|
|
'name' => ['required', 'string', 'max:255'],
|
|
'national_id' => ['required', 'string', 'unique:users,national_id'],
|
|
'email' => ['required', 'email', 'unique:users,email'],
|
|
'phone' => ['required', 'string'],
|
|
'password' => ['required', 'string', 'min:8'],
|
|
'preferred_language' => ['required', 'in:ar,en'],
|
|
];
|
|
}
|
|
```
|
|
|
|
### Admin Logging
|
|
```php
|
|
// After creating user
|
|
AdminLog::create([
|
|
'admin_id' => auth()->id(),
|
|
'action_type' => 'create',
|
|
'target_type' => 'user',
|
|
'target_id' => $user->id,
|
|
'new_values' => $user->only(['name', 'email', 'national_id']),
|
|
'ip_address' => request()->ip(),
|
|
]);
|
|
```
|
|
|
|
### Edge Cases & Error Handling
|
|
- **Validation failure:** Display inline field errors using Flux UI error states
|
|
- **Duplicate email:** Show "Email already exists" error on email field
|
|
- **Duplicate National ID:** Show "National ID already registered" error
|
|
- **Empty search results:** Display "No clients found" message with clear filters option
|
|
|
|
## Testing Requirements
|
|
|
|
### Test File Location
|
|
`tests/Feature/Admin/IndividualClientTest.php`
|
|
|
|
### Test Scenarios
|
|
|
|
#### Create Client Tests
|
|
- [ ] Can create individual client with all valid data
|
|
- [ ] Cannot create client without required name field
|
|
- [ ] Cannot create client without required email field
|
|
- [ ] Cannot create client without required national_id field
|
|
- [ ] Cannot create client without required phone field
|
|
- [ ] Cannot create client with invalid email format
|
|
- [ ] Cannot create client with duplicate email (existing user)
|
|
- [ ] Cannot create client with duplicate national_id
|
|
- [ ] Cannot create client with password less than 8 characters
|
|
- [ ] Created client has user_type set to 'individual'
|
|
- [ ] AdminLog entry created on successful creation
|
|
|
|
#### List View Tests
|
|
- [ ] Index page displays only individual clients (not company/admin)
|
|
- [ ] Pagination works with 10/25/50 per page options
|
|
- [ ] Clients sorted by created_at desc by default
|
|
|
|
#### Search & Filter Tests
|
|
- [ ] Can search clients by name (partial match)
|
|
- [ ] Can search clients by email (partial match)
|
|
- [ ] Can search clients by national_id (partial match)
|
|
- [ ] Can filter clients by active status
|
|
- [ ] Can filter clients by deactivated status
|
|
- [ ] Clear filters resets search and filter
|
|
|
|
#### Edit Client Tests
|
|
- [ ] Can edit existing client information
|
|
- [ ] Edit form pre-populates with current values
|
|
- [ ] Validation rules apply on edit (except unique for own record)
|
|
- [ ] AdminLog entry created on successful update
|
|
- [ ] Cannot change user_type via edit form
|
|
|
|
#### View Profile Tests
|
|
- [ ] Profile page displays all client information
|
|
- [ ] Profile shows consultation count/summary
|
|
- [ ] Profile shows timeline count/summary
|
|
|
|
### Testing Approach
|
|
```php
|
|
use Livewire\Volt\Volt;
|
|
|
|
test('admin can create individual client', function () {
|
|
$admin = User::factory()->admin()->create();
|
|
|
|
Volt::actingAs($admin)
|
|
->test('admin.clients.individual.create')
|
|
->set('name', 'Test Client')
|
|
->set('email', 'client@example.com')
|
|
->set('national_id', '123456789')
|
|
->set('phone', '+970599123456')
|
|
->set('password', 'password123')
|
|
->set('preferred_language', 'ar')
|
|
->call('create')
|
|
->assertHasNoErrors();
|
|
|
|
expect(User::where('email', 'client@example.com')->exists())->toBeTrue();
|
|
expect(AdminLog::where('action_type', 'create')->exists())->toBeTrue();
|
|
});
|
|
```
|
|
|
|
## Definition of Done
|
|
|
|
- [ ] Create individual client form works
|
|
- [ ] List view displays all individual clients
|
|
- [ ] Search and filter functional
|
|
- [ ] Edit client works with validation
|
|
- [ ] View profile shows complete information
|
|
- [ ] Duplicate prevention works
|
|
- [ ] Audit logging implemented
|
|
- [ ] Bilingual support complete
|
|
- [ ] Tests pass for all CRUD operations
|
|
- [ ] Code formatted with Pint
|
|
|
|
## Dependencies
|
|
|
|
- **Story 1.1:** Database schema with `users` table (user_type, national_id, status fields) and `admin_logs` table
|
|
- **Story 1.2:** Authentication system with admin role, AdminLog model
|
|
- **Story 1.3:** Bilingual infrastructure (translation files, `__()` helper)
|
|
- **Story 1.4:** Base admin layout and navigation
|
|
|
|
## Risk Assessment
|
|
|
|
- **Primary Risk:** Duplicate National ID from different sources
|
|
- **Mitigation:** Database unique constraint + form validation
|
|
- **Rollback:** Remove user and notify if duplicate discovered
|
|
|
|
## Estimation
|
|
|
|
**Complexity:** Medium
|
|
**Estimated Effort:** 4-5 hours
|