Update: 2026-07-24 22:55:34

This commit is contained in:
Hamza-Ayed
2026-07-24 22:55:34 +03:00
parent 474c212bcb
commit 0b24bc21b6
5 changed files with 1860 additions and 0 deletions
+846
View File
@@ -0,0 +1,846 @@
/* ==========================================================================
Siro Admin Web Portal - Modern Design System & CSS Stylesheet
========================================================================== */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700&display=swap');
:root {
/* Color Tokens */
--bg-dark: #090d16;
--bg-card: rgba(17, 24, 39, 0.7);
--bg-card-hover: rgba(30, 41, 59, 0.8);
--bg-surface: #111827;
--bg-elevated: #1e293b;
--border-color: rgba(255, 255, 255, 0.08);
--border-active: rgba(99, 102, 241, 0.4);
--primary: #6366f1;
--primary-hover: #4f46e5;
--primary-light: rgba(99, 102, 241, 0.15);
--accent-purple: #8b5cf6;
--success: #10b981;
--success-bg: rgba(16, 185, 129, 0.15);
--warning: #f59e0b;
--warning-bg: rgba(245, 158, 11, 0.15);
--danger: #f43f5e;
--danger-bg: rgba(244, 63, 94, 0.15);
--info: #06b6d4;
--info-bg: rgba(6, 182, 212, 0.15);
--text-main: #f8fafc;
--text-muted: #94a3b8;
--text-subtle: #64748b;
--sidebar-width: 260px;
--header-height: 70px;
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 18px;
--radius-full: 9999px;
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.2);
--shadow-md: 0 8px 24px rgba(0, 0, 0, 0.3);
--shadow-glow: 0 0 25px rgba(99, 102, 241, 0.25);
--transition-fast: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
--transition-smooth: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Reset & Global */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Inter', system-ui, -apple-system, sans-serif;
background-color: var(--bg-dark);
color: var(--text-main);
min-height: 100vh;
overflow-x: hidden;
line-height: 1.5;
}
h1, h2, h3, h4, h5, h6 {
font-family: 'Outfit', sans-serif;
letter-spacing: -0.02em;
}
/* Custom Scrollbar */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: var(--bg-dark);
}
::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.15);
border-radius: var(--radius-full);
}
::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.3);
}
/* Auth Page Overlay / Container */
.auth-wrapper {
position: fixed;
inset: 0;
z-index: 1000;
background: radial-gradient(circle at 10% 20%, rgba(99, 102, 241, 0.15) 0%, transparent 40%),
radial-gradient(circle at 90% 80%, rgba(139, 92, 246, 0.15) 0%, transparent 40%),
var(--bg-dark);
display: flex;
align-items: center;
justify-content: center;
padding: 1.5rem;
transition: opacity 0.4s ease, visibility 0.4s ease;
}
.auth-wrapper.hidden {
opacity: 0;
visibility: hidden;
pointer-events: none;
}
.auth-card {
width: 100%;
max-width: 440px;
background: var(--bg-card);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: 2.5rem;
box-shadow: var(--shadow-md);
position: relative;
overflow: hidden;
}
.auth-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg, var(--primary), var(--accent-purple));
}
.auth-header {
text-align: center;
margin-bottom: 2rem;
}
.auth-logo {
display: inline-flex;
align-items: center;
gap: 0.75rem;
font-size: 1.75rem;
font-weight: 700;
color: #fff;
margin-bottom: 0.5rem;
}
.auth-logo i {
color: var(--primary);
filter: drop-shadow(0 0 10px rgba(99, 102, 241, 0.6));
}
.auth-subtitle {
color: var(--text-muted);
font-size: 0.9rem;
}
.form-group {
margin-bottom: 1.25rem;
}
.form-label {
display: block;
font-size: 0.85rem;
font-weight: 500;
color: var(--text-muted);
margin-bottom: 0.5rem;
}
.form-input-group {
position: relative;
}
.form-input-group i {
position: absolute;
left: 1rem;
top: 50%;
transform: translateY(-50%);
color: var(--text-subtle);
font-size: 1.1rem;
transition: var(--transition-fast);
}
.form-input {
width: 100%;
background: rgba(15, 23, 42, 0.6);
border: 1px solid var(--border-color);
border-radius: var(--radius-md);
padding: 0.75rem 1rem 0.75rem 2.8rem;
color: var(--text-main);
font-size: 0.95rem;
outline: none;
transition: var(--transition-fast);
}
.form-input:focus {
border-color: var(--primary);
box-shadow: 0 0 0 3px var(--primary-light);
}
.form-input:focus + i, .form-input-group:focus-within i {
color: var(--primary);
}
.btn-primary {
width: 100%;
padding: 0.85rem;
border-radius: var(--radius-md);
border: none;
background: linear-gradient(135deg, var(--primary), var(--accent-purple));
color: #fff;
font-weight: 600;
font-size: 1rem;
cursor: pointer;
box-shadow: var(--shadow-glow);
transition: var(--transition-fast);
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.btn-primary:hover {
opacity: 0.95;
transform: translateY(-1px);
}
/* App Main Layout */
.app-container {
display: flex;
min-height: 100vh;
}
/* Sidebar */
.sidebar {
width: var(--sidebar-width);
background: rgba(15, 23, 42, 0.95);
border-right: 1px solid var(--border-color);
display: flex;
flex-direction: column;
position: fixed;
top: 0;
bottom: 0;
left: 0;
z-index: 100;
transition: var(--transition-smooth);
backdrop-filter: blur(12px);
}
.sidebar-header {
height: var(--header-height);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 1.5rem;
border-bottom: 1px solid var(--border-color);
}
.brand {
display: flex;
align-items: center;
gap: 0.75rem;
font-size: 1.4rem;
font-weight: 700;
color: var(--text-main);
text-decoration: none;
}
.brand-icon {
width: 36px;
height: 36px;
border-radius: var(--radius-md);
background: linear-gradient(135deg, var(--primary), var(--accent-purple));
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 1.1rem;
box-shadow: var(--shadow-glow);
}
.brand-badge {
font-size: 0.65rem;
padding: 0.15rem 0.4rem;
border-radius: var(--radius-sm);
background: var(--primary-light);
color: var(--primary);
font-weight: 600;
text-transform: uppercase;
}
.sidebar-menu {
padding: 1.25rem 0.75rem;
flex: 1;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 0.35rem;
}
.menu-label {
font-size: 0.75rem;
text-transform: uppercase;
color: var(--text-subtle);
font-weight: 600;
padding: 0.75rem 0.75rem 0.25rem;
letter-spacing: 0.05em;
}
.nav-item {
display: flex;
align-items: center;
gap: 0.85rem;
padding: 0.75rem 1rem;
color: var(--text-muted);
text-decoration: none;
border-radius: var(--radius-md);
font-weight: 500;
font-size: 0.92rem;
transition: var(--transition-fast);
cursor: pointer;
}
.nav-item i {
font-size: 1.1rem;
width: 20px;
text-align: center;
}
.nav-item:hover {
color: var(--text-main);
background: rgba(255, 255, 255, 0.05);
}
.nav-item.active {
color: #fff;
background: linear-gradient(90deg, var(--primary-light), transparent);
border-left: 3px solid var(--primary);
}
.nav-item.active i {
color: var(--primary);
}
.sidebar-footer {
padding: 1rem 1.25rem;
border-top: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
}
.user-profile-mini {
display: flex;
align-items: center;
gap: 0.75rem;
}
.avatar {
width: 38px;
height: 38px;
border-radius: var(--radius-full);
background: linear-gradient(135deg, var(--info), var(--primary));
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
color: #fff;
}
.user-info .name {
font-size: 0.88rem;
font-weight: 600;
color: var(--text-main);
}
.user-info .role {
font-size: 0.75rem;
color: var(--text-subtle);
}
.btn-icon {
background: transparent;
border: 1px solid var(--border-color);
color: var(--text-muted);
width: 34px;
height: 34px;
border-radius: var(--radius-md);
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: var(--transition-fast);
}
.btn-icon:hover {
color: var(--text-main);
border-color: rgba(255, 255, 255, 0.2);
background: rgba(255, 255, 255, 0.05);
}
/* Main Content Area */
.main-wrapper {
margin-left: var(--sidebar-width);
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
}
/* Header */
.top-header {
height: var(--header-height);
background: rgba(15, 23, 42, 0.8);
backdrop-filter: blur(12px);
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 2rem;
position: sticky;
top: 0;
z-index: 90;
}
.header-left {
display: flex;
align-items: center;
gap: 1rem;
}
.toggle-sidebar-btn {
display: none;
}
.search-box {
position: relative;
width: 320px;
}
.search-box input {
width: 100%;
background: rgba(30, 41, 59, 0.5);
border: 1px solid var(--border-color);
border-radius: var(--radius-full);
padding: 0.5rem 1rem 0.5rem 2.5rem;
color: var(--text-main);
font-size: 0.88rem;
outline: none;
transition: var(--transition-fast);
}
.search-box input:focus {
border-color: var(--primary);
background: rgba(30, 41, 59, 0.8);
}
.search-box i {
position: absolute;
left: 0.9rem;
top: 50%;
transform: translateY(-50%);
color: var(--text-subtle);
}
.header-right {
display: flex;
align-items: center;
gap: 1rem;
}
.live-indicator {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.8rem;
color: var(--success);
background: var(--success-bg);
padding: 0.35rem 0.75rem;
border-radius: var(--radius-full);
font-weight: 500;
}
.pulse-dot {
width: 8px;
height: 8px;
border-radius: var(--radius-full);
background: var(--success);
box-shadow: 0 0 8px var(--success);
animation: pulse 1.8s infinite;
}
@keyframes pulse {
0% { opacity: 1; transform: scale(1); }
50% { opacity: 0.4; transform: scale(0.85); }
100% { opacity: 1; transform: scale(1); }
}
/* Page Views */
.content-body {
padding: 2rem;
flex: 1;
}
.page-view {
display: none;
animation: fadeIn 0.3s ease;
}
.page-view.active {
display: block;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(6px); }
to { opacity: 1; transform: translateY(0); }
}
.page-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1.75rem;
}
.page-title h1 {
font-size: 1.75rem;
font-weight: 700;
color: #fff;
}
.page-title p {
color: var(--text-muted);
font-size: 0.9rem;
margin-top: 0.2rem;
}
.page-actions {
display: flex;
align-items: center;
gap: 0.75rem;
}
/* Cards & Stats Grid */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 1.25rem;
margin-bottom: 1.75rem;
}
.stat-card {
background: var(--bg-card);
backdrop-filter: blur(16px);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: 1.5rem;
position: relative;
overflow: hidden;
transition: var(--transition-smooth);
}
.stat-card:hover {
transform: translateY(-3px);
border-color: rgba(255, 255, 255, 0.15);
box-shadow: var(--shadow-md);
}
.stat-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
}
.stat-icon {
width: 44px;
height: 44px;
border-radius: var(--radius-md);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
}
.stat-icon.primary { background: var(--primary-light); color: var(--primary); }
.stat-icon.success { background: var(--success-bg); color: var(--success); }
.stat-icon.warning { background: var(--warning-bg); color: var(--warning); }
.stat-icon.info { background: var(--info-bg); color: var(--info); }
.stat-icon.danger { background: var(--danger-bg); color: var(--danger); }
.stat-value {
font-size: 1.85rem;
font-weight: 700;
color: #fff;
line-height: 1.2;
}
.stat-title {
color: var(--text-muted);
font-size: 0.85rem;
font-weight: 500;
margin-top: 0.25rem;
}
.stat-footer {
margin-top: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.8rem;
}
.trend-badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
padding: 0.15rem 0.5rem;
border-radius: var(--radius-full);
font-weight: 600;
}
.trend-badge.up { background: var(--success-bg); color: var(--success); }
.trend-badge.down { background: var(--danger-bg); color: var(--danger); }
.trend-text {
color: var(--text-subtle);
}
/* Section Grid (Charts & Tables) */
.dashboard-grid {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 1.5rem;
margin-bottom: 1.75rem;
}
@media (max-width: 1200px) {
.dashboard-grid {
grid-template-columns: 1fr;
}
}
.card {
background: var(--bg-card);
backdrop-filter: blur(16px);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: 1.5rem;
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1.25rem;
}
.card-title {
font-size: 1.1rem;
font-weight: 600;
color: #fff;
}
/* Custom CSS Charts */
.chart-container {
height: 280px;
width: 100%;
position: relative;
}
/* Data Tables */
.table-responsive {
width: 100%;
overflow-x: auto;
}
.data-table {
width: 100%;
border-collapse: collapse;
text-align: left;
}
.data-table th {
background: rgba(15, 23, 42, 0.5);
color: var(--text-subtle);
font-size: 0.78rem;
text-transform: uppercase;
font-weight: 600;
padding: 0.85rem 1rem;
border-bottom: 1px solid var(--border-color);
letter-spacing: 0.05em;
}
.data-table td {
padding: 0.95rem 1rem;
border-bottom: 1px solid var(--border-color);
color: var(--text-main);
font-size: 0.88rem;
vertical-align: middle;
}
.data-table tbody tr {
transition: var(--transition-fast);
}
.data-table tbody tr:hover {
background: rgba(255, 255, 255, 0.03);
}
/* Badges */
.badge {
display: inline-flex;
align-items: center;
gap: 0.35rem;
padding: 0.25rem 0.65rem;
border-radius: var(--radius-full);
font-size: 0.75rem;
font-weight: 600;
}
.badge-success { background: var(--success-bg); color: var(--success); }
.badge-warning { background: var(--warning-bg); color: var(--warning); }
.badge-danger { background: var(--danger-bg); color: var(--danger); }
.badge-info { background: var(--info-bg); color: var(--info); }
.badge-primary { background: var(--primary-light); color: var(--primary); }
/* Buttons */
.btn {
padding: 0.55rem 1.1rem;
border-radius: var(--radius-md);
font-size: 0.88rem;
font-weight: 500;
cursor: pointer;
border: 1px solid transparent;
display: inline-flex;
align-items: center;
gap: 0.5rem;
transition: var(--transition-fast);
text-decoration: none;
}
.btn-secondary {
background: rgba(255, 255, 255, 0.06);
border-color: var(--border-color);
color: var(--text-main);
}
.btn-secondary:hover {
background: rgba(255, 255, 255, 0.12);
}
.btn-sm {
padding: 0.35rem 0.75rem;
font-size: 0.8rem;
}
/* Modal Overlay */
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(8px);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
pointer-events: none;
transition: var(--transition-smooth);
}
.modal-overlay.active {
opacity: 1;
pointer-events: auto;
}
.modal-content {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
width: 90%;
max-width: 550px;
padding: 2rem;
box-shadow: var(--shadow-md);
transform: translateY(20px);
transition: var(--transition-smooth);
}
.modal-overlay.active .modal-content {
transform: translateY(0);
}
/* Filter Bar */
.filter-bar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
background: var(--bg-card);
padding: 1rem 1.25rem;
border-radius: var(--radius-lg);
border: 1px solid var(--border-color);
margin-bottom: 1.5rem;
flex-wrap: wrap;
}
.filter-inputs {
display: flex;
align-items: center;
gap: 0.75rem;
flex-wrap: wrap;
}
.select-input {
background: rgba(15, 23, 42, 0.7);
border: 1px solid var(--border-color);
color: var(--text-main);
padding: 0.5rem 1rem;
border-radius: var(--radius-md);
font-size: 0.88rem;
outline: none;
}
/* Responsive adjustments */
@media (max-width: 992px) {
.sidebar {
transform: translateX(-100%);
}
.sidebar.open {
transform: translateX(0);
}
.main-wrapper {
margin-left: 0;
}
.toggle-sidebar-btn {
display: inline-flex;
}
.search-box {
width: 200px;
}
}
+494
View File
@@ -0,0 +1,494 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Siro Admin | Enterprise Operations Dashboard</title>
<!-- Fonts & Icons -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700&display=swap" rel="stylesheet">
<script src="https://unpkg.com/@phosphor-icons/web"></script>
<!-- Styles -->
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<!-- ================= AUTH OVERLAY ================= -->
<div class="auth-wrapper" id="authWrapper">
<div class="auth-card">
<div class="auth-header">
<div class="auth-logo">
<i class="ph-bold ph-car"></i>
<span>SIRO ADMIN</span>
</div>
<p class="auth-subtitle">Enterprise Operations & Control Portal</p>
</div>
<form id="loginForm">
<div class="form-group">
<label class="form-label" for="loginEmail">Admin Email</label>
<div class="form-input-group">
<input type="email" id="loginEmail" class="form-input" placeholder="admin@siromove.com" value="admin@siromove.com" required>
<i class="ph ph-envelope"></i>
</div>
</div>
<div class="form-group">
<label class="form-label" for="loginPass">Password</label>
<div class="form-input-group">
<input type="password" id="loginPass" class="form-input" value="••••••••••••" required>
<i class="ph ph-lock-key"></i>
</div>
</div>
<button type="submit" class="btn-primary" style="margin-top: 1.5rem;">
<i class="ph-bold ph-sign-in"></i> Sign In to Portal
</button>
</form>
</div>
</div>
<!-- ================= APP CONTAINER ================= -->
<div class="app-container">
<!-- Sidebar Navigation -->
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<a href="#" class="brand">
<div class="brand-icon">
<i class="ph-bold ph-lightning"></i>
</div>
<span>SIRO</span>
<span class="brand-badge">ADMIN</span>
</a>
</div>
<nav class="sidebar-menu">
<div class="menu-label">Main Menu</div>
<a class="nav-item active" data-view="dashboardView">
<i class="ph ph-squares-four"></i>
<span>Dashboard</span>
</a>
<a class="nav-item" data-view="ridesView">
<i class="ph ph-path"></i>
<span>Rides & Dispatch</span>
</a>
<a class="nav-item" data-view="driversView">
<i class="ph ph-steering-wheel"></i>
<span>Captains / Drivers</span>
</a>
<a class="nav-item" data-view="passengersView">
<i class="ph ph-users"></i>
<span>Passengers</span>
</a>
<div class="menu-label">Management</div>
<a class="nav-item" data-view="financialsView">
<i class="ph ph-currency-circle-dollar"></i>
<span>Financials & Reports</span>
</a>
<a class="nav-item" data-view="complaintsView">
<i class="ph ph-warning-circle"></i>
<span>Support & Complaints</span>
</a>
<a class="nav-item" data-view="systemView">
<i class="ph ph-cpu"></i>
<span>System Status</span>
</a>
</nav>
<div class="sidebar-footer">
<div class="user-profile-mini">
<div class="avatar">SA</div>
<div class="user-info">
<div class="name">Super Admin</div>
<div class="role">Operations Lead</div>
</div>
</div>
<button class="btn-icon" id="logoutBtn" title="Sign Out">
<i class="ph ph-sign-out"></i>
</button>
</div>
</aside>
<!-- Main Content Body -->
<div class="main-wrapper">
<!-- Top Sticky Header -->
<header class="top-header">
<div class="header-left">
<button class="btn-icon toggle-sidebar-btn" id="toggleSidebar">
<i class="ph ph-list"></i>
</button>
<div class="search-box">
<i class="ph ph-magnifying-glass"></i>
<input type="text" id="globalSearch" placeholder="Search trips, drivers, passengers...">
</div>
</div>
<div class="header-right">
<div class="live-indicator">
<span class="pulse-dot"></span> Live Fleet Network
</div>
<button class="btn-icon" title="Notifications">
<i class="ph ph-bell"></i>
</button>
<button class="btn-icon" title="Settings">
<i class="ph ph-gear"></i>
</button>
</div>
</header>
<main class="content-body">
<!-- ================= 1. DASHBOARD OVERVIEW ================= -->
<section class="page-view active" id="dashboardView">
<div class="page-header">
<div class="page-title">
<h1>Operations Dashboard</h1>
<p>Real-time analytics and fleet performance metrics</p>
</div>
<div class="page-actions">
<button class="btn btn-secondary"><i class="ph ph-calendar"></i> Today</button>
<button class="btn btn-primary" style="width: auto;"><i class="ph ph-download-simple"></i> Export PDF</button>
</div>
</div>
<!-- KPI Cards Grid -->
<div class="stats-grid">
<div class="stat-card">
<div class="stat-header">
<div>
<div class="stat-value">$42,850</div>
<div class="stat-title">Today's Revenue</div>
</div>
<div class="stat-icon primary"><i class="ph ph-currency-dollar"></i></div>
</div>
<div class="stat-footer">
<span class="trend-badge up"><i class="ph ph-trend-up"></i> +14.2%</span>
<span class="trend-text">vs yesterday</span>
</div>
</div>
<div class="stat-card">
<div class="stat-header">
<div>
<div class="stat-value">1,482</div>
<div class="stat-title">Active Rides</div>
</div>
<div class="stat-icon success"><i class="ph ph-car-profile"></i></div>
</div>
<div class="stat-footer">
<span class="trend-badge up"><i class="ph ph-trend-up"></i> +8.6%</span>
<span class="trend-text">fleet active</span>
</div>
</div>
<div class="stat-card">
<div class="stat-header">
<div>
<div class="stat-value">324</div>
<div class="stat-title">Captains Online</div>
</div>
<div class="stat-icon info"><i class="ph ph-steering-wheel"></i></div>
</div>
<div class="stat-footer">
<span class="trend-badge up"><i class="ph ph-check"></i> 94% online rate</span>
</div>
</div>
<div class="stat-card">
<div class="stat-header">
<div>
<div class="stat-value">98.4%</div>
<div class="stat-title">Dispatch Rate</div>
</div>
<div class="stat-icon warning"><i class="ph ph-lightning"></i></div>
</div>
<div class="stat-footer">
<span class="trend-badge down"><i class="ph ph-trend-down"></i> -0.4%</span>
<span class="trend-text">avg 3.2m wait</span>
</div>
</div>
</div>
<!-- Charts Section -->
<div class="dashboard-grid">
<div class="card">
<div class="card-header">
<h3 class="card-title">Revenue & Trip Surge Analytics</h3>
<button class="btn btn-secondary btn-sm">Weekly</button>
</div>
<div class="chart-container">
<canvas id="revenueChart"></canvas>
</div>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">Live Dispatch Feed</h3>
</div>
<div style="display:flex; flex-direction:column; gap:1rem;">
<div style="display:flex; align-items:center; gap:0.75rem; padding:0.75rem; background:rgba(255,255,255,0.03); border-radius:var(--radius-md);">
<div style="width:36px; height:36px; border-radius:var(--radius-full); background:var(--success-bg); color:var(--success); display:flex; align-items:center; justify-content:center;">
<i class="ph ph-check-circle"></i>
</div>
<div>
<div style="font-weight:600; font-size:0.88rem;">Ride SR-9842 Completed</div>
<div style="font-size:0.75rem; color:var(--text-subtle);">Driver: Khalid H. | $14.50</div>
</div>
</div>
<div style="display:flex; align-items:center; gap:0.75rem; padding:0.75rem; background:rgba(255,255,255,0.03); border-radius:var(--radius-md);">
<div style="width:36px; height:36px; border-radius:var(--radius-full); background:var(--primary-light); color:var(--primary); display:flex; align-items:center; justify-content:center;">
<i class="ph ph-arrows-clockwise"></i>
</div>
<div>
<div style="font-weight:600; font-size:0.88rem;">New Dispatch SR-9846</div>
<div style="font-size:0.75rem; color:var(--text-subtle);">Driver: Bilal M. | Sweifieh</div>
</div>
</div>
<div style="display:flex; align-items:center; gap:0.75rem; padding:0.75rem; background:rgba(255,255,255,0.03); border-radius:var(--radius-md);">
<div style="width:36px; height:36px; border-radius:var(--radius-full); background:var(--warning-bg); color:var(--warning); display:flex; align-items:center; justify-content:center;">
<i class="ph ph-star"></i>
</div>
<div>
<div style="font-weight:600; font-size:0.88rem;">5-Star Rating Submitted</div>
<div style="font-size:0.75rem; color:var(--text-subtle);">Rider: Sarah M.</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ================= 2. RIDES & DISPATCH VIEW ================= -->
<section class="page-view" id="ridesView">
<div class="page-header">
<div class="page-title">
<h1>Rides & Dispatch Management</h1>
<p>Monitor real-time passenger trips, statuses, and fare details</p>
</div>
<div class="page-actions">
<button class="btn btn-primary" style="width:auto;"><i class="ph ph-plus"></i> Manual Dispatch</button>
</div>
</div>
<div class="filter-bar">
<div class="filter-inputs">
<select class="select-input">
<option>All Statuses</option>
<option>Completed</option>
<option>In Progress</option>
<option>Cancelled</option>
</select>
<select class="select-input">
<option>All Cities</option>
<option>Amman</option>
<option>Zarqa</option>
<option>Irbid</option>
</select>
</div>
</div>
<div class="card">
<div class="table-responsive">
<table class="data-table">
<thead>
<tr>
<th>Trip ID</th>
<th>Passenger</th>
<th>Driver</th>
<th>Route</th>
<th>Fare</th>
<th>Status</th>
<th>Time</th>
<th>Action</th>
</tr>
</thead>
<tbody id="ridesTableBody">
<!-- Populated by JS -->
</tbody>
</table>
</div>
</div>
</section>
<!-- ================= 3. DRIVERS VIEW ================= -->
<section class="page-view" id="driversView">
<div class="page-header">
<div class="page-title">
<h1>Captains & Drivers</h1>
<p>Verify documents, manage online fleet, and inspect ratings</p>
</div>
<div class="page-actions">
<button class="btn btn-primary" style="width:auto;"><i class="ph ph-user-plus"></i> Add New Driver</button>
</div>
</div>
<div class="card">
<div class="table-responsive">
<table class="data-table">
<thead>
<tr>
<th>Driver ID</th>
<th>Name</th>
<th>Phone</th>
<th>Vehicle</th>
<th>Rating</th>
<th>Total Trips</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody id="driversTableBody">
<!-- Populated by JS -->
</tbody>
</table>
</div>
</div>
</section>
<!-- ================= 4. PASSENGERS VIEW ================= -->
<section class="page-view" id="passengersView">
<div class="page-header">
<div class="page-title">
<h1>Passengers & Customers</h1>
<p>Customer accounts, trip history, and subscription status</p>
</div>
</div>
<div class="card">
<div class="table-responsive">
<table class="data-table">
<thead>
<tr>
<th>Customer ID</th>
<th>Name</th>
<th>Email</th>
<th>Trips Count</th>
<th>Rating</th>
<th>Joined Date</th>
<th>Account Status</th>
<th>Action</th>
</tr>
</thead>
<tbody id="passengersTableBody">
<!-- Populated by JS -->
</tbody>
</table>
</div>
</div>
</section>
<!-- ================= 5. FINANCIALS VIEW ================= -->
<section class="page-view" id="financialsView">
<div class="page-header">
<div class="page-title">
<h1>Financials & Reports</h1>
<p>Payout calculations, platform commissions, and exported ledgers</p>
</div>
<div class="page-actions">
<button class="btn btn-primary" style="width:auto;"><i class="ph ph-file-text"></i> Generate Report</button>
</div>
</div>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value">$184,200</div>
<div class="stat-title">Gross Revenue (This Month)</div>
</div>
<div class="stat-card">
<div class="stat-value">$27,630</div>
<div class="stat-title">Platform Net Commission (15%)</div>
</div>
<div class="stat-card">
<div class="stat-value">$156,570</div>
<div class="stat-title">Driver Payouts Processed</div>
</div>
</div>
</section>
<!-- ================= 6. COMPLAINTS VIEW ================= -->
<section class="page-view" id="complaintsView">
<div class="page-header">
<div class="page-title">
<h1>Support & Complaints Triage</h1>
<p>Customer issues, lost & found, and ride rating disputes</p>
</div>
</div>
<div class="card">
<div style="padding:1rem; text-align:center; color:var(--text-muted);">
<i class="ph ph-shield-check" style="font-size:3rem; color:var(--success); margin-bottom:0.5rem; display:block;"></i>
<h3>All high-priority complaints resolved</h3>
<p style="font-size:0.88rem; margin-top:0.25rem;">0 active tickets requiring immediate escalation.</p>
</div>
</div>
</section>
<!-- ================= 7. SYSTEM STATUS VIEW ================= -->
<section class="page-view" id="systemView">
<div class="page-header">
<div class="page-title">
<h1>System Health & Microservices</h1>
<p>Server nodes, API gateways, database latency, and websocket connections</p>
</div>
</div>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-header">
<div>
<div class="stat-value" style="color:var(--success);">Healthy</div>
<div class="stat-title">Location Server</div>
</div>
<div class="stat-icon success"><i class="ph ph-map-pin-line"></i></div>
</div>
<div class="stat-footer"><span class="trend-text">Latency: 14ms</span></div>
</div>
<div class="stat-card">
<div class="stat-header">
<div>
<div class="stat-value" style="color:var(--success);">Healthy</div>
<div class="stat-title">Ride Dispatch Engine</div>
</div>
<div class="stat-icon success"><i class="ph ph-cpu"></i></div>
</div>
<div class="stat-footer"><span class="trend-text">Latency: 22ms</span></div>
</div>
<div class="stat-card">
<div class="stat-header">
<div>
<div class="stat-value" style="color:var(--success);">Healthy</div>
<div class="stat-title">Payment Server</div>
</div>
<div class="stat-icon success"><i class="ph ph-credit-card"></i></div>
</div>
<div class="stat-footer"><span class="trend-text">Latency: 45ms</span></div>
</div>
</div>
</section>
</main>
</div>
</div>
<!-- Details Modal -->
<div class="modal-overlay" id="detailsModal">
<div class="modal-content">
<div id="modalBodyContent">
<!-- Dynamic content -->
</div>
</div>
</div>
<script src="js/app.js"></script>
</body>
</html>
+333
View File
@@ -0,0 +1,333 @@
/* ==========================================================================
Siro Admin Web Portal - Interactive Application Engine
========================================================================== */
document.addEventListener('DOMContentLoaded', () => {
// DOM Elements
const authWrapper = document.getElementById('authWrapper');
const loginForm = document.getElementById('loginForm');
const navItems = document.querySelectorAll('.nav-item[data-view]');
const pageViews = document.querySelectorAll('.page-view');
const logoutBtn = document.getElementById('logoutBtn');
const sidebar = document.getElementById('sidebar');
const toggleSidebarBtn = document.getElementById('toggleSidebar');
// Sample State & Datasets
let currentUser = JSON.parse(localStorage.getItem('siro_admin_user')) || null;
const mockRides = [
{ id: 'SR-9842', rider: 'Ahmad Al-Mansoor', driver: 'Khalid Hassan', pickup: 'Abdoun, Amman', dropoff: '7th Circle', fare: '$14.50', status: 'Completed', time: '10 mins ago' },
{ id: 'SR-9843', rider: 'Sarah Mahmoud', driver: 'Omar Farooq', pickup: 'Jabal Amman', dropoff: 'Queen Alia Airport', fare: '$28.00', status: 'In Progress', time: 'Just now' },
{ id: 'SR-9844', rider: 'Tariq Ziyad', driver: 'Youssef Ali', pickup: 'Sweifieh Mall', dropoff: 'University of Jordan', fare: '$9.20', status: 'Completed', time: '25 mins ago' },
{ id: 'SR-9845', rider: 'Reem Kanaan', driver: 'Hassan Nabil', pickup: 'Mecca Street', dropoff: 'Tabarbour', fare: '$11.80', status: 'Cancelled', time: '40 mins ago' },
{ id: 'SR-9846', rider: 'Fadi Jarrah', driver: 'Bilal Mustafa', pickup: 'Khalda', dropoff: 'Shmeisani', fare: '$16.00', status: 'In Progress', time: '5 mins ago' },
];
const mockDrivers = [
{ id: 'DRV-101', name: 'Khalid Hassan', phone: '+962 7 9123 4567', vehicle: 'Toyota Camry 2022', rating: '4.95', trips: 1420, status: 'Online', verified: true },
{ id: 'DRV-102', name: 'Omar Farooq', phone: '+962 7 8876 5432', vehicle: 'Hyundai Elantra 2021', rating: '4.88', trips: 980, status: 'In Trip', verified: true },
{ id: 'DRV-103', name: 'Youssef Ali', phone: '+962 7 7654 3210', vehicle: 'Kia Optima 2023', rating: '4.90', trips: 1150, status: 'Online', verified: true },
{ id: 'DRV-104', name: 'Hassan Nabil', phone: '+962 7 9988 7766', vehicle: 'Nissan Sentra 2020', rating: '4.72', trips: 620, status: 'Offline', verified: false },
];
const mockPassengers = [
{ id: 'PSG-501', name: 'Ahmad Al-Mansoor', email: 'ahmad@example.com', trips: 45, rating: '4.9', joined: 'Jan 2025', status: 'Active' },
{ id: 'PSG-502', name: 'Sarah Mahmoud', email: 'sarah.m@example.com', trips: 89, rating: '5.0', joined: 'Nov 2024', status: 'Active' },
{ id: 'PSG-503', name: 'Reem Kanaan', email: 'reem.k@example.com', trips: 12, rating: '4.6', joined: 'Mar 2025', status: 'Suspended' },
];
// Initialize App
function initApp() {
checkAuth();
setupNavigation();
renderRidesTable();
renderDriversTable();
renderPassengersTable();
initCharts();
setupEvents();
}
// Auth Functions
function checkAuth() {
if (currentUser) {
authWrapper.classList.add('hidden');
} else {
authWrapper.classList.remove('hidden');
}
}
loginForm?.addEventListener('submit', (e) => {
e.preventDefault();
const email = document.getElementById('loginEmail').value;
currentUser = { name: 'Super Admin', email: email, role: 'Administrator' };
localStorage.setItem('siro_admin_user', JSON.stringify(currentUser));
authWrapper.classList.add('hidden');
showNotification('Welcome back, Super Admin!', 'success');
});
logoutBtn?.addEventListener('click', () => {
localStorage.removeItem('siro_admin_user');
currentUser = null;
authWrapper.classList.remove('hidden');
});
// Sidebar & Navigation
function setupNavigation() {
navItems.forEach(item => {
item.addEventListener('click', (e) => {
e.preventDefault();
const targetView = item.getAttribute('data-view');
navItems.forEach(n => n.classList.remove('active'));
item.classList.add('active');
pageViews.forEach(view => {
if (view.id === targetView) {
view.classList.add('active');
} else {
view.classList.remove('active');
}
});
// Close sidebar on mobile
if (window.innerWidth <= 992) {
sidebar.classList.remove('open');
}
});
});
toggleSidebarBtn?.addEventListener('click', () => {
sidebar.classList.toggle('open');
});
}
// Render Data Tables
function renderRidesTable() {
const tbody = document.getElementById('ridesTableBody');
if (!tbody) return;
tbody.innerHTML = mockRides.map(ride => `
<tr>
<td><strong>${ride.id}</strong></td>
<td>${ride.rider}</td>
<td>${ride.driver}</td>
<td><span style="font-size:0.82rem; color: var(--text-muted);"><i class="ph ph-map-pin"></i> ${ride.pickup} → ${ride.dropoff}</span></td>
<td><strong>${ride.fare}</strong></td>
<td><span class="badge ${getStatusBadge(ride.status)}">${ride.status}</span></td>
<td>${ride.time}</td>
<td>
<button class="btn btn-secondary btn-sm" onclick="viewDetails('${ride.id}')">
<i class="ph ph-eye"></i> View
</button>
</td>
</tr>
`).join('');
}
function renderDriversTable() {
const tbody = document.getElementById('driversTableBody');
if (!tbody) return;
tbody.innerHTML = mockDrivers.map(drv => `
<tr>
<td><strong>${drv.id}</strong></td>
<td>
<div style="display:flex; align-items:center; gap:0.5rem;">
<span>${drv.name}</span>
${drv.verified ? '<i class="ph-fill ph-seal-check" style="color:var(--info);" title="Verified"></i>' : ''}
</div>
</td>
<td>${drv.phone}</td>
<td>${drv.vehicle}</td>
<td><i class="ph-fill ph-star" style="color:var(--warning);"></i> ${drv.rating}</td>
<td>${drv.trips}</td>
<td><span class="badge ${getStatusBadge(drv.status)}">${drv.status}</span></td>
<td>
<button class="btn btn-secondary btn-sm"><i class="ph ph-gear"></i> Manage</button>
</td>
</tr>
`).join('');
}
function renderPassengersTable() {
const tbody = document.getElementById('passengersTableBody');
if (!tbody) return;
tbody.innerHTML = mockPassengers.map(p => `
<tr>
<td><strong>${p.id}</strong></td>
<td>${p.name}</td>
<td>${p.email}</td>
<td>${p.trips} trips</td>
<td><i class="ph-fill ph-star" style="color:var(--warning);"></i> ${p.rating}</td>
<td>${p.joined}</td>
<td><span class="badge ${getStatusBadge(p.status)}">${p.status}</span></td>
<td>
<button class="btn btn-secondary btn-sm"><i class="ph ph-user"></i> Profile</button>
</td>
</tr>
`).join('');
}
function getStatusBadge(status) {
switch (status) {
case 'Completed':
case 'Online':
case 'Active':
return 'badge-success';
case 'In Progress':
case 'In Trip':
return 'badge-primary';
case 'Cancelled':
case 'Offline':
case 'Suspended':
return 'badge-danger';
default:
return 'badge-info';
}
}
// Dynamic Canvas Charts
function initCharts() {
const canvas = document.getElementById('revenueChart');
if (!canvas) return;
const ctx = canvas.getContext('2d');
// Resize canvas
canvas.width = canvas.parentElement.clientWidth;
canvas.height = canvas.parentElement.clientHeight;
const data = [12000, 18500, 15000, 24000, 29000, 34500, 42000];
const labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
const W = canvas.width;
const H = canvas.height;
const padding = 40;
// Draw Grid Lines
ctx.strokeStyle = 'rgba(255, 255, 255, 0.05)';
ctx.lineWidth = 1;
for (let i = 0; i <= 4; i++) {
const y = padding + (i * (H - padding * 2) / 4);
ctx.beginPath();
ctx.moveTo(padding, y);
ctx.lineTo(W - padding, y);
ctx.stroke();
}
// Draw Smooth Line
const max = 50000;
const points = data.map((val, idx) => {
const x = padding + (idx * (W - padding * 2) / (data.length - 1));
const y = H - padding - (val / max * (H - padding * 2));
return { x, y };
});
// Area Gradient
const gradient = ctx.createLinearGradient(0, 0, 0, H);
gradient.addColorStop(0, 'rgba(99, 102, 241, 0.4)');
gradient.addColorStop(1, 'rgba(99, 102, 241, 0.0)');
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
for (let i = 1; i < points.length; i++) {
const xc = (points[i].x + points[i - 1].x) / 2;
const yc = (points[i].y + points[i - 1].y) / 2;
ctx.quadraticCurveTo(points[i - 1].x, points[i - 1].y, xc, yc);
}
ctx.lineTo(points[points.length - 1].x, points[points.length - 1].y);
ctx.lineTo(points[points.length - 1].x, H - padding);
ctx.lineTo(points[0].x, H - padding);
ctx.closePath();
ctx.fillStyle = gradient;
ctx.fill();
// Line Path
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
for (let i = 1; i < points.length; i++) {
const xc = (points[i].x + points[i - 1].x) / 2;
const yc = (points[i].y + points[i - 1].y) / 2;
ctx.quadraticCurveTo(points[i - 1].x, points[i - 1].y, xc, yc);
}
ctx.lineTo(points[points.length - 1].x, points[points.length - 1].y);
ctx.strokeStyle = '#6366f1';
ctx.lineWidth = 3;
ctx.stroke();
// Draw Points
points.forEach((p, idx) => {
ctx.beginPath();
ctx.arc(p.x, p.y, 5, 0, Math.PI * 2);
ctx.fillStyle = '#6366f1';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = '#fff';
ctx.stroke();
// Labels
ctx.fillStyle = '#94a3b8';
ctx.font = '12px Inter';
ctx.textAlign = 'center';
ctx.fillText(labels[idx], p.x, H - 15);
});
}
// Setup Event Listeners & Search Filters
function setupEvents() {
window.addEventListener('resize', () => {
initCharts();
});
const searchInput = document.getElementById('globalSearch');
searchInput?.addEventListener('input', (e) => {
const query = e.target.value.toLowerCase();
// Highlight matching items in tables if any
});
}
// Notifications Helper
function showNotification(msg, type = 'info') {
const toast = document.createElement('div');
toast.style.cssText = `
position: fixed;
bottom: 24px;
right: 24px;
background: var(--bg-elevated);
border: 1px solid var(--border-active);
color: #fff;
padding: 12px 20px;
border-radius: 12px;
box-shadow: var(--shadow-md);
z-index: 9999;
font-size: 0.9rem;
animation: fadeIn 0.3s ease;
`;
toast.innerHTML = `<i class="ph ph-check-circle" style="color:var(--success);"></i> ${msg}`;
document.body.appendChild(toast);
setTimeout(() => toast.remove(), 3500);
}
window.viewDetails = function(id) {
const modal = document.getElementById('detailsModal');
const modalBody = document.getElementById('modalBodyContent');
if (!modal || !modalBody) return;
modalBody.innerHTML = `
<h3 style="margin-bottom:1rem; color:#fff;">Ride Details: ${id}</h3>
<p style="color:var(--text-muted); margin-bottom:0.5rem;"><strong>Pickup:</strong> Abdoun Circle, Amman</p>
<p style="color:var(--text-muted); margin-bottom:0.5rem;"><strong>Dropoff:</strong> Queen Alia International Airport</p>
<p style="color:var(--text-muted); margin-bottom:0.5rem;"><strong>Fare Breakdown:</strong> Base Fare ($4.00) + Distance ($20.00) + Peak Surge ($4.00)</p>
<p style="color:var(--text-muted); margin-bottom:1.5rem;"><strong>Payment Method:</strong> Credit Card (Visa **** 4921)</p>
<div style="text-align:right;">
<button class="btn btn-secondary" onclick="closeModal()">Close</button>
</div>
`;
modal.classList.add('active');
};
window.closeModal = function() {
const modal = document.getElementById('detailsModal');
modal?.classList.remove('active');
};
// Run initial state
initApp();
});
+126
View File
@@ -0,0 +1,126 @@
/* ==========================================================================
Siro Service Web Portal - Modern Design System
========================================================================== */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700&display=swap');
:root {
--bg-dark: #090d16;
--bg-card: rgba(17, 24, 39, 0.75);
--border-color: rgba(255, 255, 255, 0.08);
--primary: #06b6d4;
--accent: #3b82f6;
--text-main: #f8fafc;
--text-muted: #94a3b8;
--radius-lg: 18px;
}
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Inter', sans-serif;
background-color: var(--bg-dark);
color: var(--text-main);
min-height: 100vh;
display: flex;
flex-direction: column;
}
header {
padding: 1.5rem 3rem;
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
backdrop-filter: blur(12px);
}
.logo {
display: flex;
align-items: center;
gap: 0.75rem;
font-family: 'Outfit', sans-serif;
font-size: 1.5rem;
font-weight: 700;
}
.logo i {
color: var(--primary);
}
main {
flex: 1;
padding: 3rem;
max-width: 1200px;
margin: 0 auto;
width: 100%;
}
.hero-card {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: 3rem;
text-align: center;
backdrop-filter: blur(16px);
}
.hero-card h1 {
font-size: 2.25rem;
margin-bottom: 1rem;
background: linear-gradient(135deg, #fff, var(--primary));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.services-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
margin-top: 2.5rem;
}
.service-card {
background: rgba(30, 41, 59, 0.4);
border: 1px solid var(--border-color);
border-radius: 14px;
padding: 1.75rem;
text-align: left;
transition: all 0.3s ease;
}
.service-card:hover {
transform: translateY(-4px);
border-color: var(--primary);
}
.service-icon {
width: 48px;
height: 48px;
border-radius: 12px;
background: rgba(6, 182, 212, 0.15);
color: var(--primary);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
margin-bottom: 1rem;
}
.btn-cyan {
background: linear-gradient(135deg, var(--primary), var(--accent));
color: white;
padding: 0.75rem 1.5rem;
border-radius: 10px;
border: none;
font-weight: 600;
cursor: pointer;
margin-top: 1.5rem;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
+61
View File
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Siro Service | Fleet & Maintenance Portal</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700&display=swap" rel="stylesheet">
<script src="https://unpkg.com/@phosphor-icons/web"></script>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<header>
<div class="logo">
<i class="ph-bold ph-wrench"></i>
<span>SIRO SERVICE</span>
</div>
<div>
<span style="font-size:0.88rem; color:var(--text-muted);"><i class="ph-fill ph-circle-pulse" style="color:#10b981;"></i> Service Hub Online</span>
</div>
</header>
<main>
<div class="hero-card">
<h1>Siro Fleet Maintenance & Service Center</h1>
<p style="color:var(--text-muted); max-width:600px; margin:0 auto;">
Dedicated web portal for registered service centers, vehicle inspection, maintenance scheduling, and captain support services.
</p>
<div class="services-grid">
<div class="service-card">
<div class="service-icon"><i class="ph ph-shield-check"></i></div>
<h3 style="margin-bottom:0.5rem; font-size:1.1rem;">Vehicle Inspection</h3>
<p style="font-size:0.88rem; color:var(--text-muted);">Perform 50-point technical inspections and issue digital safety permits for captains.</p>
</div>
<div class="service-card">
<div class="service-icon"><i class="ph ph-gas-pump"></i></div>
<h3 style="margin-bottom:0.5rem; font-size:1.1rem;">Fuel & EV Charging</h3>
<p style="font-size:0.88rem; color:var(--text-muted);">Manage partner station discounts, EV charging session ledgers, and fuel vouchers.</p>
</div>
<div class="service-card">
<div class="service-icon"><i class="ph ph-arrows-counter-clockwise"></i></div>
<h3 style="margin-bottom:0.5rem; font-size:1.1rem;">Maintenance Scheduling</h3>
<p style="font-size:0.88rem; color:var(--text-muted);">Routine oil changes, tire rotations, and scheduled service appointments for active fleet.</p>
</div>
</div>
<button class="btn-cyan" onclick="alert('Siro Service Dispatch Agent initialized successfully.')">
<i class="ph ph-power"></i> Launch Service Desk
</button>
</div>
</main>
</body>
</html>