|
|
@@ -0,0 +1,211 @@
|
|
|
+"use client"
|
|
|
+
|
|
|
+import { useState, useEffect } from "react"
|
|
|
+import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"
|
|
|
+import { Button } from "@/components/ui/button"
|
|
|
+import { Input } from "@/components/ui/input"
|
|
|
+import { Label } from "@/components/ui/label"
|
|
|
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
|
|
+import { Switch } from "@/components/ui/switch"
|
|
|
+import { genericToast } from "@/lib/notifications"
|
|
|
+
|
|
|
+interface User {
|
|
|
+ id: string
|
|
|
+ username: string
|
|
|
+ identificacion: string | null
|
|
|
+ name: string
|
|
|
+ lastname: string
|
|
|
+ email: string | null
|
|
|
+ role: string
|
|
|
+ isExternalAuth: boolean
|
|
|
+ isActive: boolean
|
|
|
+}
|
|
|
+
|
|
|
+interface EditUserDialogProps {
|
|
|
+ user: User
|
|
|
+ open: boolean
|
|
|
+ onOpenChange: (open: boolean) => void
|
|
|
+ onUserUpdated: () => void
|
|
|
+}
|
|
|
+
|
|
|
+export default function EditUserDialog({ user, open, onOpenChange, onUserUpdated }: EditUserDialogProps) {
|
|
|
+ const [loading, setLoading] = useState(false)
|
|
|
+ const [formData, setFormData] = useState({
|
|
|
+ name: user.name,
|
|
|
+ lastname: user.lastname,
|
|
|
+ email: user.email || "",
|
|
|
+ role: user.role,
|
|
|
+ isActive: user.isActive,
|
|
|
+ password: "",
|
|
|
+ confirmPassword: "",
|
|
|
+ })
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ setFormData({
|
|
|
+ name: user.name,
|
|
|
+ lastname: user.lastname,
|
|
|
+ email: user.email || "",
|
|
|
+ role: user.role,
|
|
|
+ isActive: user.isActive,
|
|
|
+ password: "",
|
|
|
+ confirmPassword: "",
|
|
|
+ })
|
|
|
+ }, [user])
|
|
|
+
|
|
|
+ const handleSubmit = async (e: React.FormEvent) => {
|
|
|
+ e.preventDefault()
|
|
|
+
|
|
|
+ if (formData.password && formData.password !== formData.confirmPassword) {
|
|
|
+ genericToast.error("Las contraseñas no coinciden")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (formData.password && formData.password.length < 6) {
|
|
|
+ genericToast.error("La contraseña debe tener al menos 6 caracteres")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ setLoading(true)
|
|
|
+ const response = await fetch(`/api/admin/users/${user.id}`, {
|
|
|
+ method: "PUT",
|
|
|
+ headers: { "Content-Type": "application/json" },
|
|
|
+ body: JSON.stringify({
|
|
|
+ name: formData.name,
|
|
|
+ lastname: formData.lastname,
|
|
|
+ email: formData.email || null,
|
|
|
+ role: formData.role,
|
|
|
+ isActive: formData.isActive,
|
|
|
+ password: formData.password || undefined,
|
|
|
+ }),
|
|
|
+ })
|
|
|
+
|
|
|
+ const data = await response.json()
|
|
|
+
|
|
|
+ if (response.ok) {
|
|
|
+ genericToast.success("Usuario actualizado")
|
|
|
+ onUserUpdated()
|
|
|
+ } else {
|
|
|
+ genericToast.error(data.error || "Error al actualizar usuario")
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ genericToast.error("Error al actualizar usuario")
|
|
|
+ } finally {
|
|
|
+ setLoading(false)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Dialog open={open} onOpenChange={onOpenChange}>
|
|
|
+ <DialogContent className="max-w-md">
|
|
|
+ <DialogHeader>
|
|
|
+ <DialogTitle>Editar Usuario</DialogTitle>
|
|
|
+ </DialogHeader>
|
|
|
+ <form onSubmit={handleSubmit} className="space-y-4">
|
|
|
+ <div className="space-y-2">
|
|
|
+ <Label>Username</Label>
|
|
|
+ <Input value={user.username} disabled className="bg-gray-50" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {user.identificacion && (
|
|
|
+ <div className="space-y-2">
|
|
|
+ <Label>Identificación</Label>
|
|
|
+ <Input value={user.identificacion} disabled className="bg-gray-50" />
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+
|
|
|
+ <div className="grid grid-cols-2 gap-4">
|
|
|
+ <div className="space-y-2">
|
|
|
+ <Label htmlFor="name">Nombre</Label>
|
|
|
+ <Input
|
|
|
+ id="name"
|
|
|
+ value={formData.name}
|
|
|
+ onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
|
+ disabled={user.isExternalAuth}
|
|
|
+ className={user.isExternalAuth ? "bg-gray-50" : ""}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div className="space-y-2">
|
|
|
+ <Label htmlFor="lastname">Apellido</Label>
|
|
|
+ <Input
|
|
|
+ id="lastname"
|
|
|
+ value={formData.lastname}
|
|
|
+ onChange={(e) => setFormData({ ...formData, lastname: e.target.value })}
|
|
|
+ disabled={user.isExternalAuth}
|
|
|
+ className={user.isExternalAuth ? "bg-gray-50" : ""}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="space-y-2">
|
|
|
+ <Label htmlFor="email">Email</Label>
|
|
|
+ <Input
|
|
|
+ id="email"
|
|
|
+ type="email"
|
|
|
+ value={formData.email}
|
|
|
+ onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="space-y-2">
|
|
|
+ <Label htmlFor="role">Rol</Label>
|
|
|
+ <Select value={formData.role} onValueChange={(value) => setFormData({ ...formData, role: value })}>
|
|
|
+ <SelectTrigger>
|
|
|
+ <SelectValue />
|
|
|
+ </SelectTrigger>
|
|
|
+ <SelectContent>
|
|
|
+ <SelectItem value="ADMIN">Admin</SelectItem>
|
|
|
+ <SelectItem value="DOCTOR">Doctor</SelectItem>
|
|
|
+ <SelectItem value="PATIENT">Paciente</SelectItem>
|
|
|
+ </SelectContent>
|
|
|
+ </Select>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {!user.isExternalAuth && (
|
|
|
+ <>
|
|
|
+ <div className="space-y-2">
|
|
|
+ <Label htmlFor="password">Nueva Contraseña</Label>
|
|
|
+ <Input
|
|
|
+ id="password"
|
|
|
+ type="password"
|
|
|
+ value={formData.password}
|
|
|
+ onChange={(e) => setFormData({ ...formData, password: e.target.value })}
|
|
|
+ placeholder="Dejar vacío para no cambiar"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="space-y-2">
|
|
|
+ <Label htmlFor="confirmPassword">Confirmar Contraseña</Label>
|
|
|
+ <Input
|
|
|
+ id="confirmPassword"
|
|
|
+ type="password"
|
|
|
+ value={formData.confirmPassword}
|
|
|
+ onChange={(e) => setFormData({ ...formData, confirmPassword: e.target.value })}
|
|
|
+ placeholder="Confirmar nueva contraseña"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+
|
|
|
+ <div className="flex items-center justify-between py-2">
|
|
|
+ <Label htmlFor="isActive">Usuario Activo</Label>
|
|
|
+ <Switch
|
|
|
+ id="isActive"
|
|
|
+ checked={formData.isActive}
|
|
|
+ onCheckedChange={(checked: boolean) => setFormData({ ...formData, isActive: checked })}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="flex gap-2 pt-4">
|
|
|
+ <Button type="button" variant="outline" onClick={() => onOpenChange(false)} className="flex-1">
|
|
|
+ Cancelar
|
|
|
+ </Button>
|
|
|
+ <Button type="submit" disabled={loading} className="flex-1">
|
|
|
+ {loading ? "Guardando..." : "Guardar Cambios"}
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </form>
|
|
|
+ </DialogContent>
|
|
|
+ </Dialog>
|
|
|
+ )
|
|
|
+}
|