"use client"; import React, { useState, useMemo } from "react"; import useSWR from "swr"; import axios from "@/lib/axios"; import { useTranslations } from "next-intl"; import PageBreadcrumb from "@/components/common/PageBreadCrumb"; import ComponentCard from "@/components/common/ComponentCard"; import { PlusIcon } from "@/icons"; import { useAuth } from "@/hooks/useAuth"; import { useToast } from "@/context/ToastContext"; import Button from "@/components/ui/button/Button"; import ConfirmationModal from "@/components/common/ConfirmationModal"; import UserModal from "@/components/users/UserModal"; import { Edit, Trash, MoreVertical, Shield, User as UserIcon, Mail, Calendar, Search } from "lucide-react"; import Image from "next/image"; import { getUserAvatar } from "@/lib/utils"; import PageLoader from "@/components/ui/PageLoader"; const fetcher = (url: string) => axios.get(url).then((res) => res.data); export default function UsersManagementClient() { const t = useTranslations("Users"); const { user: currentUser } = useAuth(); const { addToast } = useToast(); const [searchTerm, setSearchTerm] = useState(""); const [roleFilter, setRoleFilter] = useState("all"); const [isDeleting, setIsDeleting] = useState(false); const [isSaving, setIsSaving] = useState(false); const [confirmDeleteId, setConfirmDeleteId] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); const [editingUser, setEditingUser] = useState(null); const { data, error, mutate, isLoading } = useSWR("/api/admin/users", fetcher); const { isAdmin, isOwner, isAdminOrOwner } = useAuth(); const hasAdminAccess = isAdminOrOwner; const handleDelete = async (id: string) => { setIsDeleting(true); try { await axios.delete(`/api/admin/users/${id}`); mutate(); addToast(t("toast_deleted"), "success"); setConfirmDeleteId(null); } catch (err: any) { console.error(err); addToast(err.response?.data?.message || t("toast_delete_failed"), "error"); } finally { setIsDeleting(false); } }; const handleSaveUser = async (formData: any) => { setIsSaving(true); try { if (editingUser) { await axios.patch(`/api/admin/users/${editingUser.id}`, formData); addToast(t("toast_updated"), "success"); } else { await axios.post("/api/admin/users", formData); addToast(t("toast_created"), "success"); } mutate(); setIsModalOpen(false); setEditingUser(null); } catch (err: any) { console.error(err); addToast(err.response?.data?.message || t("toast_save_failed"), "error"); } finally { setIsSaving(false); } }; const handleEditClick = (u: any) => { setEditingUser(u); setIsModalOpen(true); }; const handleAddClick = () => { setEditingUser(null); setIsModalOpen(true); }; const users = data?.data || []; const filteredUsers = useMemo(() => { return users.filter((u: any) => { const fullName = `${u.first_name || ''} ${u.last_name || ''}`.toLowerCase(); const matchesSearch = fullName.includes(searchTerm.toLowerCase()) || u.email.toLowerCase().includes(searchTerm.toLowerCase()); const matchesRole = roleFilter === "all" || u.role === roleFilter; return matchesSearch && matchesRole; }); }, [users, searchTerm, roleFilter]); if (error) return
{t("load_failed")}
; return (
setSearchTerm(e.target.value)} className="pl-10 pr-4 py-2 text-sm border border-gray-200 dark:border-gray-800 rounded-lg bg-transparent focus:ring-2 focus:ring-brand-500/10 outline-none w-full sm:w-64 dark:text-white/90 dark:placeholder:text-white/30" />
{hasAdminAccess && ( )}
} >
{filteredUsers.length > 0 ? ( filteredUsers.map((u: any) => ( )) ) : !isLoading ? ( ) : null}
{t("user_th")} {t("role_th")} {t("joined_date_th")} {t("actions_th")}
{`${u.first_name}
{u.first_name} {u.last_name} {u.email}
{u.role === 'admin' || u.role === 'owner' ? : } {u.role === 'customer' ? t("customers").toLowerCase() : u.role} {new Date(u.created_at).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric", })}
{(isOwner || (isAdmin && u.role === 'customer')) && ( <> )}
{t("no_users_found")}
{(isLoading || isDeleting) && (
)}
setConfirmDeleteId(null)} onConfirm={() => confirmDeleteId && handleDelete(confirmDeleteId)} title={t("delete_title")} message={t("delete_message")} isLoading={isDeleting} confirmLabel={t("delete_confirm")} requiredInput="DELETE" /> setIsModalOpen(false)} onSave={handleSaveUser} user={editingUser} isLoading={isSaving} currentUser={currentUser} /> ); }