feat: implement form validation for alumno editing using Zod schema
This commit is contained in:
parent
6c5a04aec4
commit
65893bf052
|
@ -19,14 +19,16 @@ import {
|
|||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { set } from "react-hook-form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { alumnoSchema } from "@/schemas/AlumnosSchema";
|
||||
|
||||
export default function AlumnosVista() {
|
||||
const [alumnos, setAlumnos] = useState([]);
|
||||
const [alumnoEditando, setAlumnoEditando] = useState(null);
|
||||
const [nuevoNombre, setNuevoNombre] = useState("");
|
||||
const [nuevoCorreo, setNuevoCorreo] = useState("");
|
||||
const [nuevoNumero, setNuevoNumero] = useState("");
|
||||
const [nuevoNumero, setNuevoNumero] = useState("");
|
||||
const [mostrarModal, setMostrarModal] = useState(false);
|
||||
const [modalMensaje, setModalMensaje] = useState("");
|
||||
const [nuevoCurso, setNuevoCurso] = useState("");
|
||||
|
@ -62,38 +64,50 @@ export default function AlumnosVista() {
|
|||
}
|
||||
};
|
||||
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
setValue,
|
||||
reset,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: zodResolver(alumnoSchema),
|
||||
defaultValues: {
|
||||
nombre: "",
|
||||
correo: "",
|
||||
telefono: "",
|
||||
cursoSeleccionado: "",
|
||||
},
|
||||
});
|
||||
|
||||
// Iniciar edición
|
||||
const iniciarEdicion = (alumno) => {
|
||||
setAlumnoEditando(alumno.id);
|
||||
setNuevoNombre(alumno.nombre);
|
||||
setNuevoCorreo(alumno.correo);
|
||||
setNuevoNumero(alumno.telefono);
|
||||
setNuevoCurso(alumno.curso_id);
|
||||
setValue("nombre", alumno.nombre);
|
||||
setValue("correo", alumno.correo);
|
||||
setValue("telefono", alumno.telefono);
|
||||
setValue("cursoSeleccionado", alumno.curso_id?.toString() || "");
|
||||
};
|
||||
|
||||
// Cancelar edición
|
||||
const cancelarEdicion = () => {
|
||||
setAlumnoEditando(null);
|
||||
setNuevoNombre("");
|
||||
setNuevoCorreo("");
|
||||
setNuevoNumero("");
|
||||
setNuevoCurso("");
|
||||
reset();
|
||||
};
|
||||
|
||||
// Guardar cambios
|
||||
const guardarEdicion = async (id) => {
|
||||
const guardarEdicion = async (data) => {
|
||||
const { error } = await supabaseClient
|
||||
.from("alumno")
|
||||
.update({
|
||||
nombre: nuevoNombre,
|
||||
correo: nuevoCorreo,
|
||||
telefono: nuevoNumero,
|
||||
curso_id: nuevoCurso,
|
||||
nombre: data.nombre,
|
||||
correo: data.correo,
|
||||
telefono: data.telefono,
|
||||
curso_id: data.cursoSeleccionado,
|
||||
})
|
||||
.eq("id", id);
|
||||
.eq("id", alumnoEditando);
|
||||
|
||||
if (error) {
|
||||
console.error("Error actualizando alumno:", error.message);
|
||||
setModalMensaje("Error al actualizar el alumno");
|
||||
} else {
|
||||
setModalMensaje("Alumno actualizado exitosamente");
|
||||
|
@ -111,7 +125,10 @@ export default function AlumnosVista() {
|
|||
|
||||
// Eliminar alumno
|
||||
const eliminarAlumno = async () => {
|
||||
const { error } = await supabaseClient.from("alumno").delete().eq("id", alumnoAEliminar);
|
||||
const { error } = await supabaseClient
|
||||
.from("alumno")
|
||||
.delete()
|
||||
.eq("id", alumnoAEliminar);
|
||||
if (error) {
|
||||
console.error("Error eliminando alumno:", error.message);
|
||||
setModalMensaje("Error al eliminar el alumno");
|
||||
|
@ -148,47 +165,61 @@ export default function AlumnosVista() {
|
|||
{alumno.id}
|
||||
</td>
|
||||
<td className="py-2 px-4 border-b">
|
||||
<Input
|
||||
type="text"
|
||||
value={nuevoNombre}
|
||||
onChange={(e) => setNuevoNombre(e.target.value)}
|
||||
/>
|
||||
<Input type="text" {...register("nombre")} />
|
||||
{errors.nombre && (
|
||||
<span className="text-red-500 text-xs">
|
||||
{errors.nombre.message}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="py-2 px-4 border-b">
|
||||
<Input
|
||||
type="email"
|
||||
value={nuevoCorreo}
|
||||
onChange={(e) => setNuevoCorreo(e.target.value)}
|
||||
/>
|
||||
<Input type="email" {...register("correo")} />
|
||||
{errors.correo && (
|
||||
<span className="text-red-500 text-xs">
|
||||
{errors.correo.message}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="py-2 px-4 border-b">
|
||||
<Input
|
||||
type="text"
|
||||
value={nuevoNumero}
|
||||
onChange={(e) => setNuevoNumero(e.target.value)}
|
||||
/>
|
||||
<Input type="text" {...register("telefono")} />
|
||||
{errors.telefono && (
|
||||
<span className="text-red-500 text-xs">
|
||||
{errors.telefono.message}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="py-2 px-4 border-b">
|
||||
<Select
|
||||
value={nuevoCurso}
|
||||
onValueChange={(value) => setNuevoCurso(value)}
|
||||
value={undefined}
|
||||
onValueChange={(value) =>
|
||||
setValue("cursoSeleccionado", value)
|
||||
}
|
||||
{...register("cursoSeleccionado")}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Selecciona un curso" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{cursos.map((curso) => (
|
||||
<SelectItem key={curso.id} value={curso.id.toString()}>
|
||||
<SelectItem
|
||||
key={curso.id}
|
||||
value={curso.id.toString()}
|
||||
>
|
||||
{curso.nombre}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{errors.cursoSeleccionado && (
|
||||
<span className="text-red-500 text-xs">
|
||||
{errors.cursoSeleccionado.message}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="py-2 px-4 border-b flex justify-center">
|
||||
<Button
|
||||
className="bg-green-500 hover:bg-green-700 text-white font-bold py-1 px-3 m-2 rounded"
|
||||
onClick={() => guardarEdicion(alumno.id)}
|
||||
onClick={handleSubmit(guardarEdicion)}
|
||||
>
|
||||
Guardar
|
||||
</Button>
|
||||
|
@ -206,7 +237,9 @@ export default function AlumnosVista() {
|
|||
<td className="py-2 px-4 border-b">{alumno.nombre}</td>
|
||||
<td className="py-2 px-4 border-b">{alumno.correo}</td>
|
||||
<td className="py-2 px-4 border-b">{alumno.telefono}</td>
|
||||
<td className="py-2 px-4 border-b">{alumno.curso?.nombre || "Sin curso"}</td>
|
||||
<td className="py-2 px-4 border-b">
|
||||
{alumno.curso?.nombre || "Sin curso"}
|
||||
</td>
|
||||
<td className="py-2 px-4 border-b space-x-2">
|
||||
<Button
|
||||
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded"
|
||||
|
@ -233,9 +266,12 @@ export default function AlumnosVista() {
|
|||
<Dialog open={confirmarEliminar} onOpenChange={setConfirmarEliminar}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-black">Confirmar eliminación</DialogTitle>
|
||||
<DialogTitle className="text-black">
|
||||
Confirmar eliminación
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
¿Estás seguro de que deseas eliminar este alumno? Esta acción no se puede deshacer.
|
||||
¿Estás seguro de que deseas eliminar este alumno? Esta acción no
|
||||
se puede deshacer.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
|
@ -271,4 +307,4 @@ export default function AlumnosVista() {
|
|||
</Dialog>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ export const alumnoSchema = z.object({
|
|||
telefono: z
|
||||
.string()
|
||||
.nonempty("Escribe el número de teléfono")
|
||||
.regex(/^\d+$/, "Solo se permiten números en el teléfono"),
|
||||
.regex(/^\d+$/, "El número de teléfono solo puede contener dígitos")
|
||||
.min(10, "El número de teléfono debe tener al menos 10 dígitos")
|
||||
.max(10, "El número de teléfono no puede tener más de 10 dígitos"),
|
||||
cursoSeleccionado: z.string().nonempty("Selecciona un curso"),
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue