import React, { useEffect, useMemo, useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Building2, CalendarCheck, Crown, FileText, LayoutDashboard, LogOut, Shield, User, Users, WalletCards, BriefcaseBusiness, ClipboardCheck, Settings, BarChart3, Clock3, PackageCheck } from 'lucide-react'; import './styles.css'; const API_URL = import.meta.env.VITE_API_URL || 'http://127.0.0.1:4000/api'; const roleMeta = { admin: { label: 'لوحة الأدمن', icon: Shield, color: 'purple' }, client: { label: 'لوحة العميل', icon: User, color: 'blue' }, company: { label: 'لوحة الشركة', icon: Building2, color: 'green' }, employee: { label: 'لوحة الموظف', icon: BriefcaseBusiness, color: 'orange' } }; const demoAccounts = [ ['admin@hr.test', 'أدمن'], ['client@hr.test', 'عميل'], ['company@hr.test', 'شركة'], ['employee@hr.test', 'موظف'] ]; function useApi(token) { return useMemo(() => ({ async get(path) { const res = await fetch(`${API_URL}${path}`, { headers: { Authorization: `Bearer ${token}` } }); if (!res.ok) throw new Error((await res.json()).message || 'API error'); return res.json(); }, async post(path, body) { const res = await fetch(`${API_URL}${path}`, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }, body: JSON.stringify(body) }); if (!res.ok) throw new Error((await res.json()).message || 'API error'); return res.json(); } }), [token]); } function App() { const [session, setSession] = useState(() => { const saved = localStorage.getItem('hr-session'); return saved ? JSON.parse(saved) : null; }); function saveSession(next) { setSession(next); if (next) localStorage.setItem('hr-session', JSON.stringify(next)); else localStorage.removeItem('hr-session'); } if (!session) return ; return saveSession(null)} />; } function Login({ onLogin }) { const [email, setEmail] = useState('admin@hr.test'); const [password, setPassword] = useState('Password123!'); const [loading, setLoading] = useState(false); const [error, setError] = useState(''); async function submit(event) { event.preventDefault(); setLoading(true); setError(''); try { const res = await fetch(`${API_URL}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); const data = await res.json(); if (!res.ok) throw new Error(data.message); onLogin(data); } catch (err) { setError(err.message || 'تعذر تسجيل الدخول'); } finally { setLoading(false); } } return (
HR SaaS

نظام موارد بشرية متكامل

اشتراكات، شركات متعددة، موظفون، حضور، رواتب، طلبات، مقابلات وتقارير في تجربة عربية احترافية.

تسجيل الدخول

setEmail(e.target.value)} dir="ltr" /> setPassword(e.target.value)} type="password" dir="ltr" /> {error &&

{error}

}
{demoAccounts.map(([account, label]) => ( ))}
); } function Shell({ session, onLogout }) { const [activeRole, setActiveRole] = useState(session.user.role); const roles = session.user.role === 'admin' ? ['admin', 'client', 'company', 'employee'] : [session.user.role]; const MetaIcon = roleMeta[activeRole].icon; return (
مرحباً، {session.user.name}

{roleMeta[activeRole].label}

متعدد المستأجرين
); } function Dashboard({ role, token }) { const api = useApi(token); const [data, setData] = useState(null); const [error, setError] = useState(''); useEffect(() => { setData(null); setError(''); api.get(`/dashboard/${role}`).then(setData).catch((err) => setError(err.message)); }, [api, role]); if (error) return
{error}
; if (!data) return
جاري تحميل البيانات...
; if (role === 'admin') return ; if (role === 'client') return ; if (role === 'company') return ; return api.get('/dashboard/employee').then(setData)} />; } function StatGrid({ items }) { return
{items.map((item) => )}
; } function Stat({ icon: Icon, label, value }) { return (
{label} {value ?? 0}
); } function AdminDashboard({ data }) { return ( <> [client.name, client.email, client.plan_name || '-', client.subscription_status || client.status])} /> [lead.company_name, lead.contact_name, lead.stage, lead.status])} /> ); } function ClientDashboard({ data }) { return ( <> [company.name, company.industry, company.users_count, company.employees_count, company.status])} /> {data.subscription && } ); } function CompanyDashboard({ data }) { return ( <> [employee.employee_code, employee.name, employee.job_title, employee.department, employee.status])} /> [request.employee_name, request.title, request.type, request.status])} /> ); } function EmployeeDashboard({ data, api, onRefresh }) { const [title, setTitle] = useState(''); const [type, setType] = useState('leave'); const [message, setMessage] = useState(''); async function submitRequest(event) { event.preventDefault(); setMessage(''); await api.post('/requests', { title, type }); setTitle(''); setMessage('تم إرسال الطلب بنجاح'); onRefresh(); } return ( <>

طلب جديد

setTitle(e.target.value)} placeholder="عنوان الطلب" required />
{message &&

{message}

}
[request.title, request.type, request.status, request.requested_at])} /> [item.work_date, item.check_in || '-', item.check_out || '-', item.status])} /> ); } function ToolSections({ sections }) { return (
{sections.map((section) => (

{section.title}

{section.items.map((item) => { const Icon = item.icon; return ; })}
))}
); } function DataPanel({ title, columns, rows }) { return (

{title}

{columns.map((col) => )} {rows.map((row, index) => {row.map((cell, cellIndex) => )})}
{col}
{cell}
); } function SubscriptionCard({ subscription }) { return (

تفاصيل الاشتراك

{subscription.plan_name}{subscription.status}

{Number(subscription.price).toLocaleString()} ر.س / حد الشركات {subscription.company_limit} / حد الموظفين {subscription.employee_limit}

); } const adminSections = [ { title: 'إدارة النظام', items: [{ label: 'العملاء', icon: Users }, { label: 'الشركات', icon: Building2 }, { label: 'المستخدمون', icon: User }, { label: 'الأدوار', icon: Shield }, { label: 'السجلات', icon: FileText }] }, { title: 'الاشتراكات والفواتير', items: [{ label: 'خطط الاشتراك', icon: WalletCards }, { label: 'الفواتير', icon: FileText }, { label: 'المدفوعات', icon: ClipboardCheck }, { label: 'التقارير المالية', icon: BarChart3 }] } ]; const clientSections = [ { title: 'إدارة الحساب والاشتراك', items: [{ label: 'بيانات شخصية', icon: User }, { label: 'إدارة الاشتراك', icon: WalletCards }, { label: 'الفواتير والمدفوعات', icon: FileText }, { label: 'تاريخ العمليات', icon: Clock3 }] }, { title: 'إدارة الشركات', items: [{ label: 'إضافة شركة', icon: Building2 }, { label: 'قائمة الشركات', icon: Users }, { label: 'تقارير الشركات', icon: BarChart3 }, { label: 'إعدادات الشركة', icon: Settings }] } ]; const companySections = [ { title: 'إدارة الشركة', items: [{ label: 'التسجيل', icon: ClipboardCheck }, { label: 'الإعدادات', icon: Settings }, { label: 'الإدارات', icon: Building2 }, { label: 'المستخدمون', icon: Users }] }, { title: 'إدارة الموظفين', items: [{ label: 'قائمة الموظفين', icon: Users }, { label: 'إضافة موظف', icon: User }, { label: 'العقود', icon: FileText }, { label: 'الرواتب والسلف', icon: WalletCards }, { label: 'الحضور', icon: Clock3 }] }, { title: 'العمليات', items: [{ label: 'الإجازات والطلبات', icon: CalendarCheck }, { label: 'الأصول', icon: PackageCheck }, { label: 'تقييم الموظفين', icon: BarChart3 }, { label: 'المقابلات', icon: BriefcaseBusiness }] } ]; const employeeSections = [ { title: 'الملف الشخصي', items: [{ label: 'بياناتي', icon: User }, { label: 'الوظيفة', icon: BriefcaseBusiness }, { label: 'المستندات', icon: FileText }, { label: 'كلمة المرور', icon: Settings }] }, { title: 'الخدمة الذاتية', items: [{ label: 'تسجيل حضور', icon: Clock3 }, { label: 'طلب إجازة', icon: CalendarCheck }, { label: 'طلب سلفة', icon: WalletCards }, { label: 'طلب خطاب', icon: FileText }, { label: 'الأصول المسندة', icon: PackageCheck }] } ]; createRoot(document.getElementById('root')).render();