Website : rimsha.abasa.com
backdoor
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
var
/
www
/
talha_silentcontent
/
src
/
components
/
Filename :
OrganizationMembers.tsx
back
Copy
// @ts-nocheck "use client"; import { useMutation, useQuery } from "@tanstack/react-query"; import axios from "axios"; import { useEffect, useState } from "react"; import { RiDeleteBin6Line } from "react-icons/ri"; import { FaUserPlus, FaUserMinus } from "react-icons/fa"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { useParams, useRouter } from "next/navigation"; import { Button } from "@/components/ui/button"; import { ReloadIcon } from "@radix-ui/react-icons"; import { toast } from "@/components/ui/use-toast"; import Link from "next/link"; import SamplePrompts from "@/lib/SamplePrompts.pdf"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "@/components/ui/alert-dialog"; export default function OrganizationMembers() { const { _id } = useParams(); const [isAdmin, setIsAdmin] = useState(false); const [organization, setOrganization] = useState<any>(""); const [admins, setAdmins] = useState<any>([]); const [regularMembers, setRegularMembers] = useState<any>([]); const [memberToAction, setMemberToAction] = useState(null); const [actionType, setActionType] = useState(""); const adminQuery = useQuery({ queryKey: ["organization", _id], queryFn: async () => { const response = await axios.get(`/api/organizations/${_id}`); return response.data.data; }, onSuccess: (data) => { setIsAdmin(data.isAdmin); setOrganization(data.organizationName); // Separate admins and regular members const allMembers = data.organizationMembers || []; const admins = data.admins || []; // Create a set of admin IDs for faster lookup const adminIds = new Set(admins.map((admin) => admin._id)); // Filter regular members (those not in admins) const regulars = allMembers.filter((member) => !adminIds.has(member._id)); setAdmins(admins); setRegularMembers(regulars); }, }); // Mutation for removing a member const { mutate: removeMember, isLoading: isRemoving } = useMutation({ mutationFn: async (memberId) => { const response = await axios.post( `/api/organizations/${_id}/remove-member`, { memberId, } ); return response.data; }, onSuccess: () => { toast({ description: "Member has been removed from the organization.", variant: "success", }); adminQuery.refetch(); }, onError: (error) => { toast({ title: "Error removing member", description: error.response?.data?.message || "Failed to remove member", variant: "destructive", }); }, }); // Mutation for promoting a member to admin const { mutate: promoteMember, isLoading: isPromoting } = useMutation({ mutationFn: async (memberId) => { const response = await axios.post( `/api/organizations/${_id}/promote-admin`, { memberId, } ); return response.data; }, onSuccess: () => { toast({ description: "Member has been promoted to admin.", variant: "success", }); adminQuery.refetch(); }, onError: (error) => { toast({ title: "Error promoting member", description: error.response?.data?.message || "Failed to promote member", variant: "destructive", }); }, }); // Mutation for demoting an admin to regular member const { mutate: demoteAdmin, isLoading: isDemoting } = useMutation({ mutationFn: async (adminId) => { const response = await axios.post( `/api/organizations/${_id}/demote-admin`, { adminId, } ); return response.data; }, onSuccess: () => { toast({ description: "Admin has been demoted to regular member.", variant: "success", }); adminQuery.refetch(); }, onError: (error) => { toast({ title: "Error demoting admin", description: error.response?.data?.message || "Failed to demote admin", variant: "destructive", }); }, }); const handleAction = (memberId, action) => { setMemberToAction(memberId); setActionType(action); }; const confirmAction = () => { if (!memberToAction) return; switch (actionType) { case "remove": removeMember(memberToAction); break; case "promote": promoteMember(memberToAction); break; case "demote": demoteAdmin(memberToAction); break; } setMemberToAction(null); setActionType(""); }; return ( <Card> <CardHeader> <CardTitle className="pb-0 text-4xl">{organization}</CardTitle> <CardDescription className="text-sm mt-2"> Manage organization members and permissions </CardDescription> </CardHeader> <CardContent> <div className="grid grid-cols-1 md:grid-cols-2 gap-6"> {/* Admins Column */} <div className="space-y-4"> <h3 className="text-xl font-semibold flex items-center"> Admins{" "} <span className="ml-2 text-sm font-normal bg-amber-100 text-amber-800 px-2 py-0.5 rounded-full"> {admins?.length || 0} </span> </h3> <div className="space-y-2 max-h-[300px] overflow-y-auto pr-2"> {admins?.length > 0 ? ( admins.map((admin, index) => ( <div key={index} className="flex items-center justify-between p-3 bg-slate-50 dark:bg-muted rounded-md" > <div> <p className="font-medium">{admin.username}</p> <p className="text-xs text-muted-foreground"> {admin.email} </p> </div> {isAdmin && admin.email !== adminQuery.data?.currentUserEmail && ( <div className="flex gap-2"> <AlertDialog> <AlertDialogTrigger asChild> <Button variant="ghost" size="sm" onClick={() => handleAction(admin._id, "demote")} className="text-yellow-600 hover:text-yellow-800 hover:bg-yellow-100" > <FaUserMinus className="mr-1" /> Demote </Button> </AlertDialogTrigger> <AlertDialogContent> <AlertDialogHeader> <AlertDialogTitle> Demote Admin to Member? </AlertDialogTitle> <AlertDialogDescription> This will remove admin privileges from{" "} {admin.username}. They will become a regular member. </AlertDialogDescription> </AlertDialogHeader> <AlertDialogFooter> <AlertDialogCancel>Cancel</AlertDialogCancel> <AlertDialogAction onClick={confirmAction}> {isDemoting ? ( <ReloadIcon className="mr-2 h-4 w-4 animate-spin" /> ) : null} Demote </AlertDialogAction> </AlertDialogFooter> </AlertDialogContent> </AlertDialog> <AlertDialog> <AlertDialogTrigger asChild> <Button variant="ghost" size="sm" onClick={() => handleAction(admin._id, "remove")} className="text-red-600 hover:text-red-800 hover:bg-red-100" > <RiDeleteBin6Line className="mr-1" /> Remove </Button> </AlertDialogTrigger> <AlertDialogContent> <AlertDialogHeader> <AlertDialogTitle> Remove Admin from Organization? </AlertDialogTitle> <AlertDialogDescription> This will completely remove {admin.username} from the organization. This action cannot be undone. </AlertDialogDescription> </AlertDialogHeader> <AlertDialogFooter> <AlertDialogCancel>Cancel</AlertDialogCancel> <AlertDialogAction onClick={confirmAction}> {isRemoving ? ( <ReloadIcon className="mr-2 h-4 w-4 animate-spin" /> ) : null} Remove </AlertDialogAction> </AlertDialogFooter> </AlertDialogContent> </AlertDialog> </div> )} </div> )) ) : ( <p className="text-sm text-muted-foreground italic"> No admins found </p> )} </div> </div> {/* Regular Members Column */} <div className="space-y-4"> <h3 className="text-xl font-semibold flex items-center"> Members{" "} <span className="ml-2 text-sm font-normal bg-primary text-blue-800 px-2 py-0.5 rounded-full"> {regularMembers?.length || 0} </span> </h3> <div className="space-y-2 max-h-[300px] overflow-y-auto pr-2"> {regularMembers?.length > 0 ? ( regularMembers.map((member, index) => ( <div key={index} className="flex items-center justify-between p-3 bg-slate-50 dark:bg-muted rounded-md" > <div> <p className="font-medium">{member.username}</p> <p className="text-xs text-muted-foreground"> {member.email} </p> </div> {isAdmin && ( <div className="flex gap-2"> <AlertDialog> <AlertDialogTrigger asChild> <Button variant="ghost" size="sm" onClick={() => handleAction(member._id, "promote")} className="text-green-600 hover:text-green-800 hover:bg-green-100" > <FaUserPlus className="mr-1" /> Promote </Button> </AlertDialogTrigger> <AlertDialogContent> <AlertDialogHeader> <AlertDialogTitle>Promote to Admin?</AlertDialogTitle> <AlertDialogDescription> This will give {member.username} admin privileges. They will be able to manage members and organization settings. </AlertDialogDescription> </AlertDialogHeader> <AlertDialogFooter> <AlertDialogCancel>Cancel</AlertDialogCancel> <AlertDialogAction onClick={confirmAction}> {isPromoting ? ( <ReloadIcon className="mr-2 h-4 w-4 animate-spin" /> ) : null} Promote </AlertDialogAction> </AlertDialogFooter> </AlertDialogContent> </AlertDialog> <AlertDialog> <AlertDialogTrigger asChild> <Button variant="ghost" size="sm" onClick={() => handleAction(member._id, "remove")} className="text-red-600 hover:text-red-800 hover:bg-red-100" > <RiDeleteBin6Line className="mr-1" /> Remove </Button> </AlertDialogTrigger> <AlertDialogContent> <AlertDialogHeader> <AlertDialogTitle> Remove Member from Organization? </AlertDialogTitle> <AlertDialogDescription> This will completely remove {member.username} from the organization. This action cannot be undone. </AlertDialogDescription> </AlertDialogHeader> <AlertDialogFooter> <AlertDialogCancel>Cancel</AlertDialogCancel> <AlertDialogAction onClick={confirmAction}> {isRemoving ? ( <ReloadIcon className="mr-2 h-4 w-4 animate-spin" /> ) : null} Remove </AlertDialogAction> </AlertDialogFooter> </AlertDialogContent> </AlertDialog> </div> )} </div> )) ) : ( <p className="text-sm text-muted-foreground italic"> No members found </p> )} </div> </div> </div> </CardContent> </Card> ); }