This commit is contained in:
root committed 2026-05-11 17:58:21 +00:00
1 parent b03c1d4619
commit b07423aef3
42 files changed
+1431 -394

No files matched your search

+58 -32
View File
@@ -22,6 +22,15 @@
padding:.25em .75em; border-radius:20px; font-size:.75rem; font-weight:600;
background:#f1f5f9; color:#94a3b8;
}
.lot-checkbox-list {
border:1px solid #e2e8f0; border-radius:.625rem; max-height:180px; overflow-y:auto; padding:.5rem;
}
.lot-checkbox-item {
display:flex; align-items:center; gap:.6rem; padding:.375rem .5rem; border-radius:.4rem; cursor:pointer;
font-size:.875rem; color:#374151; transition:background .15s;
}
.lot-checkbox-item:hover { background:#f8fafc; }
.lot-checkbox-item input[type=checkbox] { width:1rem; height:1rem; cursor:pointer; flex-shrink:0; }
</style>
@endsection
@@ -61,11 +70,15 @@
<td class="py-3" style="color:#475569;">{{ $op->email }}</td>
<td class="py-3" style="color:#475569;">{{ $op->phone ?? '—' }}</td>
<td class="py-3">
@if($op->assignedLot)
<span class="lot-pill">
<i class="bi bi-buildings"></i>
{{ $op->assignedLot->name }}
</span>
@if($op->assignedLots->isNotEmpty())
<div class="d-flex flex-wrap gap-1">
@foreach($op->assignedLots as $assignedLot)
<span class="lot-pill">
<i class="bi bi-buildings"></i>
{{ $assignedLot->name }}
</span>
@endforeach
</div>
@else
<span class="no-lot-pill">
<i class="bi bi-dash-circle"></i>
@@ -81,7 +94,7 @@
data-name="{{ $op->name }}"
data-email="{{ $op->email }}"
data-phone="{{ $op->phone ?? '' }}"
data-lot="{{ $op->parking_lot_id ?? '' }}">
data-lots="{{ json_encode($op->assignedLots->pluck('id')) }}">
<i class="bi bi-pencil me-1"></i>تعديل
</button>
<button class="btn btn-sm fw-600 btn-delete-op"
@@ -134,13 +147,17 @@
<input type="password" id="createPassword" class="form-control" placeholder="8 أحرف على الأقل" dir="ltr">
</div>
<div class="mb-1">
<label class="form-label fw-600" style="font-size:.875rem;color:#374151;">الموقف المخصص <span style="color:#94a3b8;font-weight:400;">(اختياري)</span></label>
<select id="createLot" class="form-select">
<option value="">— بدون تخصيص —</option>
@foreach($lots as $lot)
<option value="{{ $lot->id }}">{{ $lot->name }}</option>
@endforeach
</select>
<label class="form-label fw-600" style="font-size:.875rem;color:#374151;">المواقف المخصصة <span style="color:#94a3b8;font-weight:400;">(اختياري)</span></label>
<div class="lot-checkbox-list" id="createLotList">
@forelse($lots as $lot)
<label class="lot-checkbox-item">
<input type="checkbox" class="create-lot-cb" value="{{ $lot->id }}">
<span>{{ $lot->name }}</span>
</label>
@empty
<p class="text-center mb-0 py-2" style="color:#94a3b8;font-size:.8rem;">لا توجد مواقف</p>
@endforelse
</div>
</div>
</div>
<div class="modal-footer border-0 pt-1">
@@ -186,13 +203,17 @@
<input type="password" id="editPassword" class="form-control" placeholder="8 أحرف على الأقل" dir="ltr">
</div>
<div class="mb-1">
<label class="form-label fw-600" style="font-size:.875rem;color:#374151;">الموقف المخصص</label>
<select id="editLot" class="form-select">
<option value="">— بدون تخصيص —</option>
@foreach($lots as $lot)
<option value="{{ $lot->id }}">{{ $lot->name }}</option>
@endforeach
</select>
<label class="form-label fw-600" style="font-size:.875rem;color:#374151;">المواقف المخصصة</label>
<div class="lot-checkbox-list" id="editLotList">
@forelse($lots as $lot)
<label class="lot-checkbox-item">
<input type="checkbox" class="edit-lot-cb" value="{{ $lot->id }}">
<span>{{ $lot->name }}</span>
</label>
@empty
<p class="text-center mb-0 py-2" style="color:#94a3b8;font-size:.8rem;">لا توجد مواقف</p>
@endforelse
</div>
</div>
</div>
<div class="modal-footer border-0 pt-1">
@@ -271,7 +292,7 @@ document.addEventListener('DOMContentLoaded', function () {
// ── Open create ───────────────────────────────────────────────────────────
document.getElementById('btnOpenCreate').addEventListener('click', function () {
['createName','createEmail','createPhone','createPassword'].forEach(id => document.getElementById(id).value = '');
document.getElementById('createLot').value = '';
document.querySelectorAll('.create-lot-cb').forEach(cb => cb.checked = false);
document.getElementById('createError').classList.add('d-none');
modal('createModal').show();
});
@@ -284,7 +305,10 @@ document.addEventListener('DOMContentLoaded', function () {
document.getElementById('editEmail').value = this.dataset.email;
document.getElementById('editPhone').value = this.dataset.phone || '';
document.getElementById('editPassword').value = '';
document.getElementById('editLot').value = this.dataset.lot || '';
const assignedIds = JSON.parse(this.dataset.lots || '[]');
document.querySelectorAll('.edit-lot-cb').forEach(cb => {
cb.checked = assignedIds.includes(parseInt(cb.value));
});
document.getElementById('editError').classList.add('d-none');
modal('editModal').show();
});
@@ -309,15 +333,16 @@ document.addEventListener('DOMContentLoaded', function () {
spinner.classList.remove('d-none');
errEl.classList.add('d-none');
try {
const createLotIds = [...document.querySelectorAll('.create-lot-cb:checked')].map(cb => parseInt(cb.value));
const res = await fetch('{{ route("admin.operators.store") }}', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrf },
body: JSON.stringify({
name: document.getElementById('createName').value.trim(),
email: document.getElementById('createEmail').value.trim(),
phone: document.getElementById('createPhone').value.trim() || null,
password: document.getElementById('createPassword').value,
parking_lot_id: document.getElementById('createLot').value || null,
name: document.getElementById('createName').value.trim(),
email: document.getElementById('createEmail').value.trim(),
phone: document.getElementById('createPhone').value.trim() || null,
password: document.getElementById('createPassword').value,
lot_ids: createLotIds,
}),
});
const json = await res.json();
@@ -343,15 +368,16 @@ document.addEventListener('DOMContentLoaded', function () {
spinner.classList.remove('d-none');
errEl.classList.add('d-none');
try {
const editLotIds = [...document.querySelectorAll('.edit-lot-cb:checked')].map(cb => parseInt(cb.value));
const res = await fetch(`/admin/operators/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrf },
body: JSON.stringify({
name: document.getElementById('editName').value.trim(),
email: document.getElementById('editEmail').value.trim(),
phone: document.getElementById('editPhone').value.trim() || null,
password: document.getElementById('editPassword').value || null,
parking_lot_id: document.getElementById('editLot').value || null,
name: document.getElementById('editName').value.trim(),
email: document.getElementById('editEmail').value.trim(),
phone: document.getElementById('editPhone').value.trim() || null,
password: document.getElementById('editPassword').value || null,
lot_ids: editLotIds,
}),
});
const json = await res.json();