Add React frontend and Sinbad2IA LLM integration.

Introduce a full Vite/React UI for exams, auth, materials, images, generation, and export.
Adapt backend for Sinbad2IA chat API, bcrypt passwords, CORS on port 5173, and schema migrations.
This commit is contained in:
Mireya Cueto Garrido
2026-06-01 13:27:41 +02:00
parent 7bc27da33a
commit 946f16a633
66 changed files with 6769 additions and 48 deletions
+79
View File
@@ -0,0 +1,79 @@
import { useEffect } from "react";
import { createPortal } from "react-dom";
import Button from "./Button";
import Icon from "./Icon";
export default function Modal({ open, onClose, title, children, footer, large }) {
useEffect(() => {
if (!open) return;
const onKey = (e) => e.key === "Escape" && onClose?.();
window.addEventListener("keydown", onKey);
const prevOverflow = document.body.style.overflow;
document.body.style.overflow = "hidden";
return () => {
window.removeEventListener("keydown", onKey);
document.body.style.overflow = prevOverflow;
};
}, [open, onClose]);
if (!open) return null;
return createPortal(
<div className="modal-overlay" onMouseDown={onClose}>
<div
className={`modal ${large ? "modal-lg" : ""}`}
onMouseDown={(e) => e.stopPropagation()}
>
{title && (
<div className="modal-head">
<h3>{title}</h3>
<span style={{ flex: 1 }} />
<button className="toast-close" type="button" aria-label="Cerrar" onClick={onClose}>
<Icon name="close" size={16} />
</button>
</div>
)}
<div className="modal-body">{children}</div>
{footer && <div className="modal-foot">{footer}</div>}
</div>
</div>,
document.body
);
}
export function ConfirmDialog({
open,
title = "¿Confirmar?",
message,
confirmLabel = "Confirmar",
danger,
loading,
onConfirm,
onClose,
}) {
return (
<Modal
open={open}
onClose={onClose}
title={title}
footer={
<>
<Button variant="ghost" onClick={onClose} disabled={loading}>
Cancelar
</Button>
<Button
variant={danger ? "danger" : "primary"}
onClick={onConfirm}
loading={loading}
>
{confirmLabel}
</Button>
</>
}
>
<p className="text-soft" style={{ margin: 0 }}>
{message}
</p>
</Modal>
);
}