feat: refactor diploma dialogs to improve structure and user experience, including enhanced layout and state management
This commit is contained in:
parent
a2a0b9631a
commit
d2c7bddf18
|
@ -1,9 +1,10 @@
|
||||||
import { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
|
DialogDescription,
|
||||||
DialogFooter,
|
DialogFooter,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
@ -15,7 +16,7 @@ const DISEÑOS = [
|
||||||
{ id: 2, nombre: "Diseño Moderno" },
|
{ id: 2, nombre: "Diseño Moderno" },
|
||||||
];
|
];
|
||||||
|
|
||||||
function CrearDiplomaDialog({
|
export default function CrearDiplomaDialog({
|
||||||
open,
|
open,
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
alumno,
|
alumno,
|
||||||
|
@ -26,13 +27,13 @@ function CrearDiplomaDialog({
|
||||||
fecha,
|
fecha,
|
||||||
setFecha,
|
setFecha,
|
||||||
}) {
|
}) {
|
||||||
const [diseñoSeleccionado, setDiseñoSeleccionado] = useState(
|
const [diseñoSeleccionado, setDiseñoSeleccionado] = useState(DISEÑOS[0]?.id || null);
|
||||||
DISEÑOS[0]?.id || null
|
|
||||||
);
|
|
||||||
|
|
||||||
const toggleCompetencia = (id) => {
|
const toggleCompetencia = (id) => {
|
||||||
setCompetenciasAcreditadas((prev) =>
|
setCompetenciasAcreditadas((prev) =>
|
||||||
prev.includes(id) ? prev.filter((cid) => cid !== id) : [...prev, id]
|
prev.includes(id)
|
||||||
|
? prev.filter((cid) => cid !== id)
|
||||||
|
: [...prev, id]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,64 +44,61 @@ function CrearDiplomaDialog({
|
||||||
.select("competencia(id, descripcion)")
|
.select("competencia(id, descripcion)")
|
||||||
.eq("curso_id", alumno.curso.id)
|
.eq("curso_id", alumno.curso.id)
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
const comps = data?.map((c) => c.competencia) || [];
|
const comps = data?.map((c) => c.competencia).filter(Boolean) || [];
|
||||||
setCompetencias(comps);
|
setCompetencias(comps);
|
||||||
setCompetenciasAcreditadas(comps.map((c) => c.id)); // todas seleccionadas por default
|
setCompetenciasAcreditadas(comps.map((c) => c.id)); // todas seleccionadas por default
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [alumno]);
|
}, [alumno, setCompetencias, setCompetenciasAcreditadas]);
|
||||||
|
|
||||||
const handleCrearDiploma = async () => {
|
const handleCrearDiploma = async () => {
|
||||||
// Aquí va la lógica para crear el diploma en la base de datos
|
// Aquí va la lógica para crear el diploma en la base de datos
|
||||||
// 1. Insertar en Diploma
|
|
||||||
// 2. Insertar en Diploma_Competencia
|
|
||||||
// 3. (Opcional) Generar PDF y enviar
|
|
||||||
|
|
||||||
// Ejemplo de inserción (ajusta según tu lógica real)
|
|
||||||
// await supabaseClient.from("Diploma").insert({...});
|
|
||||||
// await supabaseClient.from("Diploma_Competencia").insert([...]);
|
|
||||||
|
|
||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
// Aquí puedes mostrar un mensaje de éxito o iniciar la generación del PDF
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!alumno) return null;
|
if (!open || !alumno) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-black p-4">
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
<h2 className="text-xl font-bold mb-4">Crear Diploma</h2>
|
<DialogContent className="w-[400px]">
|
||||||
<div className="mb-2">
|
<DialogHeader>
|
||||||
<label className="block text-sm font-semibold mb-1">
|
<DialogTitle>Crear Diploma</DialogTitle>
|
||||||
Competencias:
|
<DialogDescription>
|
||||||
</label>
|
Selecciona las competencias acreditadas para el diploma.
|
||||||
{competencias.map((comp) => (
|
</DialogDescription>
|
||||||
<div key={comp.id} className="flex items-center mb-1">
|
</DialogHeader>
|
||||||
<input
|
<div className="mb-2">
|
||||||
type="checkbox"
|
<label className="block text-sm font-semibold mb-1">Competencias:</label>
|
||||||
checked={competenciasAcreditadas.includes(comp.id)}
|
{competencias.map((comp) => (
|
||||||
onChange={() => toggleCompetencia(comp.id)}
|
<div key={comp.id} className="flex items-center mb-1">
|
||||||
className="mr-2"
|
<input
|
||||||
/>
|
type="checkbox"
|
||||||
<span>{comp.descripcion}</span>
|
checked={competenciasAcreditadas.includes(comp.id)}
|
||||||
</div>
|
onChange={() => toggleCompetencia(comp.id)}
|
||||||
))}
|
className="mr-2"
|
||||||
</div>
|
/>
|
||||||
<div className="w-full flex justify-around">
|
<span>{comp.descripcion}</span>
|
||||||
<Button
|
</div>
|
||||||
onClick={handleCrearDiploma}
|
))}
|
||||||
className="bg-green-500 hover:bg-green-700 text-white"
|
</div>
|
||||||
>
|
<div className="mb-2">
|
||||||
Crear Diploma
|
<label className="block text-sm font-semibold mb-1">Fecha:</label>
|
||||||
</Button>
|
<input
|
||||||
<Button
|
type="date"
|
||||||
onClick={() => onOpenChange(false)}
|
className="border p-1 w-full"
|
||||||
className="bg-gray-400 hover:bg-gray-600 text-white"
|
value={fecha}
|
||||||
>
|
onChange={e => setFecha(e.target.value)}
|
||||||
Cancelar
|
/>
|
||||||
</Button>
|
</div>
|
||||||
</div>
|
<DialogFooter>
|
||||||
</div>
|
<Button onClick={handleCrearDiploma} className="bg-green-500 hover:bg-green-700 text-white">
|
||||||
|
Crear Diploma
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => onOpenChange(false)} className="bg-gray-400 hover:bg-gray-600 text-white">
|
||||||
|
Cancelar
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CrearDiplomaDialog;
|
|
||||||
|
|
|
@ -19,12 +19,14 @@ function VistaPreviaDiplomaDialog({
|
||||||
}) {
|
}) {
|
||||||
const [mostrarVistaPrevia, setMostrarVistaPrevia] = useState(false);
|
const [mostrarVistaPrevia, setMostrarVistaPrevia] = useState(false);
|
||||||
|
|
||||||
if (!alumno) return null;
|
if (!open || !alumno) return null;
|
||||||
|
|
||||||
const competenciasMostradas =
|
// Filtra solo las competencias seleccionadas si se pasa el array de acreditadas
|
||||||
Array.isArray(competenciasAcreditadas) && competenciasAcreditadas.length > 0
|
const competenciasMostradas = Array.isArray(competenciasAcreditadas)
|
||||||
? competencias.filter((comp) => competenciasAcreditadas.includes(comp.id))
|
? (Array.isArray(competencias) ? competencias : []).filter((comp) =>
|
||||||
: [];
|
competenciasAcreditadas.includes(comp.id)
|
||||||
|
)
|
||||||
|
: (Array.isArray(competencias) ? competencias : []);
|
||||||
|
|
||||||
const competenciasParaPDF =
|
const competenciasParaPDF =
|
||||||
Array.isArray(competenciasMostradas) && competenciasMostradas.length > 0
|
Array.isArray(competenciasMostradas) && competenciasMostradas.length > 0
|
||||||
|
@ -32,8 +34,8 @@ function VistaPreviaDiplomaDialog({
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-black p-4">
|
<div className="bg-white border shadow-lg rounded p-8 w-[500px] h-[350px] mx-4 flex flex-col text-black">
|
||||||
<h2 className="text-xl font-bold mb-4">Diploma</h2>
|
<h2 className="text-2xl font-bold text-center mb-6">Diploma</h2>
|
||||||
<div className="text-lg mb-2">
|
<div className="text-lg mb-2">
|
||||||
<b>Alumno:</b> {alumno.nombre}
|
<b>Alumno:</b> {alumno.nombre}
|
||||||
</div>
|
</div>
|
||||||
|
@ -51,61 +53,9 @@ function VistaPreviaDiplomaDialog({
|
||||||
<div className="text-lg mb-2">
|
<div className="text-lg mb-2">
|
||||||
<b>Fecha:</b> {fecha || new Date().toLocaleDateString()}
|
<b>Fecha:</b> {fecha || new Date().toLocaleDateString()}
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 flex justify-around">
|
<div className="mt-auto text-gray-400 text-xs text-right">
|
||||||
<PDFDownloadLink
|
Vista previa
|
||||||
document={
|
|
||||||
<Diploma
|
|
||||||
alumno={alumno}
|
|
||||||
curso={alumno.curso}
|
|
||||||
competencias={competenciasParaPDF}
|
|
||||||
fecha={fecha || new Date().toLocaleDateString()}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
fileName={`Diploma_${alumno.nombre}.pdf`}
|
|
||||||
>
|
|
||||||
{({ loading }) =>
|
|
||||||
loading ? (
|
|
||||||
<Button className="bg-gray-300 px-4 py-2 rounded" disabled>
|
|
||||||
Generando PDF...
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button className="bg-green-500 hover:bg-green-700 text-white px-4 py-2 rounded">
|
|
||||||
Descargar PDF
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</PDFDownloadLink>
|
|
||||||
<Button
|
|
||||||
className="bg-blue-500 hover:bg-blue-700 text-white px-4 py-2 rounded"
|
|
||||||
onClick={() => setMostrarVistaPrevia(true)}
|
|
||||||
>
|
|
||||||
Vista previa
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Vista previa del PDF */}
|
|
||||||
{mostrarVistaPrevia && (
|
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-60 flex flex-col items-center justify-center z-50">
|
|
||||||
<div className="bg-white rounded shadow-lg p-4 flex flex-col items-center">
|
|
||||||
<div className="w-[80vw] h-[80vh] mb-4 border">
|
|
||||||
<PDFViewer width="100%" height="100%">
|
|
||||||
<Diploma
|
|
||||||
alumno={alumno}
|
|
||||||
curso={alumno.curso}
|
|
||||||
competencias={competenciasParaPDF}
|
|
||||||
fecha={fecha || new Date().toLocaleDateString()}
|
|
||||||
/>
|
|
||||||
</PDFViewer>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
className="bg-red-500 hover:bg-red-700 text-white px-4 py-2 rounded"
|
|
||||||
onClick={() => setMostrarVistaPrevia(false)}
|
|
||||||
>
|
|
||||||
Cerrar vista previa
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { supabaseClient } from "@/utils/supabase";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import CrearDiplomaDialog from "@/components/dialogs/crearDiplomaDialog";
|
import CrearDiplomaDialog from "@/components/dialogs/crearDiplomaDialog";
|
||||||
import VistaPreviaDiplomaDialog from "@/components/dialogs/vistaPreviaDiplomaDialog";
|
import VistaPreviaDiplomaDialog from "@/components/dialogs/vistaPreviaDiplomaDialog";
|
||||||
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
|
||||||
|
|
||||||
export default function DiplomasVista() {
|
export default function DiplomasVista() {
|
||||||
const [alumnos, setAlumnos] = useState([]);
|
const [alumnos, setAlumnos] = useState([]);
|
||||||
|
@ -80,33 +79,30 @@ export default function DiplomasVista() {
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{/* Dialog para crear diploma y vista previa juntos */}
|
{/* Dialog para crear diploma y vista previa juntos */}
|
||||||
<Dialog open={mostrarDialog} onOpenChange={handleCloseDialog}>
|
{mostrarDialog && (
|
||||||
<DialogContent className="min-w-4xl">
|
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||||
<div className="flex flex-row gap-8">
|
<div className="flex gap-8 bg-black bg-opacity-30 p-8 rounded">
|
||||||
<div className="w-[350px]">
|
<CrearDiplomaDialog
|
||||||
<CrearDiplomaDialog
|
open={mostrarDialog}
|
||||||
onOpenChange={handleCloseDialog}
|
onOpenChange={handleCloseDialog}
|
||||||
alumno={alumnoSeleccionado}
|
alumno={alumnoSeleccionado}
|
||||||
competencias={competencias}
|
competencias={competencias}
|
||||||
setCompetencias={setCompetencias}
|
setCompetencias={setCompetencias}
|
||||||
competenciasAcreditadas={competenciasAcreditadas}
|
competenciasAcreditadas={competenciasAcreditadas}
|
||||||
setCompetenciasAcreditadas={setCompetenciasAcreditadas}
|
setCompetenciasAcreditadas={setCompetenciasAcreditadas}
|
||||||
fecha={fecha}
|
fecha={fecha}
|
||||||
setFecha={setFecha}
|
setFecha={setFecha}
|
||||||
/>
|
/>
|
||||||
</div>
|
<VistaPreviaDiplomaDialog
|
||||||
<div className="w-[400px]">
|
open={mostrarDialog}
|
||||||
<VistaPreviaDiplomaDialog
|
alumno={alumnoSeleccionado}
|
||||||
onOpenChange={handleCloseDialog}
|
competencias={competencias}
|
||||||
alumno={alumnoSeleccionado}
|
fecha={fecha}
|
||||||
competencias={competencias}
|
competenciasAcreditadas={competenciasAcreditadas}
|
||||||
fecha={fecha}
|
/>
|
||||||
competenciasAcreditadas={competenciasAcreditadas}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</div>
|
||||||
</Dialog>
|
)}
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue