mirror of
https://github.com/khairul169/garage-webui.git
synced 2025-10-14 23:09:32 +07:00
188 lines
5.4 KiB
TypeScript
188 lines
5.4 KiB
TypeScript
import { useEffect } from "react";
|
|
import { useForm } from "react-hook-form";
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
import { z } from "zod";
|
|
import { Modal, Button, Select } from "react-daisyui";
|
|
import { InputField } from "@/components/ui/input";
|
|
import { useUpdateUser, useTenants } from "@/hooks/useAdmin";
|
|
import { usePermissions } from "@/hooks/useAuth";
|
|
import { User } from "@/types/admin";
|
|
import { Toggle } from "@/components/ui/toggle";
|
|
|
|
const updateUserSchema = z.object({
|
|
username: z.string().min(3, "El nombre de usuario debe tener al menos 3 caracteres").optional(),
|
|
email: z.string().email("Email inválido").optional(),
|
|
password: z.string().min(6, "La contraseña debe tener al menos 6 caracteres").optional(),
|
|
role: z.enum(["admin", "tenant_admin", "user", "readonly"] as const).optional(),
|
|
tenant_id: z.string().optional(),
|
|
enabled: z.boolean().optional(),
|
|
});
|
|
|
|
type UpdateUserForm = z.infer<typeof updateUserSchema>;
|
|
|
|
interface EditUserDialogProps {
|
|
open: boolean;
|
|
user: User | null;
|
|
onClose: () => void;
|
|
}
|
|
|
|
export default function EditUserDialog({ open, user, onClose }: EditUserDialogProps) {
|
|
const updateUser = useUpdateUser();
|
|
const { data: tenants } = useTenants();
|
|
const { isAdmin } = usePermissions();
|
|
|
|
const form = useForm<UpdateUserForm>({
|
|
resolver: zodResolver(updateUserSchema),
|
|
defaultValues: {
|
|
username: "",
|
|
email: "",
|
|
password: "",
|
|
role: "user",
|
|
tenant_id: "",
|
|
enabled: true,
|
|
},
|
|
});
|
|
|
|
const selectedRole = form.watch("role");
|
|
|
|
useEffect(() => {
|
|
if (user && open) {
|
|
form.reset({
|
|
username: user.username,
|
|
email: user.email,
|
|
password: "",
|
|
role: user.role,
|
|
tenant_id: user.tenant_id || "",
|
|
enabled: user.enabled,
|
|
});
|
|
}
|
|
}, [user, open, form]);
|
|
|
|
const handleSubmit = async (data: UpdateUserForm) => {
|
|
if (!user) return;
|
|
|
|
try {
|
|
// Remove empty password field
|
|
const updateData = { ...data };
|
|
if (!updateData.password) {
|
|
delete updateData.password;
|
|
}
|
|
|
|
// Convert empty tenant_id to undefined
|
|
if (updateData.tenant_id === "") {
|
|
updateData.tenant_id = undefined;
|
|
}
|
|
|
|
await updateUser.mutateAsync({
|
|
id: user.id,
|
|
data: updateData,
|
|
});
|
|
onClose();
|
|
} catch (error) {
|
|
// Error is handled by the mutation
|
|
}
|
|
};
|
|
|
|
const roleOptions = [
|
|
...(isAdmin ? [{ value: "admin", label: "Administrador" }] : []),
|
|
{ value: "tenant_admin", label: "Administrador de Tenant" },
|
|
{ value: "user", label: "Usuario" },
|
|
{ value: "readonly", label: "Solo Lectura" },
|
|
];
|
|
|
|
if (!user) return null;
|
|
|
|
return (
|
|
<Modal open={open} onClickBackdrop={onClose}>
|
|
<Modal.Header className="font-bold">
|
|
Editar Usuario: {user.username}
|
|
</Modal.Header>
|
|
|
|
<Modal.Body>
|
|
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4">
|
|
<InputField
|
|
form={form}
|
|
name="username"
|
|
title="Nombre de Usuario"
|
|
placeholder="Ingresa el nombre de usuario"
|
|
/>
|
|
|
|
<InputField
|
|
form={form}
|
|
name="email"
|
|
title="Email"
|
|
type="email"
|
|
placeholder="Ingresa el email"
|
|
/>
|
|
|
|
<InputField
|
|
form={form}
|
|
name="password"
|
|
title="Nueva Contraseña"
|
|
type="password"
|
|
placeholder="Dejar vacío para mantener la actual"
|
|
/>
|
|
|
|
<div className="form-control w-full">
|
|
<label className="label">
|
|
<span className="label-text">Rol</span>
|
|
</label>
|
|
<Select
|
|
{...form.register("role")}
|
|
className="select-bordered"
|
|
>
|
|
{roleOptions.map((option) => (
|
|
<Select.Option key={option.value} value={option.value}>
|
|
{option.label}
|
|
</Select.Option>
|
|
))}
|
|
</Select>
|
|
</div>
|
|
|
|
{/* Show tenant selector for tenant_admin and user roles */}
|
|
{(selectedRole === "tenant_admin" || selectedRole === "user") && (
|
|
<div className="form-control w-full">
|
|
<label className="label">
|
|
<span className="label-text">Tenant</span>
|
|
</label>
|
|
<Select
|
|
{...form.register("tenant_id")}
|
|
className="select-bordered"
|
|
>
|
|
<Select.Option value="">Sin tenant</Select.Option>
|
|
{tenants?.map((tenant) => (
|
|
<Select.Option key={tenant.id} value={tenant.id}>
|
|
{tenant.name}
|
|
</Select.Option>
|
|
))}
|
|
</Select>
|
|
</div>
|
|
)}
|
|
|
|
<div className="form-control">
|
|
<label className="label cursor-pointer justify-start space-x-3">
|
|
<Toggle
|
|
{...form.register("enabled")}
|
|
color="success"
|
|
/>
|
|
<span className="label-text">Usuario habilitado</span>
|
|
</label>
|
|
</div>
|
|
</form>
|
|
</Modal.Body>
|
|
|
|
<Modal.Actions>
|
|
<Button onClick={onClose} disabled={updateUser.isPending}>
|
|
Cancelar
|
|
</Button>
|
|
<Button
|
|
color="primary"
|
|
loading={updateUser.isPending}
|
|
onClick={form.handleSubmit(handleSubmit)}
|
|
>
|
|
Actualizar Usuario
|
|
</Button>
|
|
</Modal.Actions>
|
|
</Modal>
|
|
);
|
|
} |