import type { LoaderFunctionArgs, ActionFunctionArgs, MetaFunction } from "@remix-run/node"; import { json, redirect } from "@remix-run/node"; import { useLoaderData, useSearchParams, useNavigation, useActionData } from "@remix-run/react"; import { useState, useEffect, useCallback } from "react"; import { protectUserManagementRoute } from "~/lib/auth-middleware.server"; import { getUsers, createUser, updateUser, deleteUser, toggleUserStatus } from "~/lib/user-management.server"; import { DashboardLayout } from "~/components/layout/DashboardLayout"; import { Text, Card, CardHeader, CardBody, Button, SearchInput, Modal } from "~/components/ui"; import { UserList } from "~/components/users/UserList"; import { UserForm } from "~/components/users/UserForm"; import type { UserWithoutPassword } from "~/types/database"; export const meta: MetaFunction = () => { return [ { title: "إدارة المستخدمين - نظام إدارة صيانة السيارات" }, { name: "description", content: "إدارة حسابات المستخدمين" }, ]; }; export async function loader({ request }: LoaderFunctionArgs) { const user = await protectUserManagementRoute(request); const url = new URL(request.url); const searchQuery = url.searchParams.get("search") || ""; const page = parseInt(url.searchParams.get("page") || "1"); const limit = 10; const { users, total, totalPages } = await getUsers( user.authLevel, searchQuery, page, limit ); return json({ user, users, currentPage: page, totalPages, total, searchQuery, }); } export async function action({ request }: ActionFunctionArgs) { const user = await protectUserManagementRoute(request); const formData = await request.formData(); const action = formData.get("_action") as string; try { switch (action) { case "create": { const userData = { name: formData.get("name") as string, username: formData.get("username") as string, email: formData.get("email") as string, password: formData.get("password") as string, authLevel: parseInt(formData.get("authLevel") as string), status: formData.get("status") as string, }; const result = await createUser(userData, user.authLevel); if (result.success) { return json({ success: true, message: "تم إنشاء المستخدم بنجاح" }); } else { return json({ success: false, error: result.error }, { status: 400 }); } } case "update": { const userId = parseInt(formData.get("userId") as string); const userData = { name: formData.get("name") as string, username: formData.get("username") as string, email: formData.get("email") as string, authLevel: parseInt(formData.get("authLevel") as string), status: formData.get("status") as string, }; const password = formData.get("password") as string; if (password) { (userData as any).password = password; } const result = await updateUser(userId, userData, user.authLevel); if (result.success) { return json({ success: true, message: "تم تحديث المستخدم بنجاح" }); } else { return json({ success: false, error: result.error }, { status: 400 }); } } case "delete": { const userId = parseInt(formData.get("userId") as string); const result = await deleteUser(userId, user.authLevel); if (result.success) { return json({ success: true, message: "تم حذف المستخدم بنجاح" }); } else { return json({ success: false, error: result.error }, { status: 400 }); } } case "toggle-status": { const userId = parseInt(formData.get("userId") as string); const result = await toggleUserStatus(userId, user.authLevel); if (result.success) { return json({ success: true, message: "تم تغيير حالة المستخدم بنجاح" }); } else { return json({ success: false, error: result.error }, { status: 400 }); } } default: return json({ success: false, error: "إجراء غير صحيح" }, { status: 400 }); } } catch (error) { console.error("User management action error:", error); return json({ success: false, error: "حدث خطأ في الخادم" }, { status: 500 }); } } export default function Users() { const { user, users, currentPage, totalPages, total, searchQuery } = useLoaderData(); const [searchParams, setSearchParams] = useSearchParams(); const navigation = useNavigation(); const actionData = useActionData(); const [showCreateModal, setShowCreateModal] = useState(false); const [editingUser, setEditingUser] = useState(null); const [notification, setNotification] = useState<{ type: 'success' | 'error'; message: string; } | null>(null); const isLoading = navigation.state === "loading"; const isSubmitting = navigation.state === "submitting"; // Handle action results useEffect(() => { if (actionData) { if (actionData.success) { setNotification({ type: 'success', message: actionData.message || 'تم تنفيذ العملية بنجاح', }); setShowCreateModal(false); setEditingUser(null); } else { setNotification({ type: 'error', message: actionData.error || 'حدث خطأ أثناء تنفيذ العملية', }); } } }, [actionData]); // Clear notification after 5 seconds useEffect(() => { if (notification) { const timer = setTimeout(() => { setNotification(null); }, 5000); return () => clearTimeout(timer); } }, [notification]); const handleSearch = useCallback((query: string) => { const newSearchParams = new URLSearchParams(searchParams); if (query) { newSearchParams.set("search", query); } else { newSearchParams.delete("search"); } newSearchParams.delete("page"); // Reset to first page setSearchParams(newSearchParams); }, [searchParams, setSearchParams]); const handlePageChange = useCallback((page: number) => { const newSearchParams = new URLSearchParams(searchParams); newSearchParams.set("page", page.toString()); setSearchParams(newSearchParams); }, [searchParams, setSearchParams]); const handleEdit = useCallback((userToEdit: UserWithoutPassword) => { setEditingUser(userToEdit); }, []); const handleDelete = useCallback((userId: number) => { // Create a form and submit it const form = document.createElement("form"); form.method = "POST"; form.style.display = "none"; const actionInput = document.createElement("input"); actionInput.type = "hidden"; actionInput.name = "_action"; actionInput.value = "delete"; form.appendChild(actionInput); const userIdInput = document.createElement("input"); userIdInput.type = "hidden"; userIdInput.name = "userId"; userIdInput.value = userId.toString(); form.appendChild(userIdInput); document.body.appendChild(form); form.submit(); document.body.removeChild(form); }, []); const handleToggleStatus = useCallback((userId: number) => { // Create a form and submit it const form = document.createElement("form"); form.method = "POST"; form.style.display = "none"; const actionInput = document.createElement("input"); actionInput.type = "hidden"; actionInput.name = "_action"; actionInput.value = "toggle-status"; form.appendChild(actionInput); const userIdInput = document.createElement("input"); userIdInput.type = "hidden"; userIdInput.name = "userId"; userIdInput.value = userId.toString(); form.appendChild(userIdInput); document.body.appendChild(form); form.submit(); document.body.removeChild(form); }, []); const handleFormSubmit = useCallback((formData: FormData) => { // Create a form and submit it const form = document.createElement("form"); form.method = "POST"; form.style.display = "none"; for (const [key, value] of formData.entries()) { const input = document.createElement("input"); input.type = "hidden"; input.name = key; input.value = value as string; form.appendChild(input); } document.body.appendChild(form); form.submit(); document.body.removeChild(form); }, []); return (
{/* Header */}
إدارة المستخدمين إدارة حسابات المستخدمين وصلاحيات الوصول ({total} مستخدم)
{/* Notification */} {notification && (
{notification.type === 'success' ? ( ) : ( )}
{notification.message}
)} {/* Search and Filters */}
{/* Users List */} قائمة المستخدمين {/* Create User Modal */} setShowCreateModal(false)} title="إضافة مستخدم جديد" size="lg" > setShowCreateModal(false)} loading={isSubmitting} currentUserAuthLevel={user.authLevel} /> {/* Edit User Modal */} setEditingUser(null)} title="تعديل المستخدم" size="lg" > {editingUser && ( setEditingUser(null)} loading={isSubmitting} currentUserAuthLevel={user.authLevel} /> )}
); }