libra/docs/stories/story-15.3-crud-operations.md

11 KiB

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

// 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

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

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

// 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)

<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