feat(admin-users): Add user edit dialog with form validation and update functionality
This commit is contained in:
parent
7b0b5099fe
commit
64ba7cfc31
|
|
@ -4,20 +4,76 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Badge } from "@/components/ui/badge"
|
import { Badge } from "@/components/ui/badge"
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||||||
import { ArrowLeft, Edit, Key } from "lucide-react"
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@/components/ui/dialog"
|
||||||
|
import { Input } from "@/components/ui/input"
|
||||||
|
import { Label } from "@/components/ui/label"
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select"
|
||||||
|
import { ArrowLeft, Edit, Key, Loader2 } from "lucide-react"
|
||||||
import { userService } from "@/services"
|
import { userService } from "@/services"
|
||||||
import { format } from "date-fns"
|
import { format } from "date-fns"
|
||||||
|
import { useState } from "react"
|
||||||
|
import { toast } from "sonner"
|
||||||
|
|
||||||
export default function UserDetailsPage() {
|
export default function UserDetailsPage() {
|
||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false)
|
||||||
|
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||||
|
const [editForm, setEditForm] = useState({
|
||||||
|
firstName: '',
|
||||||
|
lastName: '',
|
||||||
|
email: '',
|
||||||
|
role: '',
|
||||||
|
isActive: true,
|
||||||
|
})
|
||||||
|
|
||||||
const { data: user, isLoading } = useQuery({
|
const { data: user, isLoading, refetch } = useQuery({
|
||||||
queryKey: ['admin', 'users', id],
|
queryKey: ['admin', 'users', id],
|
||||||
queryFn: () => userService.getUser(id!),
|
queryFn: () => userService.getUser(id!),
|
||||||
enabled: !!id,
|
enabled: !!id,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const handleEditClick = () => {
|
||||||
|
if (user) {
|
||||||
|
setEditForm({
|
||||||
|
firstName: user.firstName || '',
|
||||||
|
lastName: user.lastName || '',
|
||||||
|
email: user.email,
|
||||||
|
role: user.role,
|
||||||
|
isActive: user.isActive,
|
||||||
|
})
|
||||||
|
setIsEditDialogOpen(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSaveEdit = async () => {
|
||||||
|
try {
|
||||||
|
setIsSubmitting(true)
|
||||||
|
await userService.updateUser(id!, editForm)
|
||||||
|
toast.success("User updated successfully")
|
||||||
|
setIsEditDialogOpen(false)
|
||||||
|
refetch()
|
||||||
|
} catch (error) {
|
||||||
|
toast.error("Failed to update user")
|
||||||
|
console.error('Update error:', error)
|
||||||
|
} finally {
|
||||||
|
setIsSubmitting(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <div className="text-center py-8">Loading user details...</div>
|
return <div className="text-center py-8">Loading user details...</div>
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +106,7 @@ export default function UserDetailsPage() {
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<CardTitle>User Information</CardTitle>
|
<CardTitle>User Information</CardTitle>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Button variant="outline" size="sm">
|
<Button variant="outline" size="sm" onClick={handleEditClick}>
|
||||||
<Edit className="w-4 h-4 mr-2" />
|
<Edit className="w-4 h-4 mr-2" />
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -133,6 +189,82 @@ export default function UserDetailsPage() {
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
<Dialog open={isEditDialogOpen} onOpenChange={setIsEditDialogOpen}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Edit User</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Update user information and settings
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="space-y-4 py-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="firstName">First Name</Label>
|
||||||
|
<Input
|
||||||
|
id="firstName"
|
||||||
|
value={editForm.firstName}
|
||||||
|
onChange={(e) => setEditForm({ ...editForm, firstName: e.target.value })}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="lastName">Last Name</Label>
|
||||||
|
<Input
|
||||||
|
id="lastName"
|
||||||
|
value={editForm.lastName}
|
||||||
|
onChange={(e) => setEditForm({ ...editForm, lastName: e.target.value })}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="email">Email</Label>
|
||||||
|
<Input
|
||||||
|
id="email"
|
||||||
|
type="email"
|
||||||
|
value={editForm.email}
|
||||||
|
onChange={(e) => setEditForm({ ...editForm, email: e.target.value })}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="role">Role</Label>
|
||||||
|
<Select value={editForm.role} onValueChange={(value) => setEditForm({ ...editForm, role: value })}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select role" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="ADMIN">Admin</SelectItem>
|
||||||
|
<SelectItem value="EMPLOYEE">Employee</SelectItem>
|
||||||
|
<SelectItem value="CLIENT">Client</SelectItem>
|
||||||
|
<SelectItem value="MEMBER">Member</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="status">Status</Label>
|
||||||
|
<Select
|
||||||
|
value={editForm.isActive ? 'active' : 'inactive'}
|
||||||
|
onValueChange={(value) => setEditForm({ ...editForm, isActive: value === 'active' })}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select status" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="active">Active</SelectItem>
|
||||||
|
<SelectItem value="inactive">Inactive</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="outline" onClick={() => setIsEditDialogOpen(false)} disabled={isSubmitting}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleSaveEdit} disabled={isSubmitting}>
|
||||||
|
{isSubmitting && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
|
||||||
|
Save Changes
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user