Notas y bibliotecas funcionando

This commit is contained in:
2025-05-14 02:06:33 +02:00
parent bf1814bb8e
commit c13240b481
18 changed files with 266 additions and 168 deletions
+106 -28
View File
@@ -12,6 +12,7 @@ import {
Modal,
Box,
Loader,
Textarea
} from '@mantine/core';
import { AppShellWithMenu } from '../components/Appshell/Appshell';
import axios from 'axios';
@@ -38,6 +39,10 @@ export function Biblioteca() {
const [loadingNotas, setLoadingNotas] = useState(false);
const [notaEnEdicion, setNotaEnEdicion] = useState<Nota | null>(null);
const [modalEditarAbierto, setModalEditarAbierto] = useState(false);
const [modalNuevaBiblio, setModalNuevaBiblio] = useState(false);
const [nombreBiblio, setNombreBiblio] = useState('');
const [descripcionBiblio, setDescripcionBiblio] = useState('');
const [loadingNuevaBiblio, setLoadingNuevaBiblio] = useState(false);
const fetchBibliotecas = async () => {
@@ -63,6 +68,31 @@ export function Biblioteca() {
}
};
const crearBiblioteca = async () => {
setLoadingNuevaBiblio(true); // 🔄 Activa el loader en el botón
try {
// Llamada a backend
await axios.post('/api/v1/text_manager/biblioteca', {
nombre_biblioteca: nombreBiblio,
descripcion: descripcionBiblio,
});
// 🧼 Limpia formularios
setNombreBiblio('');
setDescripcionBiblio('');
// 🔒 Cierra el modal
setModalNuevaBiblio(false);
// 🔄 Refresca la lista de bibliotecas
await fetchBibliotecas();
} catch (error) {
console.error('❌ Error al crear biblioteca:', error);
} finally {
setLoadingNuevaBiblio(false); // ✅ Apaga el loader
}
};
const agregarNota = async () => {
if (!bibliotecaSeleccionada) return;
@@ -101,7 +131,14 @@ export function Biblioteca() {
if (!bibliotecaSeleccionada) return;
try {
await axios.delete(`/api/v1/text_manager/nota/${bibliotecaSeleccionada.id}/${notaId}`);
await fetchBibliotecas();
// Solo actualiza la biblioteca actual
const nuevasNotas = await axios.get(`/api/v1/text_manager/nota/list/${bibliotecaSeleccionada.id}`);
const nuevasBibliotecas = bibliotecas.map((b) =>
b.id === bibliotecaSeleccionada.id ? { ...b, notas: nuevasNotas.data as Nota[] } : b
);
setBibliotecas(nuevasBibliotecas);
setBibliotecaSeleccionada(nuevasBibliotecas.find(b => b.id === bibliotecaSeleccionada.id) || null);
} catch (error) {
console.error("Error al eliminar nota:", error);
}
@@ -140,9 +177,9 @@ export function Biblioteca() {
<Box w={240} p="md">
<ScrollArea h="100%">
<Stack>
<Button color="teal" onClick={fetchBibliotecas}>
🔄 Recuperar bibliotecas
</Button>
<Button color="teal" onClick={fetchBibliotecas}>🔄 Recuperar bibliotecas</Button>
<Button color="grape" variant="outline" onClick={() => setModalNuevaBiblio(true)}> Nueva biblioteca</Button>
{bibliotecas.map((biblio) => (
<Button
@@ -181,32 +218,29 @@ export function Biblioteca() {
padding="lg"
radius="md"
withBorder
style={{ width: 300, position: 'relative' }}
style={{
width: 300,
height: 250, // Altura fija para asegurar la separación
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
}}
>
{/* Botones en esquina superior derecha */}
<Box style={{ position: 'absolute', top: 8, right: 8, display: 'flex', gap: 4, zIndex: 1 }}>
<div>
<Title order={4} style={{ marginBottom: 10 }}>{nota.titulo}</Title>
<Text>{nota.texto}</Text>
</div>
<Box mt="md" style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Button
size="xs"
color="blue"
variant="light"
p={4}
color="blue"
onClick={() => abrirModalEditar(nota)}
>
</Button>
<Button
size="xs"
color="red"
variant="light"
p={4}
onClick={() => eliminarNota(nota.id)}
>
🗑
Editar
</Button>
</Box>
<Title order={4} style={{ marginBottom: 10 }}>{nota.titulo}</Title>
<Text>{nota.texto}</Text>
</Card>
// Fin de notas en cards
@@ -218,9 +252,7 @@ export function Biblioteca() {
) : (
<Stack>
<Text>Selecciona una biblioteca</Text>
<Button color="teal" onClick={fetchBibliotecas}>
🔄 Recuperar bibliotecas
</Button>
</Stack>
)}
</Box>
@@ -234,8 +266,10 @@ export function Biblioteca() {
value={tituloNota}
onChange={(event) => setTituloNota(event.currentTarget.value)}
/>
<TextInput
<Textarea
label="Contenido"
minRows={6}
autosize
value={contenidoNota}
onChange={(event) => setContenidoNota(event.currentTarget.value)}
/>
@@ -253,16 +287,60 @@ export function Biblioteca() {
setNotaEnEdicion((prev) => (prev ? { ...prev, titulo: e.currentTarget.value } : null))
}
/>
<TextInput
<Textarea
label="Contenido"
minRows={6}
autosize
value={notaEnEdicion?.texto || ""}
onChange={(e) =>
setNotaEnEdicion((prev) => (prev ? { ...prev, texto: e.currentTarget.value } : null))
}
/>
<Button onClick={guardarEdicionNota}>Guardar cambios</Button>
<Group grow>
<Button color="blue" onClick={guardarEdicionNota}>
💾 Guardar cambios
</Button>
<Button
color="red"
onClick={async () => {
if (!notaEnEdicion || !bibliotecaSeleccionada) return;
await eliminarNota(notaEnEdicion.id);
setModalEditarAbierto(false);
setNotaEnEdicion(null);
}}
>
🗑 Eliminar nota
</Button>
</Group>
</Stack>
</Modal>
{/* Modal para crear una biblioteca */}
<Modal
opened={modalNuevaBiblio}
onClose={() => setModalNuevaBiblio(false)}
title="Crear nueva biblioteca"
>
<Stack>
<TextInput
label="Nombre"
value={nombreBiblio}
onChange={(e) => setNombreBiblio(e.currentTarget.value)}
disabled={loadingNuevaBiblio}
/>
<TextInput
label="Descripción"
value={descripcionBiblio}
onChange={(e) => setDescripcionBiblio(e.currentTarget.value)}
disabled={loadingNuevaBiblio}
/>
<Button onClick={crearBiblioteca} loading={loadingNuevaBiblio}>
Crear
</Button>
</Stack>
</Modal>
</AppShellWithMenu>
);