Files
musadaq-saas/public/shell.php
2026-05-03 22:51:59 +03:00

290 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ar" dir="rtl" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>مُصادَق | لوحة التحكم</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
<style>
:root {
--emerald: #10b981;
--bg-base: #080c14;
--bg-surface: #0d1424;
--border-default: rgba(255,255,255,0.1);
--text-primary: #f0f6fc;
}
body { font-family: 'IBM Plex Sans Arabic', sans-serif; background-color: var(--bg-base); color: var(--text-primary); }
</style>
</head>
<body x-data="app" x-init="init()">
<div class="flex h-screen overflow-hidden">
<!-- Sidebar -->
<aside class="w-64 bg-surface border-l border-gray-800 flex flex-col">
<div class="p-6">
<h1 class="text-xl font-bold text-emerald-500">مُصادَق</h1>
</div>
<nav class="flex-1 px-4 space-y-2">
<a href="#" @click="page='dashboard'" class="block p-3 rounded hover:bg-gray-800" :class="page==='dashboard'?'bg-emerald-900/20 text-emerald-500':''">📊 لوحة التحكم</a>
<a href="#" @click="page='companies'" class="block p-3 rounded hover:bg-gray-800" :class="page==='companies'?'bg-emerald-900/20 text-emerald-500':''">🏢 الشركات</a>
<a x-show="user?.role === 'super_admin' || user?.role === 'admin'" href="#" @click="page='users'" class="block p-3 rounded hover:bg-gray-800" :class="page==='users'?'bg-emerald-900/20 text-emerald-500':''">👥 المستخدمون</a>
</nav>
<div class="p-6 border-t border-gray-800">
<button @click="logout()" class="w-full text-right text-red-400 text-sm">🚪 تسجيل الخروج</button>
</div>
</aside>
<!-- Main -->
<main class="flex-1 overflow-y-auto p-10">
<header class="mb-10 flex justify-between items-center">
<h2 class="text-2xl font-bold" x-text="title()"></h2>
<div class="flex items-center gap-4">
<button x-show="page==='users' && (user?.role === 'super_admin' || user?.role === 'admin')" @click="showAddModal = true" class="bg-emerald-600 hover:bg-emerald-500 px-4 py-2 rounded text-sm font-bold transition"> إضافة مستخدم</button>
<button x-show="page==='companies' && (user?.role === 'super_admin' || user?.role === 'admin')" @click="showAddCompanyModal = true" class="bg-emerald-600 hover:bg-emerald-500 px-4 py-2 rounded text-sm font-bold transition"> إضافة شركة</button>
<div class="text-sm text-gray-500" x-text="user?.name"></div>
</div>
</header>
<div id="content">
<!-- Dashboard -->
<div x-show="page === 'dashboard'">
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="p-6 bg-surface border border-gray-800 rounded">
<p class="text-gray-500 text-sm">إجمالي الفواتير</p>
<p class="text-3xl font-bold mt-2" x-text="stats.total"></p>
</div>
<div class="p-6 bg-surface border border-gray-800 rounded">
<p class="text-gray-500 text-sm">قيد المعالجة</p>
<p class="text-3xl font-bold mt-2 text-yellow-500" x-text="stats.pending"></p>
</div>
<div class="p-6 bg-surface border border-gray-800 rounded">
<p class="text-gray-500 text-sm">تم الاعتماد</p>
<p class="text-3xl font-bold mt-2 text-emerald-500" x-text="stats.approved"></p>
</div>
</div>
</div>
<!-- Companies -->
<div x-show="page === 'companies'">
<div class="bg-surface border border-gray-800 rounded overflow-hidden">
<table class="w-full text-right">
<thead class="bg-gray-900/50">
<tr>
<th class="p-4">اسم الشركة</th>
<th class="p-4">الرقم الضريبي</th>
<th class="p-4">رقم التسجيل</th>
<th class="p-4">تاريخ الإضافة</th>
</tr>
</thead>
<tbody>
<template x-for="c in companies" :key="c.id">
<tr class="border-t border-gray-800">
<td class="p-4 font-bold text-emerald-500" x-text="c.name"></td>
<td class="p-4" x-text="c.tax_number"></td>
<td class="p-4" x-text="c.registration_number"></td>
<td class="p-4 text-xs text-gray-500" x-text="c.created_at"></td>
</tr>
</template>
</tbody>
</table>
</div>
</div>
<!-- Users -->
<div x-show="page === 'users'">
<div class="bg-surface border border-gray-800 rounded overflow-hidden">
<table class="w-full text-right">
<thead class="bg-gray-900/50">
<tr>
<th class="p-4">الاسم</th>
<th class="p-4">البريد الإلكتروني</th>
<th class="p-4">المكتب</th>
<th class="p-4">الشركة المعينة</th>
<th class="p-4">الدور</th>
</tr>
</thead>
<tbody>
<template x-for="u in users" :key="u.id">
<tr class="border-t border-gray-800">
<td class="p-4" x-text="u.name"></td>
<td class="p-4" x-text="u.email"></td>
<td class="p-4 text-xs text-gray-400" x-text="u.tenant_name || '-'"></td>
<td class="p-4 text-xs text-gray-400" x-text="u.company_name || 'كامل المكتب'"></td>
<td class="p-4 text-xs uppercase text-gray-500">
<span class="px-2 py-1 bg-gray-800 rounded" x-text="u.role"></span>
</td>
</tr>
</template>
</tbody>
</table>
</div>
</div>
</div>
</main>
<!-- Add User Modal -->
<div x-show="showAddModal" class="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center p-4 z-50" x-cloak>
<div class="bg-surface border border-gray-800 w-full max-w-md p-8 rounded-lg shadow-2xl" @click.away="showAddModal = false">
<h3 class="text-xl font-bold mb-6">إضافة مستخدم جديد 👤</h3>
<form @submit.prevent="createUser" class="space-y-4">
<div>
<label class="block text-xs text-gray-500 uppercase mb-1">الاسم الكامل</label>
<input type="text" x-model="newUser.name" class="w-full bg-gray-950 border border-gray-800 p-3 rounded outline-none focus:border-emerald-500" required>
</div>
<div>
<label class="block text-xs text-gray-500 uppercase mb-1">البريد الإلكتروني</label>
<input type="email" x-model="newUser.email" class="w-full bg-gray-950 border border-gray-800 p-3 rounded outline-none focus:border-emerald-500" required>
</div>
<div>
<label class="block text-xs text-gray-500 uppercase mb-1">كلمة المرور</label>
<input type="password" x-model="newUser.password" class="w-full bg-gray-950 border border-gray-800 p-3 rounded outline-none focus:border-emerald-500" required>
</div>
<div>
<label class="block text-xs text-gray-500 uppercase mb-1">الدور</label>
<select x-model="newUser.role" class="w-full bg-gray-950 border border-gray-800 p-3 rounded outline-none focus:border-emerald-500">
<option value="employee">موظف</option>
<option value="accountant">محاسب</option>
<option value="admin">مدير نظام</option>
</select>
</div>
<div class="pt-4 flex gap-3">
<button type="submit" class="flex-1 bg-emerald-600 hover:bg-emerald-500 py-3 rounded font-bold transition">حفظ المستخدم</button>
<button type="button" @click="showAddModal = false" class="px-6 py-3 border border-gray-800 rounded hover:bg-gray-800 transition">إلغاء</button>
</div>
</form>
</div>
</div>
<!-- Add Company Modal -->
<div x-show="showAddCompanyModal" class="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center p-4 z-50" x-cloak>
<div class="bg-surface border border-gray-800 w-full max-w-md p-8 rounded-lg shadow-2xl" @click.away="showAddCompanyModal = false">
<h3 class="text-xl font-bold mb-6">إنشاء شركة جديدة 🏢</h3>
<form @submit.prevent="createCompany" class="space-y-4">
<div>
<label class="block text-xs text-gray-500 uppercase mb-1">اسم الشركة</label>
<input type="text" x-model="newCompany.name" class="w-full bg-gray-950 border border-gray-800 p-3 rounded outline-none focus:border-emerald-500" required>
</div>
<div>
<label class="block text-xs text-gray-500 uppercase mb-1">الرقم الضريبي</label>
<input type="text" x-model="newCompany.tax_identification_number" class="w-full bg-gray-950 border border-gray-800 p-3 rounded outline-none focus:border-emerald-500">
</div>
<div>
<label class="block text-xs text-gray-500 uppercase mb-1">رقم التسجيل</label>
<input type="text" x-model="newCompany.commercial_registration_number" class="w-full bg-gray-950 border border-gray-800 p-3 rounded outline-none focus:border-emerald-500">
</div>
<div>
<label class="block text-xs text-gray-500 uppercase mb-1">العنوان</label>
<textarea x-model="newCompany.address" class="w-full bg-gray-950 border border-gray-800 p-3 rounded outline-none focus:border-emerald-500"></textarea>
</div>
<div class="pt-4 flex gap-3">
<button type="submit" class="flex-1 bg-emerald-600 hover:bg-emerald-500 py-3 rounded font-bold transition">حفظ الشركة</button>
<button type="button" @click="showAddCompanyModal = false" class="px-6 py-3 border border-gray-800 rounded hover:bg-gray-800 transition">إلغاء</button>
</div>
</form>
</div>
</div>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('app', () => ({
user: JSON.parse(localStorage.getItem('user')),
page: 'dashboard',
users: [],
companies: [],
stats: { total: 0, pending: 0, approved: 0 },
showAddModal: false,
showAddCompanyModal: false,
newUser: { name: '', email: '', password: '', role: 'employee' },
newCompany: { name: '', tax_identification_number: '', commercial_registration_number: '', address: '' },
init() {
if (!this.user) window.location.href = '/login.php';
this.loadUsers();
this.loadStats();
this.loadCompanies();
},
title() {
return { dashboard: 'لوحة التحكم', users: 'المستخدمون', companies: 'الشركات' }[this.page];
},
async loadUsers() {
const res = await fetch('/api/v1/users', {
headers: { 'Authorization': 'Bearer ' + localStorage.getItem('access_token') }
});
if (res.status === 401) this.logout();
const json = await res.json();
if (json.success) this.users = json.data;
},
async loadCompanies() {
const res = await fetch('/api/v1/companies', {
headers: { 'Authorization': 'Bearer ' + localStorage.getItem('access_token') }
});
const json = await res.json();
if (json.success) this.companies = json.data;
},
async loadStats() {
const res = await fetch('/api/v1/dashboard/stats', {
headers: { 'Authorization': 'Bearer ' + localStorage.getItem('access_token') }
});
const json = await res.json();
if (json.success) this.stats = json.data;
},
async createUser() {
const res = await fetch('/api/v1/users/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem('access_token')
},
body: JSON.stringify(this.newUser)
});
const json = await res.json();
if (json.success) {
this.showAddModal = false;
this.newUser = { name: '', email: '', password: '', role: 'employee' };
this.loadUsers();
alert('تم إضافة المستخدم بنجاح');
} else {
alert(json.message);
}
},
async createCompany() {
const res = await fetch('/api/v1/companies/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem('access_token')
},
body: JSON.stringify(this.newCompany)
});
const json = await res.json();
if (json.success) {
this.showAddCompanyModal = false;
this.newCompany = { name: '', tax_identification_number: '', commercial_registration_number: '', address: '' };
this.loadCompanies();
alert('تم إنشاء الشركة بنجاح');
} else {
alert(json.message);
}
},
logout() {
localStorage.clear();
window.location.href = '/login.php';
}
}));
});
</script>
</body>
</html>