{{-- ======================= وضع القائمة ======================= --}} @if($mode === 'list')

إدارة المستخدمين

@can('email-users') @endcan
@can('show-number-users-table') @endcan @can('details-users') @endcan @forelse ($users as $u) @php $s = $membershipMap[$u->membership_status] ?? ['label' => $u->membership_status, 'class' => 'kt-badge-outline']; $avatar = $u->img_profile ? asset('storage/'.ltrim($u->img_profile,'/')) : null; $initial = \Illuminate\Support\Str::upper(\Illuminate\Support\Str::substr($u->name ?? '؟', 0, 1)); $userTypeLabel = [ 'individual' => 'أفراد', 'private' => 'قطاع خاص', 'government' => 'جهة حكومية', ][$u->user_type] ?? $u->user_type; @endphp @can('show-number-users-table') @endcan @can('details-users') @endcan @empty @endforelse
رقم العضوية اسم المستخدم البريدرقم الهاتفالحالة نوع المستخدمالإجراءات
{{ $u->membership_number }}
@if($avatar) avatar @else
{{ $initial }}
@endif {{ $u->name }}
{{ $u->email }}{{ $u->phone ?? '—' }} {{ $s['label'] }} {{ $userTypeLabel }}
لا يوجد مستخدمون.
{{-- سبينر --}}
{{-- فوتر --}}
@endif {{-- ======================= وضع البريد الجماعي ======================= --}} @if($mode === 'bulk_mail')

إرسال بريد للأعضاء (جماعي)

{{-- اختيار الفئة --}}
فئة المستلمين
{{-- داخل صندوق "فئة المستلمين" أضف هذا الخيار --}} {{-- الخيار الجديد للدورات التدريبية --}}
مرشحات إضافية
{{-- فلترة حسب نطاق البريد --}} {{-- نطاقات البريد (تظهر فقط مع فئة email_domain) --}} @if($bulkKind === 'email_domain')
اختر نطاق/نطاقات البريد
{{-- بدال select multiple نخليها شيكات عشان الاختيار المتعدد يكون واضح --}}
@foreach($this->emailDomainOptions as $opt) @endforeach
المختارة: {{ count($bulkEmailDomainsSelected ?? []) }} — المستلمون: {{ $this->bulkRecipientsCount }}
@if(empty($bulkEmailDomainsSelected))
اختر نطاقًا واحدًا على الأقل.
@endif
@endif {{-- داخل صندوق "مرشحات إضافية" أضف كتلة المسمّيات --}} @if($bulkKind === 'cert_position')
اختر المسمّى
يمكنك اختيار أكثر من مسمى بالضغط على Ctrl/⌘
المختارة: {{ count($bulkPositions ?? []) }} المستلمون: {{ $this->bulkRecipientsCount }}
@if(!empty($bulkPositions))
@foreach($bulkPositions as $p) {{ $p }} @endforeach
@else

اختر مسمى واحد على الأقل.

@endif
@endif {{-- إظهار مرشحات الدورات فقط عند اختيار هذا الخيار --}} @if($bulkKind === 'course_members')
اختر الدورة التدريبية
@if($bulkCourseId) @php $selectedCourse = $this->courses->firstWhere('id', $bulkCourseId); @endphp
الدورة المختارة: {{ $selectedCourse->title ?? '' }}
@endif
@endif {{-- المرشحات العامة --}}
عدد المستلمين المتوقع: {{ $this->bulkRecipientsCount }} @if($bulkKind === 'course_members' && $bulkCourseId)
الأعضاء المسجلين في الدورة المختارة @endif
{{-- عنوان ومحتوى الرسالة --}}
{{-- زر "بدء الإرسال ومتابعة"—حدّث شرط التعطيل --}} جاري بدء المهمة… الإرسال فردي لكل مستلم لاستبدال المتغيرات وحماية الخصوصية.
{{-- رسالة تحذير إذا لم يتم اختيار دورة --}} @if($bulkKind === 'course_members' && !$bulkCourseId)
يرجى اختيار دورة تدريبية للمتابعة
@endif @if($bulkJobId)
@php $done = $bulkProgressSent + $bulkProgressFailed; $remain = max(0, $bulkProgressTotal - $done); $pct = $bulkProgressTotal > 0 ? round(($done / $bulkProgressTotal) * 100) : 0; @endphp
التقدّم: {{ $bulkProgressSent }} / {{ $bulkProgressTotal }} — المتبقي {{ $remain }}
فشل: {{ $bulkProgressFailed }}
{{-- آخر 6 سطور (بريد + ✓/✗ + رسالة قصيرة) --}} @if(!empty($bulkRecent))
@foreach($bulkRecent as $line)
{{ $line['email'] }} {!! ($line['ok'] ?? false) ? '✅' : '❌' !!} @if(!empty($line['msg'])) {{ $line['msg'] }} @endif
@endforeach
@endif
@if($bulkSending) جاري الإرسال… @else اكتمل/توقّف الإرسال. @endif
@endif
@endif {{-- ======================= وضع التفاصيل ======================= --}} @if($mode === 'detail' && $current)

تفاصيل المستخدم

{{-- رقم العضوية بارز --}} عضوية: {{ $current->membership_number }} {{-- Badge عضوية GOVI بلون #4c3177 --}} @if($this->hasGoviMembership) عضو – GOVI @endif {{-- حالة 2FA واضحة --}} 2FA: {{ $two_factor_enabled ? 'مُفعّل' : 'غير مُفعّل' }}
{{-- العمود الرئيسي --}}
{{-- تبويبات --}}
@can('profile-users') @endcan @can('security') @endcan @can('related-users') @endcan @can('permission-users') {{-- زر التبويب الجديد ضمن شريط التبويبات --}} @endcan @can('email-users') @endcan
{{-- الملف --}} @if($detailTab==='profile')

بيانات المستخدم

{{-- سطر علوي --}}
رقم العضوية
{{ $current->membership_number }}
آخر دخول
{{ $current->last_login_at ? \Carbon\Carbon::parse($current->last_login_at)->timezone('Asia/Riyadh')->format('Y-m-d H:i') : '—' }} IP: {{ $current->last_ip ?? '—' }}
الحالة
@php $ms = $membershipMap[$membership_status] ?? ['label'=>$membership_status,'class'=>'kt-badge-outline']; @endphp
{{ $ms['label'] }}
{{-- صورة الملف الشخصي --}} @php $avatar = $current->img_profile ? asset('storage/'.ltrim($current->img_profile,'/')) : null; $initial = \Illuminate\Support\Str::upper(\Illuminate\Support\Str::substr($current->name ?? '؟', 0, 1)); @endphp @can('edit-users')
@if($avatar) avatar @else
{{ $initial }}
@endif
جاري التحميل...
@if($avatar) @endif
@error('profileImage') {{ $message }} @enderror {{-- الاسم والبريد --}}
@error('name') {{ $message }} @enderror @error('email') {{ $message }} @enderror {{-- الهاتف واللغة --}}
@error('phone') {{ $message }} @enderror {{-- الدور ونوع المستخدم/الشركة --}}
{{-- توثيق البريد والجوال --}}
توثيق البريد: {{ $email_verified ? 'موثق' : 'غير موثق' }}
توثيق الجوال: {{ $phone_verified ? 'موثق' : 'غير موثق' }}
{{-- الحظر --}}
@error('ban_expires_at') {{ $message }} @enderror
@endcan
@endif {{-- البيانات الشخصية --}} @if($detailTab==='personal')

البيانات الشخصية

@php $pstate = $this->personalDataState; @endphp @if($pstate === 'missing') لا يوجد بيانات شخصية @elseif($pstate === 'incomplete') البيانات غير مكتملة @else مكتملة @endif
{{-- معاينة الصورة الشخصية 4×6 --}} @php $photo = $dataUser?->personal_photo ? asset('storage/'.ltrim($dataUser->personal_photo,'/')) : null; @endphp
@if($photo) صورة شخصية @else لا توجد صورة @endif
جاري التحميل...
@if($photo) فتح الصورة الحالية @endif
{{-- الجنسية --}}
{{-- مرفق المؤهل --}} @php $eduFile = $dataUser?->education_attachment ? asset('storage/'.ltrim($dataUser->education_attachment,'/')) : null; @endphp
جاري التحميل...
@if($eduFile) فتح المرفق الحالي @endif
@if($pstate === 'missing' || $pstate === 'incomplete') @endif
@endif {{-- الأمان --}} @if($detailTab==='security')

الأمان

التحقق الثنائي 2FA: {{ $two_factor_enabled ? 'مُفعّل' : 'غير مُفعّل' }}
محاولات دخول فاشلة: {{ $current->failed_login_attempts ?? 0 }}
مقفول حتى: {{ $current->locked_until ? \Carbon\Carbon::parse($current->locked_until)->timezone('Asia/Riyadh')->format('Y-m-d H:i') : '—' }}
آخر IP: {{ $current->last_ip ?? '—' }}
توليد كلمة مرور مؤقتة
سيتم إرسال كلمة المرور المؤقتة عبر البريد بتنسيق عربي جميل.
@endif {{-- البريد --}} @if($detailTab==='mail')

إرسال بريد يدوي

سيتم الإرسال إلى: {{ $current->email }}
@endif {{-- العلاقات: الطلبات + الشهادات --}} @if($detailTab==='relations') {{-- الطلبات --}}

طلبات المستخدم

{{-- عرض طلب مفرد --}} @if($viewOrderId) @php $o = $this->userOrders->firstWhere('id', $viewOrderId); @endphp @if($o) @php $s = $orderStatusMap[$o->status] ?? ['label'=>$o->status,'class'=>'kt-badge-outline']; $inv = $invoiceStatusMap[$o->invoice_status] ?? ['label'=>$o->invoice_status,'class'=>'kt-badge-outline']; @endphp
عرض الطلب رقم {{ $o->order_no }}
رقم التذكرة
{{ $o->order_no }}
الخدمة
{{ $o->service->title ?? '—' }} ({{ $o->service->service_no ?? '—' }})
التاريخ
{{ \Carbon\Carbon::parse($o->created_at)->timezone('Asia/Riyadh')->format('Y-m-d H:i') }}
{{-- المرفقات --}}
المرفقات
جاري التحميل...
@if($orderFile)
{{ \Illuminate\Support\Str::limit($orderFile->getClientOriginalName(), 40, '…') }}
@endif
@error('orderFile') {{ $message }} @enderror
@php $atts = is_array($o->attachments) ? $o->attachments : (json_decode($o->attachments, true) ?: []); $atts = collect($atts)->sortByDesc(function ($a) { $t = $a['ts'] ?? ($a['created_at'] ?? ($a['at'] ?? null)); if (is_numeric($t)) return (int)$t; try { return \Carbon\Carbon::parse($t)->timestamp; } catch (\Throwable $e) { return 0; } })->values()->all(); @endphp @if(empty($atts))
لا توجد مرفقات.
@else
@foreach($atts as $a) @php $path = $a['path'] ?? ''; $url = (!empty($path) && preg_match('#^https?://#', $path)) ? $path : asset('storage/' . ltrim($path, '/')); $fullName = $a['name'] ?? 'مرفق'; $shortName = \Illuminate\Support\Str::limit($fullName, 40, '…'); @endphp
{{ $shortName }}
بواسطة: {{ $a['by'] ?? '—' }} {{ $a['at'] ?? '' }}
@if(!empty($a['size'])) {{ number_format(($a['size']/1024), 1) }} KB @endif
@endforeach
@endif
{{-- الردود --}}
الردود
@error('replyText') {{ $message }} @enderror
@php $notes = is_array($o->notes) ? $o->notes : (json_decode($o->notes, true) ?: []); $notes = collect($notes)->sortByDesc(function ($n) { $t = $n['ts'] ?? ($n['created_at'] ?? ($n['at'] ?? null)); if (is_numeric($t)) return (int)$t; try { return \Carbon\Carbon::parse($t)->timestamp; } catch (\Exception $e) { return 0; } })->values()->all(); @endphp @if(empty($notes))
لا توجد ردود.
@else
@foreach($notes as $n)
{{ $n['body'] ?? '' }}
المستخدم: {{ $n['by'] ?? '—' }}
@endforeach
@endif
@endif @else {{-- جدول الطلبات --}}
@php $orders = $this->userOrders; @endphp @if($orders->isEmpty())
لا توجد طلبات.
@else
@foreach($orders as $o) @php $s = $orderStatusMap[$o->status] ?? ['label'=>$o->status,'class'=>'kt-badge-outline']; $i = $invoiceStatusMap[$o->invoice_status] ?? ['label'=>$o->invoice_status,'class'=>'kt-badge-outline']; @endphp @endforeach
رقم التذكرة رقم الخدمة عنوان الخدمة الحالة الفاتورة تاريخ إجراءات
{{ $o->order_no }} {{ $o->service->service_no ?? '—' }} {{ $o->service->title ?? '—' }} {{ $s['label'] }} {{ $i['label'] }} @if(!is_null($o->bill)) — {{ number_format($o->bill,2) }}@endif {{ \Carbon\Carbon::parse($o->created_at)->timezone('Asia/Riyadh')->format('Y-m-d H:i') }}
@endif
{{-- محرر الطلب --}} @if($editOrderId)

تعديل الطلب #{{ $editOrder?->order_no }}

@error('editOrderStatus') {{ $message }} @enderror @error('editOrderInvoiceStatus') {{ $message }} @enderror @error('editOrderBill') {{ $message }} @enderror
@endif @endif
{{-- الشهادات --}}

شهادات المستخدم

{{-- عرض شهادة مفردة --}} @if($viewCertId) @php $vc = $this->userCertificates->firstWhere('id', $viewCertId); @endphp @if($vc) @php $catLabel = $this->categoryMap[$vc->category] ?? $vc->category ?? '—'; $docLabel = $this->docTypeMap[$vc->document_type] ?? $vc->document_type ?? '—'; $stMeta = $certificateStatusMap[$vc->status] ?? ['label'=>$vc->status,'class'=>'kt-badge-outline']; $url = $vc->attachment ? (preg_match('#^https?://#',$vc->attachment) ? $vc->attachment : asset('storage/'.ltrim($vc->attachment,'/'))) : null; @endphp
عرض الشهادة رقم {{ $vc->certificate_no }}
رقم الشهادة
{{ $vc->certificate_no }}
اسم الشهادة
{{ $vc->name }}
النوع
{{ $docLabel }}
الفئة
{{ $catLabel }}
الحالة
{{ $stMeta['label'] }}
تاريخ الإصدار
{{ $vc->issued_at }}
تاريخ الانتهاء
{{ $vc->end_date }}
المرفق
@if($url)عرض@else — @endif
إعادة الإصدار بنفس الرقم (مع الاحتفاظ بتاريخ الإصدار)
@error('reissueName') {{ $message }} @enderror @error('reissueMajor') {{ $message }} @enderror
@endif @else {{-- جدول الشهادات (يختفي أثناء التعديل أيضاً) --}} @if(!$editCertId)
@php $certs = $this->userCertificates; @endphp @if($certs->isEmpty())
لا توجد شهادات.
@else
@foreach($certs as $c) @php $catLabel = $this->categoryMap[$c->category] ?? $c->category ?? '—'; $docLabel = $this->docTypeMap[$c->document_type] ?? $c->document_type ?? '—'; $stMeta = $certificateStatusMap[$c->status] ?? ['label'=>$c->status,'class'=>'kt-badge-outline']; $url = $c->attachment ? (preg_match('#^https?://#',$c->attachment) ? $c->attachment : asset('storage/'.ltrim($c->attachment,'/'))) : null; @endphp @endforeach
رقم الشهادة الاسم النوع الفئة الحالة الإصدار الانتهاء مرفق إجراءات
{{ $c->certificate_no }} {{ $c->name }} {{ $docLabel }} {{ $catLabel }} {{ $stMeta['label'] }} {{ $c->issued_at }} {{ $c->end_date }} @if($url) عرض @else — @endif
@endif
@endif {{-- محرر الشهادة --}} @if($editCertId)

تعديل الشهادة

@error('editCertNo') {{ $message }} @enderror @error('editCertName') {{ $message }} @enderror
@error('editCertDocType') {{ $message }} @enderror @error('editCertCategory') {{ $message }} @enderror
@error('editCertIssuedAt') {{ $message }} @enderror @error('editCertEndDate') {{ $message }} @enderror
جاري التحميل...
@if($editCertFile)
{{ \Illuminate\Support\Str::limit($editCertFile->getClientOriginalName(), 40, '…') }}
@endif
@error('editCertFile') {{ $message }} @enderror
@endif @endif
@endif {{-- مقطع تبويب الصلاحيات (ضعه بعد بقية التبويبات) --}} @if($detailTab==='authz')

صلاحيات وأدوار المستخدم

الأدوار المعطاة
{{ count($uRoleIds) }}
الصلاحيات المباشرة
{{ count($uPermissionIds) }}
المجموع
{{ count($uRoleIds) + count($uPermissionIds) }}
الأدوار
@foreach($this->allRoles as $r) @endforeach
الصلاحيات المباشرة
@foreach($this->allPermissions as $p) @endforeach
ملاحظة: الصلاحيات القادمة من الأدوار لا تظهر هنا كـ “مباشرة”.
@endif
{{-- العمود الجانبي --}}

ملخص المستخدم

@php $avatar = $current->img_profile ? asset('storage/'.ltrim($current->img_profile,'/')) : null; $initial = \Illuminate\Support\Str::upper(\Illuminate\Support\Str::substr($current->name ?? '؟', 0, 1)); $userTypeLabel = [ 'individual' => 'أفراد', 'private' => 'قطاع خاص', 'government' => 'جهة حكومية', ][$current->user_type] ?? $current->user_type; $natLabel = [ 'saudi' => 'سعودي', 'gcc' => 'دول الخليج', 'levant' => 'الشامية', 'arab' => 'العربية كافة', ][$du_nationality ?? ''] ?? ($du_nationality ?: '—'); @endphp
@if($avatar) avatar @else
{{ $initial }}
@endif
{{ $current->name }}
{{ $current->email }}
@if($this->hasGoviMembership)
عضو – GOVI
@endif
الهاتف{{ $current->phone ?? '—' }}
الدور{{ $role }}
نوع المستخدم{{ $userTypeLabel }}
الجنسية{{ $natLabel }}
2FA{{ $two_factor_enabled ? 'مُفعّل' : 'غير مُفعّل' }}
@php $ms = $membershipMap[$membership_status] ?? ['label'=>$membership_status,'class'=>'kt-badge-outline']; @endphp
الحالة{{ $ms['label'] }}
الطلبات{{ (int)($current->orders_count ?? 0) }}
الشهادات{{ (int)($current->certs_count ?? 0) }}
@can('edit-users') @endcan
@can('edit-users')

إجراءات سريعة

@endcan
@endif
{{-- === تحديث الرابط تلقائياً عند الدخول/الخروج من التفاصيل === --}}