Add removal/blacklist tools, Arabic UI, and a persistent sign-in error

Authorisation: driver/deleteCaptain.php permanently deletes a captain and had
no role check at all — any valid token, including a driver's or passenger's,
could delete captains. It now requires super_admin. The two unblacklist
endpoints had no role check either and now require an admin role.

Console:
- Blacklist & removal screen (super admin only): current blocks, permanent
  removal, and lifting a block. Deletion additionally requires the phone
  number to be retyped, because the row is deleted outright.
- Arabic interface with full RTL layout and a language toggle. Sidebar,
  content offset, input affordances, toasts and directional icons all mirror;
  numbers, identifiers and the diagnostics output stay LTR.
- Sign-in failures now render in the form and stay there. They were only
  shown as a toast, which disappears before it can be read — a locked
  account or a rejected device looked like the page simply returning to
  the login screen with no explanation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hamza-Ayed
2026-07-25 14:53:26 +03:00
co-authored by Claude Opus 5
parent 42f6d33efd
commit 81ee2acefd
3 changed files with 608 additions and 98 deletions
+124
View File
@@ -1384,3 +1384,127 @@ textarea.form-input { text-align: start; }
}
.card-header { gap: 1rem; flex-wrap: wrap; }
/* Destructive action button */
.btn-danger {
background: var(--danger-bg);
border-color: rgba(244, 63, 94, 0.45);
color: var(--danger);
font-weight: 600;
}
.btn-danger:hover { background: rgba(244, 63, 94, 0.28); }
/* ==========================================================================
Right-to-left layout (Arabic)
The base layout is written LTR with physical properties, so RTL flips the
fixed sidebar, the content offset and anything anchored to a screen edge.
========================================================================== */
.lang-toggle {
font-weight: 700;
font-size: 0.85rem;
font-family: 'Outfit', sans-serif;
}
[dir="rtl"] .sidebar {
left: auto;
right: 0;
border-right: none;
border-left: 1px solid var(--border-color);
}
[dir="rtl"] .main-wrapper {
margin-left: 0;
margin-right: var(--sidebar-width);
}
[dir="rtl"] .nav-item.active::before,
[dir="rtl"] .nav-item::before {
left: auto;
right: 0;
}
[dir="rtl"] .toast {
right: auto;
left: 24px;
}
/* The icon sits at the inline start; in RTL that is the right edge, and the
input's reserved padding must move with it. */
[dir="rtl"] .form-input-group i {
left: auto;
right: 1rem;
}
[dir="rtl"] .form-input-group .form-input {
padding-left: 1rem;
padding-right: 2.8rem;
}
[dir="rtl"] .search-box i {
left: auto;
right: 0.9rem;
}
[dir="rtl"] .search-box input {
padding-left: 1rem;
padding-right: 2.5rem;
}
[dir="rtl"] .nav-count { margin-left: 0; margin-right: auto; }
[dir="rtl"] .card-sub { margin-left: 0; margin-right: 0.4rem; }
[dir="rtl"] .kv-row strong { text-align: left; }
[dir="rtl"] .stop-list { padding-left: 0; padding-right: 1.2rem; }
/* Directional icons must mirror, plain symbols must not */
[dir="rtl"] .route-cell .ph-arrow-right,
[dir="rtl"] .btn .ph-caret-left,
[dir="rtl"] .btn .ph-caret-right {
transform: scaleX(-1);
}
/* Numbers, code and diagnostics stay LTR even inside an RTL page */
[dir="rtl"] .diagnostics,
[dir="rtl"] .device-note code,
[dir="rtl"] .stat-value,
[dir="rtl"] .kpi-tile-value {
direction: ltr;
text-align: start;
}
@media (max-width: 992px) {
[dir="rtl"] .sidebar { transform: translateX(100%); }
[dir="rtl"] .sidebar.open { transform: translateX(0); }
[dir="rtl"] .main-wrapper { margin-right: 0; }
}
/* Persistent sign-in error */
.login-error {
display: flex;
align-items: flex-start;
gap: 0.6rem;
margin-top: 1.25rem;
padding: 0.8rem 0.95rem;
border-radius: var(--radius-md);
background: var(--danger-bg);
border: 1px solid rgba(244, 63, 94, 0.4);
color: var(--danger);
font-size: 0.82rem;
line-height: 1.55;
}
/* display:flex would otherwise override the [hidden] attribute */
.login-error[hidden] { display: none; }
.login-error i { font-size: 1.1rem; flex-shrink: 0; }
.login-error div { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
.login-error strong { color: var(--text-main); font-weight: 600; }
.login-error span {
color: var(--text-muted);
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 0.72rem;
word-break: break-all;
direction: ltr;
text-align: start;
}