added epic and stories for potential clients
This commit is contained in:
@@ -0,0 +1,324 @@
|
||||
# Story 15.3: CRUD Operations for Potential Clients
|
||||
|
||||
## Story
|
||||
|
||||
**As an** admin
|
||||
**I want to** create, view, edit, and delete potential clients
|
||||
**So that** I can fully manage my prospective client records
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### AC1: Create Form Access
|
||||
|
||||
**Given** the admin is on the potential clients list
|
||||
**When** clicking "Add Potential Client"
|
||||
**Then** navigate to `/admin/potential-clients/create`
|
||||
**And** display the create form
|
||||
|
||||
### AC2: Create Form Fields
|
||||
|
||||
**Given** the admin is on the create form
|
||||
**When** the form is displayed
|
||||
**Then** show the following fields:
|
||||
- Type (required) - dropdown with Individual, Company, Agency
|
||||
- Name (optional) - text input
|
||||
- Phone (optional) - text input
|
||||
- Email (optional) - email input
|
||||
- Address (optional) - textarea
|
||||
- Social Media (optional) - text input (URL or handle)
|
||||
- Website (optional) - text input (URL)
|
||||
- Notes (optional) - textarea
|
||||
|
||||
### AC3: Create Submission
|
||||
|
||||
**Given** the admin fills the create form
|
||||
**When** submitting with valid data
|
||||
**Then** create a new potential client record
|
||||
**And** show success message: "Potential client created successfully" / "تم إنشاء العميل المحتمل بنجاح"
|
||||
**And** redirect to potential clients list
|
||||
|
||||
### AC4: Create Validation
|
||||
|
||||
**Given** the admin submits the create form
|
||||
**When** type is not selected
|
||||
**Then** show validation error: "Please select a type" / "يرجى اختيار النوع"
|
||||
|
||||
**When** email is provided but invalid format
|
||||
**Then** show validation error on email field
|
||||
|
||||
**When** website is provided but invalid URL format
|
||||
**Then** show validation error on website field
|
||||
|
||||
### AC5: View Page
|
||||
|
||||
**Given** a potential client exists
|
||||
**When** the admin clicks the view icon from the list
|
||||
**Then** navigate to `/admin/potential-clients/{id}`
|
||||
**And** display all potential client information in a clean layout
|
||||
**And** show "Edit" and "Delete" action buttons
|
||||
**And** show "Back to Potential Clients" navigation
|
||||
|
||||
### AC6: View Page Display
|
||||
|
||||
**Given** the admin is viewing a potential client
|
||||
**When** the page loads
|
||||
**Then** display:
|
||||
- Type with colored badge
|
||||
- All contact information (showing "Not provided" / "غير متوفر" for empty fields)
|
||||
- Notes section (if provided)
|
||||
- Created date
|
||||
- Last updated date
|
||||
|
||||
### AC7: Edit Form Access
|
||||
|
||||
**Given** the admin is viewing a potential client
|
||||
**When** clicking "Edit"
|
||||
**Then** navigate to `/admin/potential-clients/{id}/edit`
|
||||
**And** pre-populate form with existing data
|
||||
|
||||
**Given** the admin is on the list page
|
||||
**When** clicking the edit icon
|
||||
**Then** navigate directly to the edit form
|
||||
|
||||
### AC8: Edit Form Submission
|
||||
|
||||
**Given** the admin modifies the edit form
|
||||
**When** submitting with valid data
|
||||
**Then** update the potential client record
|
||||
**And** show success message: "Potential client updated successfully" / "تم تحديث العميل المحتمل بنجاح"
|
||||
**And** redirect to the view page
|
||||
|
||||
### AC9: Delete Confirmation
|
||||
|
||||
**Given** the admin is viewing a potential client
|
||||
**When** clicking "Delete"
|
||||
**Then** show a confirmation modal with:
|
||||
- Warning message: "Are you sure you want to delete this potential client?" / "هل أنت متأكد من حذف هذا العميل المحتمل؟"
|
||||
- Potential client name displayed
|
||||
- "Cancel" and "Delete" buttons
|
||||
|
||||
**Given** the admin is on the list page
|
||||
**When** clicking the delete icon
|
||||
**Then** show the same confirmation modal
|
||||
|
||||
### AC10: Delete Execution
|
||||
|
||||
**Given** the delete confirmation modal is shown
|
||||
**When** the admin confirms deletion
|
||||
**Then** delete the potential client record
|
||||
**And** close the modal
|
||||
**And** show success message: "Potential client deleted successfully" / "تم حذف العميل المحتمل بنجاح"
|
||||
**And** redirect to list (if on view page) or refresh list (if on list page)
|
||||
|
||||
### AC11: RTL Support
|
||||
|
||||
**Given** Arabic language is selected
|
||||
**When** viewing create/edit/view pages
|
||||
**Then** all forms and layouts align correctly right-to-left
|
||||
|
||||
### AC12: Cancel Actions
|
||||
|
||||
**Given** the admin is on create or edit form
|
||||
**When** clicking "Cancel"
|
||||
**Then** navigate back to the previous page (list or view)
|
||||
**And** discard unsaved changes
|
||||
|
||||
## Technical Notes
|
||||
|
||||
### Files to Create
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `resources/views/livewire/admin/potential-clients/create.blade.php` | Create form component |
|
||||
| `resources/views/livewire/admin/potential-clients/show.blade.php` | View page component |
|
||||
| `resources/views/livewire/admin/potential-clients/edit.blade.php` | Edit form component |
|
||||
|
||||
### Files to Modify
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `routes/web.php` | Add create, show, edit routes |
|
||||
| `resources/views/livewire/admin/potential-clients/index.blade.php` | Add delete modal |
|
||||
| `lang/en/potential-clients.php` | Add CRUD translations |
|
||||
| `lang/ar/potential-clients.php` | Add CRUD translations |
|
||||
|
||||
### Routes
|
||||
|
||||
```php
|
||||
// Add to admin routes group
|
||||
Route::get('/admin/potential-clients/create', /* component */)->name('admin.potential-clients.create');
|
||||
Route::get('/admin/potential-clients/{potentialClient}', /* component */)->name('admin.potential-clients.show');
|
||||
Route::get('/admin/potential-clients/{potentialClient}/edit', /* component */)->name('admin.potential-clients.edit');
|
||||
```
|
||||
|
||||
### Create Component Structure
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use App\Enums\PotentialClientType;
|
||||
use App\Models\PotentialClient;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
public string $type = '';
|
||||
public string $name = '';
|
||||
public string $phone = '';
|
||||
public string $email = '';
|
||||
public string $address = '';
|
||||
public string $social_media = '';
|
||||
public string $website = '';
|
||||
public string $notes = '';
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'type' => ['required', 'in:individual,company,agency'],
|
||||
'name' => ['nullable', 'string', 'max:255'],
|
||||
'phone' => ['nullable', 'string', 'max:50'],
|
||||
'email' => ['nullable', 'email', 'max:255'],
|
||||
'address' => ['nullable', 'string', 'max:1000'],
|
||||
'social_media' => ['nullable', 'string', 'max:255'],
|
||||
'website' => ['nullable', 'url', 'max:255'],
|
||||
'notes' => ['nullable', 'string', 'max:5000'],
|
||||
];
|
||||
}
|
||||
|
||||
public function create(): void
|
||||
{
|
||||
$validated = $this->validate();
|
||||
|
||||
PotentialClient::create($validated);
|
||||
|
||||
session()->flash('success', __('potential-clients.created_success'));
|
||||
$this->redirect(route('admin.potential-clients.index'), navigate: true);
|
||||
}
|
||||
|
||||
public function with(): array
|
||||
{
|
||||
return [
|
||||
'types' => PotentialClientType::cases(),
|
||||
];
|
||||
}
|
||||
}; ?>
|
||||
```
|
||||
|
||||
### Show Component Structure
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use App\Models\PotentialClient;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
public PotentialClient $potentialClient;
|
||||
|
||||
public bool $showDeleteModal = false;
|
||||
|
||||
public function confirmDelete(): void
|
||||
{
|
||||
$this->showDeleteModal = true;
|
||||
}
|
||||
|
||||
public function delete(): void
|
||||
{
|
||||
$this->potentialClient->delete();
|
||||
|
||||
session()->flash('success', __('potential-clients.deleted_success'));
|
||||
$this->redirect(route('admin.potential-clients.index'), navigate: true);
|
||||
}
|
||||
}; ?>
|
||||
```
|
||||
|
||||
### Additional Translations
|
||||
|
||||
```php
|
||||
// Add to lang/en/potential-clients.php
|
||||
'create_potential_client' => 'Create Potential Client',
|
||||
'edit_potential_client' => 'Edit Potential Client',
|
||||
'potential_client_details' => 'Potential Client Details',
|
||||
'back_to_list' => 'Back to Potential Clients',
|
||||
'not_provided' => 'Not provided',
|
||||
'created_success' => 'Potential client created successfully',
|
||||
'updated_success' => 'Potential client updated successfully',
|
||||
'deleted_success' => 'Potential client deleted successfully',
|
||||
'delete_confirm_title' => 'Delete Potential Client',
|
||||
'delete_confirm_message' => 'Are you sure you want to delete this potential client?',
|
||||
'cancel' => 'Cancel',
|
||||
'save' => 'Save',
|
||||
'create' => 'Create',
|
||||
'contact_information' => 'Contact Information',
|
||||
'additional_information' => 'Additional Information',
|
||||
'type_required' => 'Please select a type',
|
||||
|
||||
// Add to lang/ar/potential-clients.php
|
||||
'create_potential_client' => 'إنشاء عميل محتمل',
|
||||
'edit_potential_client' => 'تعديل العميل المحتمل',
|
||||
'potential_client_details' => 'تفاصيل العميل المحتمل',
|
||||
'back_to_list' => 'العودة للقائمة',
|
||||
'not_provided' => 'غير متوفر',
|
||||
'created_success' => 'تم إنشاء العميل المحتمل بنجاح',
|
||||
'updated_success' => 'تم تحديث العميل المحتمل بنجاح',
|
||||
'deleted_success' => 'تم حذف العميل المحتمل بنجاح',
|
||||
'delete_confirm_title' => 'حذف العميل المحتمل',
|
||||
'delete_confirm_message' => 'هل أنت متأكد من حذف هذا العميل المحتمل؟',
|
||||
'cancel' => 'إلغاء',
|
||||
'save' => 'حفظ',
|
||||
'create' => 'إنشاء',
|
||||
'contact_information' => 'معلومات الاتصال',
|
||||
'additional_information' => 'معلومات إضافية',
|
||||
'type_required' => 'يرجى اختيار النوع',
|
||||
```
|
||||
|
||||
### Delete Modal (using Flux)
|
||||
|
||||
```blade
|
||||
<flux:modal name="delete-potential-client" class="min-w-[22rem]">
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<flux:heading size="lg">{{ __('potential-clients.delete_confirm_title') }}</flux:heading>
|
||||
<flux:text class="mt-2">{{ __('potential-clients.delete_confirm_message') }}</flux:text>
|
||||
<flux:text class="mt-2 font-medium">{{ $potentialClient->name ?? __('potential-clients.not_provided') }}</flux:text>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<flux:spacer />
|
||||
<flux:button variant="ghost" x-on:click="$flux.modal('delete-potential-client').close()">
|
||||
{{ __('potential-clients.cancel') }}
|
||||
</flux:button>
|
||||
<flux:button variant="danger" wire:click="delete">
|
||||
{{ __('potential-clients.delete') }}
|
||||
</flux:button>
|
||||
</div>
|
||||
</div>
|
||||
</flux:modal>
|
||||
```
|
||||
|
||||
## Dev Checklist
|
||||
|
||||
- [ ] Add routes for create, show, edit pages
|
||||
- [ ] Create `create.blade.php` component with form
|
||||
- [ ] Create `show.blade.php` component with details display
|
||||
- [ ] Create `edit.blade.php` component with pre-populated form
|
||||
- [ ] Add delete confirmation modal to show page
|
||||
- [ ] Add delete functionality to list page (inline delete)
|
||||
- [ ] Implement form validation rules
|
||||
- [ ] Add success flash messages
|
||||
- [ ] Add English translations for CRUD operations
|
||||
- [ ] Add Arabic translations for CRUD operations
|
||||
- [ ] Test create flow
|
||||
- [ ] Test edit flow
|
||||
- [ ] Test delete flow
|
||||
- [ ] Test validation errors
|
||||
- [ ] Test RTL layout
|
||||
- [ ] Write feature tests for all CRUD operations
|
||||
|
||||
## Estimation
|
||||
|
||||
**Complexity:** Medium
|
||||
**Risk:** Low - Follows established patterns
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Story 15.1 (Database & Model) must be completed
|
||||
- Story 15.2 (List & Filter) must be completed
|
||||
Reference in New Issue
Block a user