MIF_E31221222/sigap-website/components/admin/users/sheet.tsx

316 lines
11 KiB
TypeScript

"use client"
import { useState } from "react"
import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { UserForm } from "./user-form"
import { Button } from "@/components/ui/button"
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
import { Mail, ShieldAlert, Trash2, Ban } from "lucide-react"
import { User } from "./column"
import { toast } from "@/hooks/use-toast"
interface UserDetailSheetProps {
user: User
open: boolean
onOpenChange: (open: boolean) => void
}
export function UserDetailSheet({ user, open, onOpenChange }: UserDetailSheetProps) {
const [isDeleting, setIsDeleting] = useState(false)
const [isResetting, setIsResetting] = useState(false)
const [isSendingMagic, setIsSendingMagic] = useState(false)
const [isRemovingMfa, setIsRemovingMfa] = useState(false)
const [isBanning, setIsBanning] = useState(false)
const handleResetPassword = async () => {
try {
setIsResetting(true)
toast({
title: "Success",
description: "Password reset email sent",
})
} catch (error) {
toast({
title: "Error",
description: "Failed to send reset password email",
variant: "destructive",
})
console.error(error)
} finally {
setIsResetting(false)
}
}
const handleSendMagicLink = async () => {
try {
setIsSendingMagic(true)
toast({
title: "Success",
description: "Magic link sent",
})
} catch (error) {
toast({
title: "Error",
description: "Failed to send magic link",
variant: "destructive",
})
console.error(error)
} finally {
setIsSendingMagic(false)
}
}
const handleRemoveMfa = async () => {
try {
setIsRemovingMfa(true)
await removeMfaFactors(user.id)
toast({
title: "Success",
description: "MFA factors removed",
})
} catch (error) {
toast({
title: "Error",
description: "Failed to remove MFA factors",
variant: "destructive",
})
console.error(error)
} finally {
setIsRemovingMfa(false)
}
}
const handleBanUser = async () => {
try {
setIsBanning(true)
await banUser(user.id)
toast({
title: "Success",
description: "User banned successfully",
})
} catch (error) {
toast({
title: "Error",
description: "Failed to ban user",
variant: "destructive",
})
console.error(error)
} finally {
setIsBanning(false)
}
}
const handleDeleteUser = async () => {
try {
setIsDeleting(true)
await deleteUser(user.id)
toast({
title: "Success",
description: "User deleted successfully",
})
onOpenChange(false)
} catch (error) {
toast({
title: "Error",
description: "Failed to delete user",
variant: "destructive",
})
console.error(error)
} finally {
setIsDeleting(false)
}
}
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent className="sm:max-w-xl overflow-y-auto bg-[#121212] text-white border-l border-[#2a2a2a]">
<SheetHeader>
<SheetTitle className="text-white">User Details</SheetTitle>
</SheetHeader>
<div className="py-6">
<div className="flex items-center justify-between mb-6">
<div>
<h2 className="text-xl font-semibold">{user.email}</h2>
<p className="text-sm text-gray-400">ID: {user.id}</p>
</div>
</div>
<Tabs defaultValue="details" className="w-full">
<TabsList className="grid w-full grid-cols-3 bg-[#1c1c1c]">
<TabsTrigger value="details" className="data-[state=active]:bg-[#2a2a2a]">
Details
</TabsTrigger>
<TabsTrigger value="profile" className="data-[state=active]:bg-[#2a2a2a]">
Profile
</TabsTrigger>
<TabsTrigger value="security" className="data-[state=active]:bg-[#2a2a2a]">
Security
</TabsTrigger>
</TabsList>
<TabsContent value="details" className="mt-4">
<UserForm user={user} />
</TabsContent>
<TabsContent value="profile" className="mt-4">
<div className="space-y-4">
<h3 className="text-lg font-medium">Profile Information</h3>
<p className="text-sm text-gray-400">Profile data will be loaded here.</p>
</div>
</TabsContent>
<TabsContent value="security" className="mt-4">
<div className="space-y-6">
<div className="bg-[#1c1c1c] p-4 rounded-md border border-[#2a2a2a]">
<div className="flex items-center justify-between">
<div>
<h3 className="font-medium">Reset password</h3>
<p className="text-sm text-gray-400">Send a password recovery email to the user</p>
</div>
<Button
variant="outline"
size="sm"
onClick={handleResetPassword}
disabled={isResetting}
className="bg-[#121212] border-[#2a2a2a] hover:bg-[#2a2a2a]"
>
<Mail className="mr-2 h-4 w-4" />
Send password recovery
</Button>
</div>
</div>
<div className="bg-[#1c1c1c] p-4 rounded-md border border-[#2a2a2a]">
<div className="flex items-center justify-between">
<div>
<h3 className="font-medium">Send magic link</h3>
<p className="text-sm text-gray-400">Passwordless login via email for the user</p>
</div>
<Button
variant="outline"
size="sm"
onClick={handleSendMagicLink}
disabled={isSendingMagic}
className="bg-[#121212] border-[#2a2a2a] hover:bg-[#2a2a2a]"
>
<Mail className="mr-2 h-4 w-4" />
Send magic link
</Button>
</div>
</div>
<div>
<h3 className="text-lg font-medium mb-2">Danger zone</h3>
<p className="text-sm text-gray-400 mb-4">
Be wary of the following features as they cannot be undone.
</p>
<div className="space-y-4 border border-red-900/50 rounded-md overflow-hidden">
<div className="p-4 border-b border-red-900/50">
<div className="flex items-center justify-between">
<div>
<h4 className="font-medium">Remove MFA factors</h4>
<p className="text-sm text-gray-400">This will log the user out of all active sessions</p>
</div>
<Button
variant="outline"
size="sm"
onClick={handleRemoveMfa}
disabled={isRemovingMfa}
className="bg-[#121212] border-[#2a2a2a] hover:bg-[#2a2a2a]"
>
<ShieldAlert className="mr-2 h-4 w-4" />
Remove MFA factors
</Button>
</div>
</div>
<div className="p-4 border-b border-red-900/50">
<div className="flex items-center justify-between">
<div>
<h4 className="font-medium">Ban user</h4>
<p className="text-sm text-gray-400">Revoke access to the project for a set duration</p>
</div>
<Button
variant="outline"
size="sm"
onClick={handleBanUser}
disabled={isBanning}
className="bg-[#121212] border-[#2a2a2a] hover:bg-[#2a2a2a]"
>
<Ban className="mr-2 h-4 w-4" />
Ban user
</Button>
</div>
</div>
<div className="p-4">
<div className="flex items-center justify-between">
<div>
<h4 className="font-medium">Delete user</h4>
<p className="text-sm text-gray-400">User will no longer have access to the project</p>
</div>
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
variant="destructive"
size="sm"
className="bg-red-900 hover:bg-red-800 text-white border-0"
>
<Trash2 className="mr-2 h-4 w-4" />
Delete user
</Button>
</AlertDialogTrigger>
<AlertDialogContent className="bg-[#121212] text-white border-[#2a2a2a]">
<AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
<AlertDialogDescription className="text-gray-400">
This action cannot be undone. This will permanently delete the user account and remove
their data from our servers.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel className="bg-[#1c1c1c] text-white border-[#2a2a2a] hover:bg-[#2a2a2a]">
Cancel
</AlertDialogCancel>
<AlertDialogAction
onClick={handleDeleteUser}
disabled={isDeleting}
className="bg-red-900 hover:bg-red-800 text-white border-0"
>
Delete
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>
</div>
</div>
</div>
</div>
</TabsContent>
</Tabs>
</div>
</SheetContent>
</Sheet>
)
}