🚀 مُصادَق: الإطلاق الأولي للنظام المتكامل

This commit is contained in:
Hamza-Ayed
2026-05-03 00:59:39 +03:00
commit d0e538408d
43 changed files with 2554 additions and 0 deletions

85
public/assets/css/app.css Normal file
View File

@@ -0,0 +1,85 @@
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@400;500;600;700&family=JetBrains+Mono&family=Inter:wght@400;500;600&display=swap');
:root {
--primary: #10b981;
--primary-hover: #059669;
--primary-muted: rgba(16,185,129,0.1);
--danger: #ef4444;
--warning: #f59e0b;
--info: #3b82f6;
--success: #22c55e;
/* Dark (default) */
--bg-app: #0a0f1a;
--bg-card: rgba(15,23,42,0.8);
--bg-sidebar: #060b14;
--bg-input: rgba(15,23,42,0.6);
--border: rgba(51,65,85,0.6);
--text-primary: #f1f5f9;
--text-secondary: #94a3b8;
--text-muted: #475569;
--glass: rgba(15,23,42,0.6);
--glass-border: rgba(255,255,255,0.06);
--shadow-glow: 0 0 40px rgba(16,185,129,0.08);
}
[data-theme="light"] {
--bg-app: #f1f5f9;
--bg-card: #ffffff;
--bg-sidebar: #ffffff;
--bg-input: #f8fafc;
--border: #e2e8f0;
--text-primary: #0f172a;
--text-secondary: #475569;
--text-muted: #94a3b8;
--glass: rgba(255,255,255,0.8);
--glass-border: rgba(0,0,0,0.04);
--shadow-glow: 0 4px 24px rgba(0,0,0,0.06);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Inter', 'IBM Plex Sans Arabic', sans-serif;
}
body {
background-color: var(--bg-app);
color: var(--text-primary);
direction: rtl;
min-height: 100vh;
overflow-x: hidden;
transition: background-color 0.3s, color 0.3s;
}
/* Glassmorphism Utilities */
.glass {
background: var(--glass);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid var(--glass-border);
}
.glow {
box-shadow: var(--shadow-glow);
}
/* Custom Scrollbar */
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--border);
border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-muted);
}
/* RTL Specifics */
[dir="rtl"] .ml-auto { margin-right: auto; margin-left: 0; }
[dir="rtl"] .mr-auto { margin-left: auto; margin-right: 0; }

76
public/assets/js/api.js Normal file
View File

@@ -0,0 +1,76 @@
/**
* مُصادَق — API Client with JWT Auth & Refresh Flow
*/
const API = {
baseUrl: '/api/v1',
accessToken: localStorage.getItem('access_token'),
async get(path) {
return this._request('GET', path);
},
async post(path, body) {
return this._request('POST', path, body);
},
async upload(path, formData) {
return this._request('POST', path, formData, true);
},
async _request(method, path, body = null, isFormData = false) {
const headers = {
'Accept': 'application/json',
};
if (this.accessToken) {
headers['Authorization'] = `Bearer ${this.accessToken}`;
}
if (!isFormData && body) {
headers['Content-Type'] = 'application/json';
body = JSON.stringify(body);
}
try {
const response = await fetch(`${this.baseUrl}${path}`, {
method,
headers,
body
});
if (response.status === 401) {
// Try refresh token
const refreshed = await this.refreshToken();
if (refreshed) {
return this._request(method, path, body, isFormData);
} else {
window.location.href = '/login';
}
}
const data = await response.json();
if (!response.ok) throw data;
return data;
} catch (error) {
console.error('API Error:', error);
throw error;
}
},
async refreshToken() {
try {
const response = await fetch(`${this.baseUrl}/auth/refresh`, { method: 'POST' });
if (response.ok) {
const result = await response.json();
this.accessToken = result.data.access_token;
localStorage.setItem('access_token', this.accessToken);
return true;
}
} catch (e) {
return false;
}
return false;
}
};
export default API;