Commit a961e76d authored by Mahmoud Aglan's avatar Mahmoud Aglan

Add sortable columns to all list views + trainer salary editing

- Created WithSorting trait (shared across all 35 list components)
- Created <x-ui.sort-header> Blade component with arrow indicators
- All table lists now support click-to-sort on key columns (persisted via URL)
- Trainer edit form: added salary amount + frequency fields from Employee model
- Trainer edit form: person data (name, national_id, phone) already included
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent bbd5895f
......@@ -5,6 +5,7 @@
use App\Domain\HR\Models\Trainer;
use App\Domain\Training\Models\Activity;
use App\Domain\Training\Services\ActivityService;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -14,12 +15,17 @@
#[Title('الأنشطة')]
class ActivityList extends Component
{
use WithSorting;
#[Url]
public string $search = '';
#[Url]
public string $category = '';
public string $sortBy = 'name_ar';
public string $sortDir = 'asc';
public function updatedSearch(): void
{
// Reset not needed without pagination, but keeping for consistency
......@@ -49,8 +55,7 @@ public function render()
->when($this->search, fn ($q) => $q->where('name_ar', 'ilike', "%{$this->search}%")
->orWhere('name', 'ilike', "%{$this->search}%"))
->when($this->category, fn ($q) => $q->where('category', $this->category))
->orderBy('sort_order')
->orderBy('name_ar');
->orderBy($this->sortBy, $this->sortDir);
$trainersByActivity = [];
foreach (Trainer::with('employee.person')->where('status', 'active')->get() as $trainer) {
......
......@@ -11,6 +11,7 @@
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Models\TrainingSession;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use App\Models\User;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
......@@ -22,7 +23,7 @@
#[Title('التكليفات')]
class AssignmentList extends Component
{
use WithPagination, UsesBranchScope, AppliesRoleScope;
use WithPagination, UsesBranchScope, AppliesRoleScope, WithSorting;
protected string $scopePermission = 'assignments.list';
......@@ -131,7 +132,7 @@ public function render()
}
})
->when($this->userId, fn ($q) => $q->where('user_id', $this->userId))
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -5,6 +5,7 @@
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Domain\Training\Models\TrainingSession;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -15,7 +16,10 @@
#[Title('سجل الحضور')]
class AttendanceList extends Component
{
use WithPagination, UsesBranchScope, AppliesRoleScope;
use WithPagination, UsesBranchScope, AppliesRoleScope, WithSorting;
public string $sortBy = 'session_date';
public string $sortDir = 'desc';
protected string $scopePermission = 'attendance.list';
......@@ -82,8 +86,7 @@ public function render()
->where('end_time', '<', now()->format('H:i:s'))
->whereDoesntHave('attendanceRecords', fn ($ar) => $ar->whereNotIn('status', ['expected']));
})
->orderByDesc('session_date')
->orderByDesc('start_time');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -3,6 +3,7 @@
namespace App\Livewire\Audit;
use App\Domain\Audit\Models\AuditLog;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -13,7 +14,7 @@
#[Title('سجل التدقيق')]
class AuditLogList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
#[Url]
public string $search = '';
......@@ -76,7 +77,7 @@ public function render()
->when($this->actionFilter, fn ($q) => $q->where('action', $this->actionFilter))
->when($this->dateFrom, fn ($q) => $q->whereDate('created_at', '>=', $this->dateFrom))
->when($this->dateTo, fn ($q) => $q->whereDate('created_at', '<=', $this->dateTo))
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
return view('livewire.audit.audit-log-list', [
'logs' => $query->paginate(25),
......
......@@ -3,6 +3,7 @@
namespace App\Livewire\Branches;
use App\Domain\Identity\Models\Branch;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;
......@@ -12,11 +13,14 @@
#[Title('الفروع')]
class BranchList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
public string $search = '';
public bool $showInactive = false;
public string $sortBy = 'name_ar';
public string $sortDir = 'asc';
public function updatedSearch(): void
{
$this->resetPage();
......@@ -40,8 +44,7 @@ public function render()
->orWhere('name', 'ilike', "%{$this->search}%")
->orWhere('code', 'ilike', "%{$this->search}%"))
->when(!$this->showInactive, fn ($q) => $q->where('is_active', true))
->orderByDesc('is_main')
->orderBy('name_ar');
->orderBy($this->sortBy, $this->sortDir);
return view('livewire.branches.branch-list', [
'branches' => $query->paginate(15),
......
......@@ -5,6 +5,7 @@
use App\Domain\Financial\Models\CashSession;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -15,10 +16,17 @@
#[Title('الورديات النقدية')]
class CashSessionList extends Component
{
use WithPagination, UsesBranchScope, AppliesRoleScope;
use WithPagination, WithSorting, UsesBranchScope, AppliesRoleScope;
protected string $scopePermission = 'cash_sessions.list';
public function mount(): void
{
if (! request()->has('sortBy')) {
$this->sortBy = 'opened_at';
}
}
#[Url]
public string $status = '';
......@@ -35,7 +43,7 @@ public function render()
->with(['user', 'branch'])
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->when($this->status, fn ($q) => $q->where('status', $this->status))
->orderByDesc('opened_at');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
<?php
namespace App\Livewire\Concerns;
use Livewire\Attributes\Url;
trait WithSorting
{
#[Url]
public string $sortBy = 'created_at';
#[Url]
public string $sortDir = 'desc';
public function sortColumn(string $column): void
{
if ($this->sortBy === $column) {
$this->sortDir = $this->sortDir === 'asc' ? 'desc' : 'asc';
} else {
$this->sortBy = $column;
$this->sortDir = 'asc';
}
}
}
......@@ -5,6 +5,7 @@
use App\Domain\Document\Enums\DocumentStatus;
use App\Domain\Document\Enums\DocumentType;
use App\Domain\Document\Models\Document;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -15,7 +16,7 @@
#[Title('اعتماد المستندات')]
class DocumentApprovalList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
#[Url]
public string $search = '';
......@@ -46,7 +47,7 @@ public function render()
$this->authorize('documents.approve');
$query = Document::with(['documentable', 'uploader'])
->latest();
->orderBy($this->sortBy, $this->sortDir);
if ($this->status) {
$query->where('status', $this->status);
......
......@@ -9,6 +9,7 @@
use App\Domain\Training\Services\EnrollmentService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -19,7 +20,9 @@
#[Title('التسجيلات')]
class EnrollmentList extends Component
{
use WithPagination, UsesBranchScope, AppliesRoleScope;
use WithPagination, WithSorting, UsesBranchScope, AppliesRoleScope;
public string $sortBy = 'enrollment_date';
protected string $scopePermission = 'enrollments.list';
......@@ -97,7 +100,7 @@ public function render()
->when($this->programFilter, fn ($q) => $q->where('training_program_id', $this->programFilter))
->when($this->groupFilter, fn ($q) => $q->where('training_group_id', $this->groupFilter))
->when($this->paymentFilter, fn ($q) => $q->where('payment_status', $this->paymentFilter))
->orderByDesc('enrollment_date');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -3,6 +3,7 @@
namespace App\Livewire\Evaluations;
use App\Domain\Training\Models\EvaluationCriterion;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;
......@@ -12,7 +13,10 @@
#[Title('معايير التقييم')]
class EvaluationCriteriaList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
public string $sortBy = 'sort_order';
public string $sortDir = 'asc';
public string $search = '';
......@@ -125,8 +129,7 @@ public function render()
{
$query = EvaluationCriterion::query()
->when($this->search, fn ($q) => $q->where('name_ar', 'ilike', "%{$this->search}%"))
->orderBy('sort_order')
->orderBy('name_ar');
->orderBy($this->sortBy, $this->sortDir);
return view('livewire.evaluations.evaluation-criteria-list', [
'criteria' => $query->paginate(20),
......
......@@ -7,6 +7,7 @@
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Models\TrainingProgram;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -17,10 +18,13 @@
#[Title('التقييمات')]
class EvaluationList extends Component
{
use WithPagination, AppliesRoleScope;
use WithPagination, AppliesRoleScope, WithSorting;
protected string $scopePermission = 'evaluations.list';
public string $sortBy = 'evaluation_date';
public string $sortDir = 'desc';
#[Url]
public string $search = '';
......@@ -67,7 +71,7 @@ public function render()
->when($this->status, fn ($q) => $q->where('status', $this->status))
->when($this->programFilter, fn ($q) => $q->whereHas('group', fn ($gq) => $gq->where('training_program_id', $this->programFilter)))
->when($this->groupId, fn ($q) => $q->where('training_group_id', $this->groupId))
->orderByDesc('evaluation_date');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -5,6 +5,7 @@
use App\Domain\Event\Enums\EventStatus;
use App\Domain\Event\Enums\EventType;
use App\Domain\Event\Models\Event;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -15,7 +16,7 @@
#[Title('الأحداث')]
class EventList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
#[Url]
public string $search = '';
......@@ -29,6 +30,10 @@ class EventList extends Component
public function mount(): void
{
$this->authorize('events.list');
if (! request()->has('sortBy')) {
$this->sortBy = 'starts_at';
}
}
public function updatedSearch(): void
......@@ -53,7 +58,7 @@ public function render()
->when($this->status, fn ($q) => $q->where('status', $this->status))
->when($this->type, fn ($q) => $q->where('type', $this->type))
->withCount('registrations')
->orderByDesc('starts_at')
->orderBy($this->sortBy, $this->sortDir)
->paginate(15);
return view('livewire.events.event-list', [
......
......@@ -6,6 +6,7 @@
use App\Domain\Event\Models\EventRegistration;
use App\Domain\Event\Services\EventRegistrationService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -17,7 +18,7 @@
#[Title('تسجيلات الحدث')]
class EventRegistrationList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
public Event $event;
......@@ -198,7 +199,7 @@ public function render()
});
})
->when($this->status, fn ($q) => $q->where('status', $this->status))
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
return view('livewire.events.event-registration-list', [
'registrations' => $query->paginate(25),
......
......@@ -10,6 +10,7 @@
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -20,10 +21,18 @@
#[Title('المنشآت')]
class FacilityList extends Component
{
use WithPagination, UsesBranchScope, AppliesRoleScope;
use WithPagination, WithSorting, UsesBranchScope, AppliesRoleScope;
protected string $scopePermission = 'facilities.list';
public function mount(): void
{
if (! request()->has('sortBy')) {
$this->sortBy = 'name_ar';
$this->sortDir = 'asc';
}
}
#[Url]
public string $search = '';
......@@ -84,8 +93,7 @@ public function render()
})
->when($this->status, fn ($q) => $q->where('status', $this->status))
->when($this->type, fn ($q) => $q->where('type', $this->type))
->orderBy('sort_order')
->orderBy('name_ar');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -6,6 +6,7 @@
use App\Domain\Financial\Models\Expense;
use App\Domain\Financial\Services\ExpenseService;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -16,7 +17,9 @@
#[Title('سجل المصروفات')]
class ExpenseList extends Component
{
use WithPagination, UsesBranchScope;
use WithPagination, UsesBranchScope, WithSorting;
public string $sortBy = 'expense_date';
#[Url]
public string $search = '';
......@@ -87,7 +90,7 @@ public function render()
$q->where('description', 'ilike', "%{$this->search}%")
->orWhere('recipient_name', 'ilike', "%{$this->search}%");
}))
->orderByDesc('expense_date')
->orderBy($this->sortBy, $this->sortDir)
->paginate(20);
$totalAmount = Expense::query()
......
......@@ -4,6 +4,7 @@
use App\Domain\Financial\Models\FacilityRentPayment;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -14,7 +15,10 @@
#[Title('سجل إيجارات المنشآت')]
class FacilityRentList extends Component
{
use WithPagination, UsesBranchScope;
use WithPagination, UsesBranchScope, WithSorting;
public string $sortBy = 'payment_date';
public string $sortDir = 'desc';
#[Url]
public string $search = '';
......@@ -48,7 +52,7 @@ public function render()
->orWhere('recipient_name', 'ilike', "%{$this->search}%")
->orWhere('bank_name', 'ilike', "%{$this->search}%");
}))
->orderByDesc('payment_date')
->orderBy($this->sortBy, $this->sortDir)
->paginate(20);
$totalAmount = FacilityRentPayment::query()
......
......@@ -6,6 +6,7 @@
use App\Domain\HR\Enums\EmploymentType;
use App\Domain\HR\Models\Employee;
use App\Domain\Identity\Services\PermissionService;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -16,7 +17,7 @@
#[Title('الموظفين')]
class EmployeeList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
#[Url]
public string $search = '';
......@@ -53,7 +54,7 @@ public function updatedBranchId(): void
public function render()
{
$query = Employee::with(['person', 'branch'])
->latest();
->orderBy($this->sortBy, $this->sortDir);
$query = app(PermissionService::class)->applyScope($query, auth()->user(), 'employees.list');
......
......@@ -29,6 +29,10 @@ class TrainerForm extends Component
public string $personPhone = '';
public string $personNationalId = '';
// Employee salary fields (editable when editing)
public ?string $salaryAmount = null;
public string $salaryFrequency = 'monthly';
// Form fields
public string $bio = '';
public string $bioAr = '';
......@@ -67,6 +71,12 @@ public function mount(?Trainer $trainer = null): void
$this->personPhone = $person?->phone ?? '';
$this->personNationalId = $person?->national_id ?? '';
// Salary data
if ($trainer->employee) {
$this->salaryAmount = $trainer->employee->salary_amount ? (string) ($trainer->employee->salary_amount / 100) : null;
$this->salaryFrequency = $trainer->employee->salary_frequency?->value ?? 'monthly';
}
$this->bio = $trainer->bio ?? '';
$this->bioAr = $trainer->bio_ar ?? '';
$this->specializations = $trainer->specializations ?? [];
......@@ -99,6 +109,8 @@ public function rules(): array
'personName' => 'nullable|string|max:100',
'personPhone' => 'nullable|string|max:20',
'personNationalId' => 'nullable|string|max:30',
'salaryAmount' => 'nullable|numeric|min:0',
'salaryFrequency' => 'required|in:monthly,biweekly,weekly,daily,hourly',
] : [];
return array_merge($personRules, [
......@@ -126,6 +138,10 @@ public function messages(): array
'personName.max' => 'الاسم بالإنجليزية لا يمكن أن يتجاوز 100 حرف',
'personPhone.max' => 'رقم الهاتف لا يمكن أن يتجاوز 20 حرف',
'personNationalId.max' => 'الرقم القومي لا يمكن أن يتجاوز 30 حرف',
'salaryAmount.numeric' => 'المرتب يجب أن يكون رقماً',
'salaryAmount.min' => 'المرتب لا يمكن أن يكون بالسالب',
'salaryFrequency.required' => 'دورية الراتب مطلوبة',
'salaryFrequency.in' => 'دورية الراتب غير صالحة',
'employeeId.required' => 'يجب اختيار موظف',
'employeeId.exists' => 'الموظف المختار غير موجود',
'sports.required' => 'يجب اختيار نشاط واحد على الأقل',
......@@ -172,6 +188,14 @@ public function save(TrainerService $service): void
]);
}
// Update salary data
if ($this->trainer->employee) {
$this->trainer->employee->update([
'salary_amount' => $this->salaryAmount ? (int) round((float) $this->salaryAmount * 100) : null,
'salary_frequency' => $this->salaryFrequency,
]);
}
session()->flash('success', __('تم تحديث بيانات المدرب بنجاح'));
} else {
$employee = Employee::findOrFail($this->employeeId);
......
......@@ -7,6 +7,7 @@
use App\Domain\HR\Models\Trainer;
use App\Domain\Identity\Services\PermissionService;
use App\Domain\Training\Models\Activity;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -17,7 +18,7 @@
#[Title('المدربين')]
class TrainerList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
#[Url]
public string $search = '';
......@@ -46,7 +47,7 @@ public function updatedCompensationModel(): void
public function render()
{
$query = Trainer::with(['employee.person', 'employee.branch', 'person'])
->latest();
->orderBy($this->sortBy, $this->sortDir);
$query = app(PermissionService::class)->applyScope($query, auth()->user(), 'trainers.list');
......
......@@ -7,6 +7,7 @@
use App\Domain\Inventory\Services\KitService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -17,7 +18,7 @@
#[Title('الأطقم')]
class KitList extends Component
{
use WithPagination, AppliesRoleScope;
use WithPagination, AppliesRoleScope, WithSorting;
protected string $scopePermission = 'inventory.manage';
......@@ -139,7 +140,7 @@ public function render()
$q->where('is_active', false);
}
})
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -6,6 +6,7 @@
use App\Domain\Inventory\Models\Product;
use App\Domain\Inventory\Models\Warehouse;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Livewire\Concerns\WithSorting;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
......@@ -17,7 +18,7 @@
#[Title('حركة المخزون')]
class MovementList extends Component
{
use WithPagination, UsesBranchScope;
use WithPagination, UsesBranchScope, WithSorting;
#[Url]
public string $search = '';
......@@ -98,7 +99,7 @@ public function render()
->when($this->movementType, fn ($q) => $q->where('inventory_movements.movement_type', $this->movementType))
->when($this->direction, fn ($q) => $q->where('inventory_movements.direction', $this->direction))
->when($this->warehouseFilter, fn ($q) => $q->where('inventory_movements.warehouse_id', $this->warehouseFilter))
->orderByDesc('inventory_movements.created_at');
->orderBy('inventory_movements.' . $this->sortBy, $this->sortDir);
$allTypes = [
'purchase_received' => 'استلام مشتريات',
......
......@@ -6,6 +6,7 @@
use App\Domain\Inventory\Models\ProductCategory;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -16,7 +17,7 @@
#[Title('المنتجات')]
class ProductList extends Component
{
use WithPagination, UsesBranchScope, AppliesRoleScope;
use WithPagination, UsesBranchScope, AppliesRoleScope, WithSorting;
protected string $scopePermission = 'inventory.list';
......@@ -91,7 +92,7 @@ public function render()
->where('min_stock_level', '>', 0)
->whereHas('inventoryLevels', fn ($il) => $il->whereRaw('quantity_on_hand <= (SELECT min_stock_level FROM products WHERE products.id = inventory_levels.product_id)'));
})
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -9,6 +9,7 @@
use App\Domain\Shared\Exceptions\InvalidStatusTransitionException;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -19,7 +20,7 @@
#[Title('أوامر الشراء')]
class PurchaseOrderList extends Component
{
use WithPagination, UsesBranchScope, AppliesRoleScope;
use WithPagination, WithSorting, UsesBranchScope, AppliesRoleScope;
protected string $scopePermission = 'inventory.manage';
......@@ -99,7 +100,7 @@ public function render()
});
})
->when($this->status, fn ($q) => $q->where('status', $this->status))
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -8,6 +8,7 @@
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Shared\Exceptions\InvalidStatusTransitionException;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -18,7 +19,7 @@
#[Title('الجرد المخزني')]
class StockCountList extends Component
{
use WithPagination, AppliesRoleScope;
use WithPagination, AppliesRoleScope, WithSorting;
protected string $scopePermission = 'inventory.manage';
......@@ -86,7 +87,7 @@ public function render()
});
})
->when($this->statusFilter, fn ($q) => $q->where('status', $this->statusFilter))
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -4,6 +4,7 @@
use App\Domain\Inventory\Models\Warehouse;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -14,11 +15,14 @@
#[Title('المستودعات')]
class WarehouseList extends Component
{
use WithPagination, UsesBranchScope;
use WithPagination, UsesBranchScope, WithSorting;
#[Url]
public string $search = '';
public string $sortBy = 'name_ar';
public string $sortDir = 'asc';
public function updatedSearch(): void
{
$this->resetPage();
......@@ -39,7 +43,7 @@ public function render()
->orWhere('code', 'ilike', "%{$search}%");
});
})
->orderBy('name_ar');
->orderBy($this->sortBy, $this->sortDir);
return view('livewire.inventory.warehouse-list', [
'warehouses' => $query->paginate(20),
......
......@@ -9,6 +9,7 @@
use App\Domain\Participant\Models\Participant;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -19,7 +20,7 @@
#[Title('الفواتير')]
class InvoiceList extends Component
{
use WithPagination, UsesBranchScope, AppliesRoleScope;
use WithPagination, WithSorting, UsesBranchScope, AppliesRoleScope;
protected string $scopePermission = 'invoices.list';
......@@ -87,8 +88,7 @@ public function render()
});
})
->when($this->status, fn ($q) => $q->where('status', $this->status))
->orderByDesc('paid_at')
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -5,6 +5,7 @@
use App\Domain\Notification\Enums\NotificationChannel;
use App\Domain\Notification\Enums\NotificationStatus;
use App\Domain\Notification\Models\NotificationLog;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -15,7 +16,7 @@
#[Title('سجل الإشعارات')]
class NotificationLogList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
#[Url]
public string $search = '';
......@@ -68,7 +69,7 @@ public function render()
->when($this->statusFilter, fn ($q) => $q->where('status', $this->statusFilter))
->when($this->dateFrom, fn ($q) => $q->whereDate('created_at', '>=', $this->dateFrom))
->when($this->dateTo, fn ($q) => $q->whereDate('created_at', '<=', $this->dateTo))
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
return view('livewire.notifications.notification-log-list', [
'logs' => $query->paginate(25),
......
......@@ -4,6 +4,7 @@
use App\Domain\Notification\Enums\NotificationChannel;
use App\Domain\Notification\Models\NotificationTemplate;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -14,7 +15,7 @@
#[Title('قوالب الإشعارات')]
class NotificationTemplateList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
#[Url]
public string $search = '';
......@@ -54,7 +55,7 @@ public function render()
});
})
->when($this->channelFilter, fn ($q) => $q->where('channel', $this->channelFilter))
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
return view('livewire.notifications.notification-template-list', [
'templates' => $query->paginate(20),
......
......@@ -6,6 +6,7 @@
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Domain\Training\Models\Activity;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -16,7 +17,7 @@
#[Title('المشتركين')]
class ParticipantList extends Component
{
use WithPagination, UsesBranchScope, AppliesRoleScope;
use WithPagination, WithSorting, UsesBranchScope, AppliesRoleScope;
protected string $scopePermission = 'participants.list';
......@@ -73,7 +74,7 @@ public function render()
->when($this->status, fn ($q) => $q->where('status', $this->status))
->when($this->activity, fn ($q) => $q->where('primary_activity_id', $this->activity))
->when($this->skillLevel, fn ($q) => $q->where('skill_level', $this->skillLevel))
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -4,6 +4,7 @@
use App\Domain\Identity\Models\Person;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\Layout;
......@@ -16,10 +17,18 @@
#[Title('السجل العام')]
class PersonList extends Component
{
use WithPagination, AppliesRoleScope;
use WithPagination, WithSorting, AppliesRoleScope;
protected string $scopePermission = 'people.list';
public function mount(): void
{
if (! request()->has('sortBy')) {
$this->sortBy = 'name_ar';
$this->sortDir = 'asc';
}
}
#[Url]
public string $search = '';
......@@ -75,7 +84,7 @@ public function render()
})
->when($this->gender, fn ($q) => $q->where('gender', $this->gender))
->when($this->classification, fn ($q) => $q->where('classification', $this->classification))
->orderBy('name_ar');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -3,6 +3,7 @@
namespace App\Livewire\Pricing;
use App\Domain\Pricing\Models\BasePrice;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -13,7 +14,7 @@
#[Title('الأسعار الأساسية')]
class BasePriceList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
#[Url]
public string $search = '';
......@@ -49,7 +50,7 @@ public function render()
->with(['branch', 'priceable'])
->when($this->search, fn ($q) => $q->where('name_ar', 'ilike', "%{$this->search}%"))
->when($this->activeFilter !== '', fn ($q) => $q->where('is_active', $this->activeFilter === '1'))
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
return view('livewire.pricing.base-price-list', [
'prices' => $query->paginate(20),
......
......@@ -4,6 +4,7 @@
use App\Domain\Pricing\Enums\PricingRuleType;
use App\Domain\Pricing\Models\PricingRule;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -14,7 +15,10 @@
#[Title('قواعد التسعير')]
class PricingRuleList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
public string $sortBy = 'priority';
public string $sortDir = 'asc';
#[Url]
public string $search = '';
......@@ -59,8 +63,7 @@ public function render()
->when($this->search, fn ($q) => $q->where('name_ar', 'ilike', "%{$this->search}%"))
->when($this->ruleType, fn ($q) => $q->where('rule_type', $this->ruleType))
->when($this->activeFilter !== '', fn ($q) => $q->where('is_active', $this->activeFilter === '1'))
->orderBy('priority')
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
return view('livewire.pricing.pricing-rule-list', [
'rules' => $query->paginate(20),
......
......@@ -4,6 +4,7 @@
use App\Domain\Pricing\Enums\PromotionType;
use App\Domain\Pricing\Models\Promotion;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -14,7 +15,7 @@
#[Title('العروض والكوبونات')]
class PromotionList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
#[Url]
public string $search = '';
......@@ -62,7 +63,7 @@ public function render()
}))
->when($this->type, fn ($q) => $q->where('type', $this->type))
->when($this->activeFilter !== '', fn ($q) => $q->where('is_active', $this->activeFilter === '1'))
->orderByDesc('created_at');
->orderBy($this->sortBy, $this->sortDir);
return view('livewire.pricing.promotion-list', [
'promotions' => $query->paginate(20),
......
......@@ -4,6 +4,7 @@
use App\Domain\Identity\Models\Role;
use App\Domain\Shared\Exceptions\DomainException;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;
......@@ -12,6 +13,11 @@
#[Title('الأدوار والصلاحيات')]
class RoleList extends Component
{
use WithSorting;
public string $sortBy = 'level';
public string $sortDir = 'desc';
public ?int $confirmingDeleteId = null;
public function confirmDelete(int $roleId): void
......@@ -60,7 +66,7 @@ public function deleteRole(int $roleId): void
public function render()
{
$roles = Role::withCount('users')
->orderBy('level', 'desc')
->orderBy($this->sortBy, $this->sortDir)
->get();
$actor = auth()->user();
......
......@@ -2,6 +2,7 @@
namespace App\Livewire\Users;
use App\Livewire\Concerns\WithSorting;
use App\Models\User;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
......@@ -13,7 +14,10 @@
#[Title('المستخدمين')]
class UserList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
public string $sortBy = 'name_ar';
public string $sortDir = 'asc';
#[Url]
public string $search = '';
......@@ -57,7 +61,7 @@ public function render()
})
->when($this->role, fn ($q) => $q->where('role_id', $this->role))
->when(!$this->showInactive, fn ($q) => $q->where('status', 'active'))
->orderBy('name_ar');
->orderBy($this->sortBy, $this->sortDir);
return view('livewire.users.user-list', [
'users' => $query->paginate(20),
......
......@@ -6,6 +6,7 @@
use App\Domain\Participant\Models\Participant;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -16,7 +17,9 @@
#[Title('المحافظ')]
class WalletList extends Component
{
use WithPagination, UsesBranchScope, AppliesRoleScope;
use WithPagination, UsesBranchScope, AppliesRoleScope, WithSorting;
public string $sortBy = 'balance';
protected string $scopePermission = 'wallets.list';
......@@ -54,7 +57,7 @@ public function render()
->when($this->activeFilter !== '', function ($q) {
$q->where('is_active', $this->activeFilter === '1');
})
->orderByDesc('balance');
->orderBy($this->sortBy, $this->sortDir);
$this->applyRoleScope($query);
......
......@@ -3,6 +3,7 @@
namespace App\Livewire\Website;
use App\Domain\Website\Models\ContactSubmission;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
......@@ -13,7 +14,7 @@
#[Title('رسائل التواصل')]
class ContactSubmissionList extends Component
{
use WithPagination;
use WithPagination, WithSorting;
#[Url]
public string $status = '';
......@@ -43,7 +44,7 @@ public function updatedStatus(): void
public function render()
{
$query = ContactSubmission::orderByDesc('created_at');
$query = ContactSubmission::orderBy($this->sortBy, $this->sortDir);
if ($this->status) {
$query->where('status', $this->status);
......
@props(['column', 'sortBy', 'sortDir', 'align' => 'start'])
<th {{ $attributes->merge(['class' => "px-4 py-3 text-{$align} font-medium text-gray-600"]) }}>
<button type="button" wire:click="sortColumn('{{ $column }}')"
class="inline-flex items-center gap-1 hover:text-gray-900 transition-colors">
{{ $slot }}
@if($sortBy === $column)
<svg class="w-3.5 h-3.5 {{ $sortDir === 'asc' ? '' : 'rotate-180' }}" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5.293 7.707a1 1 0 010-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 01-1.414 1.414L10 4.414 6.707 7.707a1 1 0 01-1.414 0z" clip-rule="evenodd"/></svg>
@else
<svg class="w-3.5 h-3.5 text-gray-300" fill="currentColor" viewBox="0 0 20 20"><path d="M7 7l3-3 3 3m0 6l-3 3-3-3"/></svg>
@endif
</button>
</th>
......@@ -62,8 +62,8 @@ class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 f
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المستخدم') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('مُكلَّف بـ') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('النطاق') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('تاريخ البداية') }}</th>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<x-ui.sort-header column="start_date" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('تاريخ البداية') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('تاريخ النهاية') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
......
......@@ -66,9 +66,9 @@ class="w-full rounded-lg border-gray-300 shadow-sm focus:border-blue-500 focus:r
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('التاريخ') }}</th>
<x-ui.sort-header column="session_date" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('التاريخ') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('المجموعة') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('الوقت') }}</th>
<x-ui.sort-header column="start_time" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('الوقت') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('الإجمالي') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('حاضر/متأخر') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('غائب') }}</th>
......
......@@ -34,10 +34,10 @@ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الوقت') }}</th>
<x-ui.sort-header column="created_at" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('الوقت') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المستخدم') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الإجراء') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الكيان') }}</th>
<x-ui.sort-header column="action" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الإجراء') }}</x-ui.sort-header>
<x-ui.sort-header column="auditable_type" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('الكيان') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('ملخص التغييرات') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('تفاصيل') }}</th>
</tr>
......
......@@ -30,11 +30,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<table class="w-full text-sm" wire:loading.class="opacity-50 pointer-events-none">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">الفرع</th>
<x-ui.sort-header column="name_ar" :sortBy="$sortBy" :sortDir="$sortDir">الفرع</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">الكود</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">المدينة</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">الهاتف</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">الحالة</th>
<x-ui.sort-header column="is_main" :sortBy="$sortBy" :sortDir="$sortDir" align="center">الحالة</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">إجراءات</th>
</tr>
</thead>
......
......@@ -37,11 +37,11 @@ class="inline-flex items-center justify-center gap-2 px-4 py-2 bg-blue-600 text-
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المستخدم') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الفرع') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<th class="px-4 py-3 text-end font-medium text-gray-600">{{ __('رصيد الافتتاح') }}</th>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<x-ui.sort-header column="total_cash_in" :sortBy="$sortBy" :sortDir="$sortDir" align="end">{{ __('رصيد الافتتاح') }}</x-ui.sort-header>
<th class="px-4 py-3 text-end font-medium text-gray-600">{{ __('رصيد الإغلاق') }}</th>
<th class="px-4 py-3 text-end font-medium text-gray-600">{{ __('الفرق') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('وقت الفتح') }}</th>
<x-ui.sort-header column="opened_at" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('وقت الفتح') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('وقت الإغلاق') }}</th>
</tr>
</thead>
......
......@@ -67,9 +67,9 @@ class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 f
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المشترك') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المجموعة') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('البرنامج') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الدفع') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('تاريخ التسجيل') }}</th>
<x-ui.sort-header column="enrollment_date" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('تاريخ التسجيل') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......
......@@ -92,8 +92,8 @@ class="w-full rounded-lg border-gray-300 shadow-sm focus:border-blue-500 focus:r
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('المشترك') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('المجموعة') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('المقيّم') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('التاريخ') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('الدرجة') }}</th>
<x-ui.sort-header column="evaluation_date" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('التاريخ') }}</x-ui.sort-header>
<x-ui.sort-header column="overall_score" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('الدرجة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('الحالة') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500 uppercase">{{ __('إجراءات') }}</th>
</tr>
......
......@@ -16,7 +16,7 @@ class="inline-flex items-center gap-2 px-4 py-2.5 bg-blue-600 text-white rounded
{{-- Filters --}}
<div class="bg-white rounded-xl border border-gray-200 p-4 mb-6">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
<div>
<input type="text" wire:model.live.debounce.300ms="search"
placeholder="{{ __('بحث بالعنوان...') }}"
......@@ -38,6 +38,17 @@ class="w-full px-4 py-2.5 border border-gray-300 rounded-lg text-sm focus:ring-2
@endforeach
</select>
</div>
<div class="flex items-center gap-2">
<select wire:model.live="sortBy" class="flex-1 px-4 py-2.5 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
<option value="starts_at">{{ __('تاريخ البدء') }}</option>
<option value="status">{{ __('الحالة') }}</option>
<option value="created_at">{{ __('تاريخ الإنشاء') }}</option>
</select>
<button type="button" wire:click="sortColumn('{{ $sortBy }}')"
class="p-2.5 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors">
<svg class="w-4 h-4 text-gray-600 {{ $sortDir === 'asc' ? '' : 'rotate-180' }}" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5.293 7.707a1 1 0 010-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 01-1.414 1.414L10 4.414 6.707 7.707a1 1 0 01-1.414 0z" clip-rule="evenodd"/></svg>
</button>
</div>
</div>
</div>
......
......@@ -57,11 +57,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الاسم') }}</th>
<x-ui.sort-header column="name_ar" :sortBy="$sortBy" :sortDir="$sortDir" align="start">{{ __('الاسم') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('النوع') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الفرع') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('السعة') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="capacity" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('السعة') }}</x-ui.sort-header>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-end font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......
......@@ -54,13 +54,13 @@ class="w-full rounded-lg border-gray-300 text-sm py-2" placeholder="{{ __('إل
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b">
<tr>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('التاريخ') }}</th>
<x-ui.sort-header column="expense_date" :sortBy="$sortBy" :sortDir="$sortDir" class="text-xs text-gray-500">{{ __('التاريخ') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('الفئة') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('الوصف') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('المبلغ') }}</th>
<x-ui.sort-header column="amount" :sortBy="$sortBy" :sortDir="$sortDir" class="text-xs text-gray-500">{{ __('المبلغ') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('المستلم') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('طريقة الدفع') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('الحالة') }}</th>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" class="text-xs text-gray-500">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('بواسطة') }}</th>
<th class="px-4 py-3 text-center text-xs font-medium text-gray-500">{{ __('إجراءات') }}</th>
</tr>
......
......@@ -44,12 +44,12 @@ class="w-full rounded-lg border-gray-300 text-sm py-2">
<thead class="bg-gray-50 border-b">
<tr>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('المنشأة') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('الشهر') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('المبلغ') }}</th>
<x-ui.sort-header column="period" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('الشهر') }}</x-ui.sort-header>
<x-ui.sort-header column="amount" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('المبلغ') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('طريقة الدفع') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('رقم الشيك') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('المستلم') }}</th>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('تاريخ الدفع') }}</th>
<x-ui.sort-header column="payment_date" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('تاريخ الدفع') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start text-xs font-medium text-gray-500">{{ __('بواسطة') }}</th>
</tr>
</thead>
......
......@@ -52,11 +52,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600 cursor-pointer" wire:click="sortColumn('code')">{{ __('الكود') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600 cursor-pointer" wire:click="sortColumn('name_ar')">{{ __('اسم المجموعة') }}</th>
<x-ui.sort-header column="code" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('الكود') }}</x-ui.sort-header>
<x-ui.sort-header column="name_ar" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('اسم المجموعة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('البرنامج') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('السعة') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="max_capacity" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('السعة') }}</x-ui.sort-header>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المدرب') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
......
......@@ -53,11 +53,11 @@ class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 f
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('الموظف') }}</th>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('الرقم الوظيفي') }}</th>
<x-ui.sort-header column="employee_number" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('الرقم الوظيفي') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('المنصب') }}</th>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('نوع التوظيف') }}</th>
<x-ui.sort-header column="employment_type" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('نوع التوظيف') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('الفرع') }}</th>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......
......@@ -78,6 +78,30 @@ class="w-full px-3 py-2.5 border border-gray-300 rounded-lg text-sm focus:ring-2
@error('personPhone') <p class="text-sm text-red-600 mt-1">{{ $message }}</p> @enderror
</div>
</div>
@if($trainer?->employee)
<hr class="my-4 border-gray-200">
<h3 class="text-base font-semibold text-gray-800 mb-3">{{ __('بيانات الراتب') }}</h3>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">{{ __('المرتب (ج.م)') }}</label>
<input type="number" wire:model="salaryAmount" step="0.01" min="0" dir="ltr"
class="w-full px-3 py-2.5 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500" placeholder="0.00">
@error('salaryAmount') <p class="text-sm text-red-600 mt-1">{{ $message }}</p> @enderror
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">{{ __('دورية الراتب') }}</label>
<select wire:model="salaryFrequency" class="w-full px-3 py-2.5 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
<option value="monthly">{{ __('شهري') }}</option>
<option value="biweekly">{{ __('نصف شهري') }}</option>
<option value="weekly">{{ __('أسبوعي') }}</option>
<option value="daily">{{ __('يومي') }}</option>
<option value="hourly">{{ __('بالساعة') }}</option>
</select>
@error('salaryFrequency') <p class="text-sm text-red-600 mt-1">{{ $message }}</p> @enderror
</div>
</div>
@endif
</div>
@endif
......
......@@ -45,12 +45,12 @@ class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 f
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('المدرب') }}</th>
<x-ui.sort-header column="trainer_number" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('المدرب') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('الأنشطة') }}</th>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('نموذج التعويض') }}</th>
<x-ui.sort-header column="compensation_model" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('نموذج التعويض') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('التقييم') }}</th>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('الحصص') }}</th>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......
......@@ -46,10 +46,10 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('SKU') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('اسم الطقم') }}</th>
<x-ui.sort-header column="name_ar" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('اسم الطقم') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('عدد المكونات') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('سعر البيع') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="is_active" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......
......@@ -49,12 +49,12 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('التاريخ') }}</th>
<x-ui.sort-header column="created_at" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('التاريخ') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المنتج') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المستودع') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('النوع') }}</th>
<x-ui.sort-header column="movement_type" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('النوع') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الاتجاه') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الكمية') }}</th>
<x-ui.sort-header column="quantity" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الكمية') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('قبل / بعد') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('بواسطة') }}</th>
</tr>
......
......@@ -65,10 +65,10 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('SKU') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المنتج') }}</th>
<x-ui.sort-header column="sku" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('SKU') }}</x-ui.sort-header>
<x-ui.sort-header column="name_ar" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('المنتج') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('التصنيف') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('سعر البيع') }}</th>
<x-ui.sort-header column="selling_price" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('سعر البيع') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('المخزون') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
......
......@@ -46,12 +46,12 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('رقم الأمر') }}</th>
<x-ui.sort-header column="order_number" :sortBy="$sortBy" :sortDir="$sortDir" align="start">{{ __('رقم الأمر') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المورد') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('عدد الأصناف') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الإجمالي') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('تاريخ الطلب') }}</th>
<x-ui.sort-header column="total_amount" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الإجمالي') }}</x-ui.sort-header>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<x-ui.sort-header column="created_at" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('تاريخ الطلب') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......
......@@ -47,8 +47,8 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('رقم الجرد') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المستودع') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('التاريخ') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="count_date" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('التاريخ') }}</x-ui.sort-header>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('عدد المنتجات') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الفروقات') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('قيمة الفروقات') }}</th>
......
......@@ -31,11 +31,11 @@ class="w-full sm:w-96 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 f
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الكود') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المستودع') }}</th>
<x-ui.sort-header column="name_ar" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('المستودع') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('النوع') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الفرع') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('عدد الأصناف') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......
......@@ -206,12 +206,12 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('رقم الفاتورة') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('العميل') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الإجمالي') }}</th>
<x-ui.sort-header column="total_amount" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الإجمالي') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('المدفوع') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('المتبقي') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('طريقة الدفع') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('تاريخ الدفع') }}</th>
<x-ui.sort-header column="due_date" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('تاريخ الدفع') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......
......@@ -46,11 +46,11 @@ class="px-3 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blu
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الوقت') }}</th>
<x-ui.sort-header column="created_at" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('الوقت') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الحدث') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('القناة') }}</th>
<x-ui.sort-header column="channel" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('القناة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('المستلم') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الموضوع') }}</th>
</tr>
</thead>
......
......@@ -61,12 +61,12 @@ class="w-full px-3 sm:px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 f
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('رقم المشترك') }}</th>
<x-ui.sort-header column="participant_number" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('رقم المشترك') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الاسم') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('النشاط') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('العضوية') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('تاريخ التسجيل') }}</th>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<x-ui.sort-header column="created_at" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('تاريخ التسجيل') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......
......@@ -40,12 +40,13 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الاسم') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الرقم القومي') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الهاتف') }}</th>
<x-ui.sort-header column="name_ar" :sortBy="$sortBy" :sortDir="$sortDir" align="start">{{ __('الاسم') }}</x-ui.sort-header>
<x-ui.sort-header column="national_id" :sortBy="$sortBy" :sortDir="$sortDir" align="start">{{ __('الرقم القومي') }}</x-ui.sort-header>
<x-ui.sort-header column="phone" :sortBy="$sortBy" :sortDir="$sortDir" align="start">{{ __('الهاتف') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الجنس') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('التصنيف') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('العمر') }}</th>
<x-ui.sort-header column="created_at" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('تاريخ الإضافة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......@@ -90,6 +91,9 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<td class="px-4 py-3 text-center text-gray-600">
{{ $person->age ?? '—' }}
</td>
<td class="px-4 py-3 text-center text-gray-500 text-xs" dir="ltr">
{{ $person->created_at?->format('Y-m-d') ?? '—' }}
</td>
<td class="px-4 py-3 text-center space-x-2 space-x-reverse">
@can('participants.view')
<a href="{{ route('people.show', $person) }}" wire:navigate class="text-blue-600 hover:text-blue-800 text-sm">{{ __('عرض') }}</a>
......@@ -106,7 +110,7 @@ class="text-red-600 hover:text-red-800 text-sm">{{ __('حذف') }}</button>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-8 text-center text-gray-500">
<td colspan="8" class="px-4 py-8 text-center text-gray-500">
{{ __('لا توجد سجلات') }}
</td>
</tr>
......
......@@ -47,9 +47,9 @@ class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 f
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الاسم') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('العنصر') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الفرع') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('المبلغ') }}</th>
<x-ui.sort-header column="amount" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('المبلغ') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الفترة') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="is_active" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......
......@@ -51,12 +51,13 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('الاسم') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الكود') }}</th>
<x-ui.sort-header column="code" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الكود') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('النوع') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('التعديل') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الاستخدام') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الفترة') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="start_date" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الفترة') }}</x-ui.sort-header>
<x-ui.sort-header column="is_active" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<x-ui.sort-header column="created_at" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('تاريخ الإنشاء') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......@@ -130,6 +131,9 @@ class="px-2 py-0.5 text-xs rounded-full {{ $promotion->is_active ? 'bg-green-100
{{ $promotion->is_active ? __('نشط') : __('غير نشط') }}
</button>
</td>
<td class="px-4 py-3 text-center text-gray-500 text-xs" dir="ltr">
{{ $promotion->created_at?->format('Y-m-d') ?? '—' }}
</td>
<td class="px-4 py-3 text-center">
@can('pricing.update')
<a href="{{ route('pricing.promotions.edit', $promotion) }}" wire:navigate
......@@ -139,7 +143,7 @@ class="text-blue-600 hover:text-blue-800 text-sm">{{ __('تعديل') }}</a>
</tr>
@empty
<tr>
<td colspan="8" class="px-4 py-12 text-center">
<td colspan="9" class="px-4 py-12 text-center">
<div class="flex flex-col items-center">
<svg class="w-12 h-12 text-gray-300 mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"/>
......
......@@ -57,19 +57,12 @@ class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 f
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-semibold text-gray-600">
<button wire:click="sortColumn('name_ar')" class="flex items-center gap-1 hover:text-gray-800">
{{ __('البرنامج') }}
@if($sortBy === 'name_ar')
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20"><path d="{{ $sortDir === 'asc' ? 'M5 10l5-5 5 5' : 'M5 10l5 5 5-5' }}"/></svg>
@endif
</button>
</th>
<x-ui.sort-header column="name_ar" :sortBy="$sortBy" :sortDir="$sortDir">{{ __('البرنامج') }}</x-ui.sort-header>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('النشاط') }}</th>
<th class="px-4 py-3 text-start font-semibold text-gray-600">{{ __('الفرع') }}</th>
<th class="px-4 py-3 text-center font-semibold text-gray-600">{{ __('المجموعات') }}</th>
<th class="px-4 py-3 text-center font-semibold text-gray-600">{{ __('الحصص/أسبوع') }}</th>
<th class="px-4 py-3 text-center font-semibold text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="sessions_per_week" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحصص/أسبوع') }}</x-ui.sort-header>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-end font-semibold text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......
......@@ -42,10 +42,10 @@ class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 f
<table class="w-full text-sm" wire:loading.class="opacity-50 pointer-events-none">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">المستخدم</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">البريد</th>
<x-ui.sort-header column="name_ar" :sortBy="$sortBy" :sortDir="$sortDir">المستخدم</x-ui.sort-header>
<x-ui.sort-header column="email" :sortBy="$sortBy" :sortDir="$sortDir">البريد</x-ui.sort-header>
<th class="px-4 py-3 text-start font-medium text-gray-600">الدور</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">الحالة</th>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">الحالة</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">إجراءات</th>
</tr>
</thead>
......
......@@ -34,8 +34,8 @@ class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 f
<tr>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('صاحب المحفظة') }}</th>
<th class="px-4 py-3 text-start font-medium text-gray-600">{{ __('النوع') }}</th>
<th class="px-4 py-3 text-end font-medium text-gray-600">{{ __('الرصيد') }}</th>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('الحالة') }}</th>
<x-ui.sort-header column="balance" :sortBy="$sortBy" :sortDir="$sortDir" align="end">{{ __('الرصيد') }}</x-ui.sort-header>
<x-ui.sort-header column="status" :sortBy="$sortBy" :sortDir="$sortDir" align="center">{{ __('الحالة') }}</x-ui.sort-header>
<th class="px-4 py-3 text-center font-medium text-gray-600">{{ __('إجراءات') }}</th>
</tr>
</thead>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment