# 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 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 --- ## Dev Agent Record ### Status **Done** ### Agent Model Used Claude Opus 4.5 (claude-opus-4-5-20251101) ### File List **Created:** - `resources/views/livewire/admin/clients/individual/index.blade.php` - List view with search/filter/pagination - `resources/views/livewire/admin/clients/individual/create.blade.php` - Create individual client form - `resources/views/livewire/admin/clients/individual/edit.blade.php` - Edit individual client form - `resources/views/livewire/admin/clients/individual/show.blade.php` - Client profile/view page - `lang/en/clients.php` - English translations for clients module - `lang/ar/clients.php` - Arabic translations for clients module - `tests/Feature/Admin/IndividualClientTest.php` - 32 comprehensive tests for CRUD operations **Modified:** - `app/Models/User.php` - Added `scopeIndividual()` and `scopeCompanies()` scopes - `routes/web.php` - Added admin routes for individual clients CRUD - `resources/views/components/layouts/app/sidebar.blade.php` - Added User Management navigation for admins - `lang/en/navigation.php` - Added navigation translations for user management - `lang/ar/navigation.php` - Added Arabic navigation translations for user management ### Change Log | Date | Change | Files | |------|--------|-------| | 2025-12-26 | Added User model scopes for individual and company clients | app/Models/User.php | | 2025-12-26 | Created bilingual translation files for clients module | lang/en/clients.php, lang/ar/clients.php | | 2025-12-26 | Created individual clients CRUD Volt components | resources/views/livewire/admin/clients/individual/*.blade.php | | 2025-12-26 | Added admin routes for individual clients management | routes/web.php | | 2025-12-26 | Added sidebar navigation for User Management | resources/views/components/layouts/app/sidebar.blade.php | | 2025-12-26 | Added navigation translations | lang/en/navigation.php, lang/ar/navigation.php | | 2025-12-26 | Created comprehensive test suite (32 tests) | tests/Feature/Admin/IndividualClientTest.php | ### Completion Notes - All CRUD operations implemented with class-based Volt components following existing patterns - Bilingual support complete for all form labels, messages, and navigation - Search supports partial match on name, email, and national_id - Filter by status (active/deactivated/all) with clear filters functionality - Pagination with 10/25/50 per page options, sorted by created_at desc by default - Audit logging (AdminLog) implemented for create and update operations - Client profile page shows consultation and timeline counts with summary stats - All 32 tests pass covering create, list, search, filter, edit, view, and authorization - Full test suite (200 tests) passes with no regressions - Code formatted with Laravel Pint ### Definition of Done Checklist - [x] Create individual client form works - [x] List view displays all individual clients - [x] Search and filter functional - [x] Edit client works with validation - [x] View profile shows complete information - [x] Duplicate prevention works (email and national_id unique validation) - [x] Audit logging implemented (AdminLog entries for create/update) - [x] Bilingual support complete - [x] Tests pass for all CRUD operations (32 tests) - [x] Code formatted with Pint ## QA Results ### Review Date: 2025-12-26 ### Reviewed By: Quinn (Test Architect) ### Risk Assessment **Risk Level: LOW-MEDIUM** - Not a security-critical feature (no auth/payment handling) - 32 tests added covering all CRUD operations - Diff is moderate (~700 lines across all new files) - First gate for this story (no previous FAIL) - 6 acceptance criteria sections with clear requirements ### Code Quality Assessment **Overall: EXCELLENT** The implementation follows Laravel/Livewire best practices consistently: 1. **Architecture & Patterns** - Class-based Volt components used correctly throughout - Proper use of `WithPagination` trait for list view - Clean separation of concerns with PHP logic in class block - Follows existing project patterns for admin components 2. **Code Structure** - Consistent file organization in `resources/views/livewire/admin/clients/individual/` - User model scopes (`scopeIndividual()`, `scopeCompanies()`) properly implemented - Clean route definitions using Volt::route() 3. **Validation** - Comprehensive rules for all form fields - Proper handling of unique constraints on edit (using `Rule::unique()->ignore()`) - Custom error messages for duplicate email/national_id 4. **Audit Logging** - AdminLog entries created for both create and update operations - Old and new values captured appropriately - IP address tracking implemented ### Refactoring Performed None required. Code is clean and follows project conventions. ### Compliance Check - Coding Standards: ✓ Pint passes with --dirty flag - Project Structure: ✓ Files in correct locations per story spec - Testing Strategy: ✓ 32 tests covering all acceptance criteria - All ACs Met: ✓ See traceability matrix below ### Requirements Traceability | Acceptance Criteria | Test Coverage | Status | |---------------------|---------------|--------| | AC1: Create form with all required fields | `admin can create individual client with all valid data`, field validation tests | ✓ | | AC2: Validation for all required fields | 5 tests for missing required fields | ✓ | | AC3: Duplicate email/National ID prevention | `cannot create client with duplicate email/national_id` | ✓ | | AC4: Password strength indicator | Optional per story - not implemented | ⚠️ Optional | | AC5: Success message on creation | Tested via redirect assertion | ✓ | | AC6: List view individual clients only | `index page displays only individual clients` | ✓ | | AC7: Columns display | Verified via component assertions | ✓ | | AC8: Pagination 10/25/50 | Component property `perPage` tested | ✓ | | AC9: Default sort by created_at desc | `clients sorted by created_at desc by default` | ✓ | | AC10: Search by name/email/National ID | 3 search tests with partial match | ✓ | | AC11: Filter by status | `can filter clients by active/deactivated status` | ✓ | | AC12: Real-time search with debounce | `wire:model.live.debounce.300ms` in template | ✓ | | AC13: Clear filters button | `clear filters resets search and filter` | ✓ | | AC14: Edit all client information | `can edit existing client information` | ✓ | | AC15: Cannot change user_type | Edit form doesn't expose user_type field | ✓ | | AC16: Edit validation same as create | `validation rules apply on edit` | ✓ | | AC17: Success message on update | Tested via session flash + redirect | ✓ | | AC18: View client profile | `profile page displays all client information` | ✓ | | AC19: Consultation history summary | `profile shows consultation count` | ✓ | | AC20: Timeline history summary | `profile shows timeline count` | ✓ | | AC21: Bilingual form labels | Translation files complete (en/ar) | ✓ | | AC22: Proper form validation display | Flux:error components used | ✓ | | AC23: Audit log entries | Tests verify AdminLog entries | ✓ | | AC24: Tests for CRUD operations | 32 tests pass | ✓ | ### Improvements Checklist All items completed by developer - no action required: - [x] Proper validation rules with custom messages - [x] Clean route structure with named routes - [x] Bilingual translations complete - [x] Sidebar navigation for admin users - [x] AdminLog entries for audit trail - [x] Proper eager loading with loadCount() for profile stats ### Security Review **Status: PASS** 1. **Authorization**: Routes properly protected by `admin` middleware 2. **Authentication**: Tests verify non-admin and unauthenticated access blocked 3. **Data Validation**: All inputs validated server-side before processing 4. **Password Handling**: Uses `Hash::make()` for password storage (proper bcrypt) 5. **Sensitive Data**: national_id marked as hidden in User model ### Performance Considerations **Status: PASS** 1. **N+1 Prevention**: Profile page uses `loadCount()` for relationship counts 2. **Pagination**: Implemented with configurable per-page options 3. **Search**: Uses database-level filtering, not PHP array filtering 4. **Eager Loading**: Properly scoped queries with when() clauses ### Maintainability Assessment **Status: PASS** 1. **Single Responsibility**: Each component handles one view/action 2. **DRY**: Translation keys reused across components 3. **Testability**: All operations fully testable via Volt::test() 4. **Documentation**: Code is self-documenting with clear method names ### Files Modified During Review None. No refactoring was necessary. ### Gate Status Gate: **PASS** → docs/qa/gates/2.1-individual-client-account-management.yml ### Recommended Status ✓ **Ready for Done** - All acceptance criteria met, comprehensive test coverage, no blocking issues found. ### Future Recommendations for Dev Agent The following items are **not blocking** but should be considered for future implementation: 1. **Password Strength Indicator (Optional)** - **File:** `resources/views/livewire/admin/clients/individual/create.blade.php` - **Description:** AC4 in the story marked this as optional. Consider adding a visual password strength indicator (e.g., weak/medium/strong) using JavaScript or a Livewire reactive property. - **Priority:** Low 2. **Delete Client Functionality** - **File:** `resources/views/livewire/admin/clients/individual/index.blade.php` - **Description:** The current story scope covers create, view, edit, and search only. Translation keys for delete already exist (`clients.delete`, `clients.client_deleted`). When requirements are clarified, add a delete action with confirmation modal and appropriate AdminLog entry. - **Priority:** Medium - implement when a future story requires it - **Considerations:** - Soft delete vs hard delete decision needed - Handle cascading relationships (consultations, timelines) - Add authorization check before deletion - Create test coverage for delete operation