import { useState } from "react"; import { useListUsers, useUpdateUser, useGetDashboardAnalytics, useListTaskTypes, useToggleTaskType, getListTaskTypesQueryKey, getListUsersQueryKey, } from "@workspace/api-client-react"; import { useQueryClient } from "@tanstack/react-query"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { Skeleton } from "@/components/ui/skeleton"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { TEAMS, getTeamColor } from "../lib/constants"; import { Users, BarChart3, Settings, ShieldCheck, ShieldAlert, Eye, EyeOff } from "lucide-react"; import { useToast } from "@/hooks/use-toast"; import { useAuth } from "../context/auth-context"; type TabId = "users" | "analytics" | "taskTypes"; const TABS: { id: TabId; label: string; icon: typeof Users }[] = [ { id: "users", label: "المستخدمون", icon: Users }, { id: "analytics", label: "التحليلات", icon: BarChart3 }, { id: "taskTypes", label: "أنواع المهام", icon: Settings }, ]; // Updated roles with new structure const CANONICAL_ROLES = [ { value: "admin", label: "مدير النظام", cls: "bg-red-100 text-red-700 border-red-200" }, { value: "head_of_team", label: "رئيس الفرق", cls: "bg-orange-100 text-orange-700 border-orange-200" }, { value: "team_lead", label: "قائد فريق", cls: "bg-blue-100 text-blue-700 border-blue-200" }, { value: "member", label: "عضو", cls: "bg-slate-100 text-slate-600 border-slate-200" }, ]; const ROLE_MAP: Record = { admin: { label: "مدير النظام", cls: "bg-red-100 text-red-700 border-red-200" }, head_of_team: { label: "رئيس الفرق", cls: "bg-orange-100 text-orange-700 border-orange-200" }, team_lead: { label: "قائد فريق", cls: "bg-blue-100 text-blue-700 border-blue-200" }, member: { label: "عضو", cls: "bg-slate-100 text-slate-600 border-slate-200" }, // Legacy support for display dept_manager: { label: "قائد فريق", cls: "bg-blue-100 text-blue-700 border-blue-200" }, team_leader: { label: "قائد فريق", cls: "bg-blue-100 text-blue-700 border-blue-200" }, }; function RoleBadge({ role }: { role: string }) { const r = ROLE_MAP[role] ?? { label: role, cls: "bg-slate-100 text-slate-500 border-slate-200" }; return ( {r.label} ); } export default function Admin() { const [tab, setTab] = useState("users"); const queryClient = useQueryClient(); const { toast } = useToast(); const { activeUser, token } = useAuth(); const { data: users, isLoading: usersLoading } = useListUsers(); const { data: analytics, isLoading: analyticsLoading } = useGetDashboardAnalytics(); const { data: taskTypes, isLoading: taskTypesLoading } = useListTaskTypes({}); const toggleTaskType = useToggleTaskType(); const updateUser = useUpdateUser(); const handleToggleTaskType = (id: number) => { toggleTaskType.mutate({ id }, { onSuccess: () => { queryClient.invalidateQueries({ queryKey: getListTaskTypesQueryKey() }); toast({ title: "تم تحديث حالة نوع المهمة" }); }, onError: () => toast({ title: "فشل التحديث", variant: "destructive" }), }); }; const [editUser, setEditUser] = useState<{ id: number; name: string; team: string; role: string } | null>(null); const [editTeam, setEditTeam] = useState(""); const [editRole, setEditRole] = useState(""); // Add User Form States const [isAddUserOpen, setIsAddUserOpen] = useState(false); const [newUserName, setNewUserName] = useState(""); const [newUserEmail, setNewUserEmail] = useState(""); const [newUserPassword, setNewUserPassword] = useState(""); const [newUserTeam, setNewUserTeam] = useState(""); const [newUserRole, setNewUserRole] = useState("member"); const [showPassword, setShowPassword] = useState(false); const [isSubmittingUser, setIsSubmittingUser] = useState(false); const openEditUser = (u: { id: number; name: string; team: string; role: string }) => { setEditUser(u); setEditTeam(u.team); setEditRole(u.role); }; const handleSaveUser = () => { if (!editUser) return; updateUser.mutate( { id: editUser.id, data: { team: editTeam, role: editRole } }, { onSuccess: () => { queryClient.invalidateQueries({ queryKey: getListUsersQueryKey() }); toast({ title: "تم تحديث بيانات المستخدم" }); setEditUser(null); }, onError: () => toast({ title: "فشل التحديث", variant: "destructive" }), } ); }; const handleRoleChange = (userId: number, newRole: string) => { updateUser.mutate( { id: userId, data: { role: newRole } }, { onSuccess: () => { queryClient.invalidateQueries({ queryKey: getListUsersQueryKey() }); toast({ title: "تم تحديث الدور" }); }, onError: () => toast({ title: "فشل التحديث", variant: "destructive" }), } ); }; // Grant/revoke admin — only admin can do this const handleGrantAdmin = (userId: number, currentRole: string) => { const newRole = currentRole === "admin" ? "team_lead" : "admin"; const confirmMsg = currentRole === "admin" ? "سيتم إلغاء صلاحيات الإدارة من هذا المستخدم. هل أنت متأكد؟" : "سيتم منح صلاحيات الإدارة الكاملة لهذا المستخدم. هل أنت متأكد؟"; if (!window.confirm(confirmMsg)) return; updateUser.mutate( { id: userId, data: { role: newRole } }, { onSuccess: () => { queryClient.invalidateQueries({ queryKey: getListUsersQueryKey() }); toast({ title: currentRole === "admin" ? "تم إلغاء صلاحيات الإدارة" : "تم منح صلاحيات الإدارة" }); }, onError: () => toast({ title: "فشل التحديث", variant: "destructive" }), } ); }; const handleCreateUser = async (e: React.FormEvent) => { e.preventDefault(); if (!newUserName.trim() || !newUserEmail.trim() || newUserPassword.length < 8 || !newUserTeam) { return; } setIsSubmittingUser(true); try { const res = await fetch("/api/auth/register", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify({ name: newUserName, email: newUserEmail, password: newUserPassword, team: newUserTeam, role: newUserRole, }), }); const data = await res.json(); if (!res.ok) { throw new Error(data.error || "حدث خطأ أثناء إضافة الموظف"); } queryClient.invalidateQueries({ queryKey: getListUsersQueryKey() }); toast({ title: "تم إضافة الموظف بنجاح" }); setIsAddUserOpen(false); // Reset form setNewUserName(""); setNewUserEmail(""); setNewUserPassword(""); setNewUserTeam(""); setNewUserRole("member"); setShowPassword(false); } catch (err: any) { toast({ title: err.message || "فشل إضافة الموظف", variant: "destructive", }); } finally { setIsSubmittingUser(false); } }; const isFormInvalid = !newUserName.trim() || !newUserEmail.trim() || newUserPassword.length < 8 || !newUserTeam; return (

لوحة الإدارة

إدارة المستخدمين والأدوار والتحليلات

{TABS.map(t => { const Icon = t.icon; return ( ); })}
{tab === "users" && (
جميع المستخدمين ({users?.length ?? 0})
صلاحية الإدارة — فقط لك كمدير النظام
{usersLoading ? (
{[1,2,3].map(i => )}
) : (
{users?.map(user => (
{user.name.substring(0, 2)}

{user.name}

{user.email}

{user.team}
{/* Grant/revoke admin — only available to the current admin, and not on themselves */} {activeUser?.role === "admin" && user.id !== activeUser?.id && ( )}
))}
)}
)} {tab === "analytics" && (
{analyticsLoading ? (
) : analytics ? ( <> المهام هذا الأسبوع مقارنة بالأسبوع الماضي
{analytics.weekly.map(d => { const maxVal = Math.max(...analytics.weekly.flatMap(w => [w.thisWeek, w.lastWeek]), 1); const thisH = Math.round((d.thisWeek / maxVal) * 100); const lastH = Math.round((d.lastWeek / maxVal) * 100); return (
{d.day}
); })}
الأسبوع الماضي
هذا الأسبوع
المهام حسب الفريق
{analytics.byTeam.filter(t => t.totalTasks > 0).map(t => { const max = Math.max(...analytics.byTeam.map(x => x.totalTasks), 1); const pct = Math.round((t.totalTasks / max) * 100); return (
{t.team} {t.totalTasks}
); })}
أكثر 5 عملاء نشاطاً {analytics.topClients.length === 0 ? (

لا توجد مهام مرتبطة بعملاء بعد

) : (
{analytics.topClients.map((c, i) => (
{i + 1}

{c?.name}

{c?.completedTasks} / {c?.totalTasks} مكتملة

))}
)}
) : null}
)} {tab === "taskTypes" && (
أنواع المهام ({taskTypes?.length ?? 0}) يمكن تفعيل/إيقاف كل نوع
{taskTypesLoading ? (
{[1,2,3,4].map(i => )}
) : taskTypes && taskTypes.length > 0 ? (
{taskTypes.map(tt => (

{tt.name}

{tt.fromDeptSlug} {tt.toDeptSlug}
handleToggleTaskType(tt.id)} > {tt.isActive ? "نشط" : "متوقف"}
))}
) : (

لا توجد أنواع مهام محددة

)}
)} {/* Add new user dialog */} إضافة موظف جديد
setNewUserName(e.target.value)} placeholder="الاسم الكامل" required />
setNewUserEmail(e.target.value)} placeholder="example@domain.com" required />
setNewUserPassword(e.target.value)} placeholder="كلمة المرور (8 أحرف على الأقل)" required />
{/* Edit user dialog */} { if (!o) setEditUser(null); }}> تعديل بيانات: {editUser?.name}
); }