8.1 KiB
8.1 KiB
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_logstable 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
// In User model
public function scopeIndividual($query)
{
return $query->where('user_type', 'individual');
}
Volt Component Structure
<?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
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
// 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
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
userstable (user_type, national_id, status fields) andadmin_logstable - 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