diff --git a/FrontAdmin/package-lock.json b/FrontAdmin/package-lock.json index dc93a4ce..9b4b7f33 100644 --- a/FrontAdmin/package-lock.json +++ b/FrontAdmin/package-lock.json @@ -32,7 +32,8 @@ "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-icons": "^5.2.1", - "react-router-dom": "^6.26.0" + "react-router-dom": "^6.26.0", + "xlsx": "^0.18.5" }, "devDependencies": { "@types/js-cookie": "^3.0.6", @@ -3540,6 +3541,14 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -3714,6 +3723,18 @@ "node": ">=6" } }, + "node_modules/cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3759,6 +3780,14 @@ "node": ">=6" } }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3838,6 +3867,17 @@ "node": ">=10" } }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -4406,6 +4446,14 @@ "node": ">=10" } }, + "node_modules/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/framer-motion": { "version": "11.9.0", "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.9.0.tgz", @@ -5964,6 +6012,17 @@ "node": ">=0.10.0" } }, + "node_modules/ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -6354,6 +6413,22 @@ "string-width": "^1.0.2 || 2 || 3 || 4" } }, + "node_modules/wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -6369,6 +6444,26 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "devOptional": true }, + "node_modules/xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "dependencies": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/FrontAdmin/package.json b/FrontAdmin/package.json index 4ef39fa6..e196bf8d 100644 --- a/FrontAdmin/package.json +++ b/FrontAdmin/package.json @@ -35,7 +35,8 @@ "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-icons": "^5.2.1", - "react-router-dom": "^6.26.0" + "react-router-dom": "^6.26.0", + "xlsx": "^0.18.5" }, "devDependencies": { "@types/js-cookie": "^3.0.6", diff --git a/FrontAdmin/src/API-Alumnos/Compromiso.ts b/FrontAdmin/src/API-Alumnos/Compromiso.ts index dbc55e12..481e0015 100644 --- a/FrontAdmin/src/API-Alumnos/Compromiso.ts +++ b/FrontAdmin/src/API-Alumnos/Compromiso.ts @@ -1,11 +1,13 @@ import Cookies from 'js-cookie' // los dni son la mama de lo hardcodeado -export const FetchCompromisos = async () => { +export const FetchCompromisos = async (dni: number | undefined ) => { try { const token = Cookies.get('tokennn'); - const dni = Cookies.get('dni'); - + if (!dni) { + dni = parseInt(Cookies.get('dni') || '', 10); + } + const response = await fetch(`http://localhost:8000/api/firmas/firmas-de-alumno/${dni}/`, { method: 'GET', headers: { diff --git a/FrontAdmin/src/API-Alumnos/DarseBaja.ts b/FrontAdmin/src/API-Alumnos/DarseBaja.ts new file mode 100644 index 00000000..446c8a3f --- /dev/null +++ b/FrontAdmin/src/API-Alumnos/DarseBaja.ts @@ -0,0 +1,121 @@ +import Cookies from 'js-cookie'; + +export const solicitarBajaAlumno = async (dni: number, motivo: string) => { + try { + const response = await fetch(`http://localhost:8000/api/alumnos/${dni}/solicitar-baja/`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${Cookies.get('tokennn')}`, + }, + body: JSON.stringify({ + motivo: motivo, + }), + }); + + if (response.ok) { + console.log('Baja solicitada correctamente'); + return true; + } else { + console.error('Error al solicitar la baja'); + return false; + } + } catch (error) { + console.error('Error al solicitar la baja:', error); + return false; + } +}; + +export const verficarBajaAlumno = async (dni: number) => { + try { + const response = await fetch(`http://localhost:8000/api/alumnos/${dni}/puede-solicitar-baja/`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${Cookies.get('tokennn')}`, + }, + }); + + if (response.ok) { + const data = await response.json(); + return data.puede_solicitar; + } else { + console.error('Error al verificar si el alumno puede solicitar la baja'); + return false; + } + } catch (error) { + console.error('Error al verificar si el alumno puede solicitar la baja:', error); + return false; + } +}; + +export const bajasSolicitadas = async () => { + try { + const response = await fetch(`http://localhost:8000/api/alumnos/bajas_solicitadas/`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${Cookies.get('tokennn')}`, + }, + }); + + if (response.ok) { + const data = await response.json(); + return data; + } else { + console.error('Error al verificar si el alumno puede solicitar la baja'); + return false; + } + } catch (error) { + console.error('Error al verificar si el alumno puede solicitar la baja:', error); + return false; + } +}; + +export const responderBaja = async (dni: number, respuesta: string) => { + try { + const response = await fetch(`http://localhost:8000/api/alumnos/baja/${dni}/`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${Cookies.get('tokennn')}`, + }, + body: JSON.stringify({ + estado: respuesta, + }), + + }); + + if (response.ok) { + + return true; + } else { + + return false; + } + } catch (error) { + console.error( error); + return false; + } +}; + +export const dadosDeBaja = async () => { + try { + const response = await fetch(`http://localhost:8000/api/alumnos/baja/`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${Cookies.get('tokennn')}`, + }, + + }); + + if (response.ok) { + const data = await response.json(); + return data; + } + } catch (error) { + console.error( error); + return false; + } +}; \ No newline at end of file diff --git a/FrontAdmin/src/API-Alumnos/InhabilitacionesAlumno.ts b/FrontAdmin/src/API-Alumnos/InhabilitacionesAlumno.ts new file mode 100644 index 00000000..0276bb0d --- /dev/null +++ b/FrontAdmin/src/API-Alumnos/InhabilitacionesAlumno.ts @@ -0,0 +1,32 @@ +import Cookies from 'js-cookie'; + +export const inhabilitacionesA = async ( + dni: number, +) => { + try { + const token = Cookies.get('tokennn'); + + const response = await fetch(`http://localhost:8000/api/alumnos/${dni}/inhabilitaciones/`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + }); + + if (response.ok) { + const data = await response.json(); + return data; + } else { + const errorData = await response.json(); + throw new Error( + `Error en la respuesta del servidor: ${errorData.message}` + ); + } + } catch (error) { + console.error('Network error:', error); + throw error; + } + + +}; \ No newline at end of file diff --git a/FrontAdmin/src/API-Alumnos/Pagos.ts b/FrontAdmin/src/API-Alumnos/Pagos.ts index 71b6718e..7fa72d5c 100644 --- a/FrontAdmin/src/API-Alumnos/Pagos.ts +++ b/FrontAdmin/src/API-Alumnos/Pagos.ts @@ -9,7 +9,7 @@ export const FetchPostPago = async ( const token = Cookies.get('tokennn'); const dni = Cookies.get('dni'); - const response = await fetch(`http://localhost:8000/api/pagos/alumno/${dni}`, { + const response = await fetch(`http://localhost:8000/api/pagos/alumno/${dni}/`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -36,11 +36,12 @@ export const FetchPostPago = async ( }; -export const FetchGetCuotas = async () => { +export const FetchGetCuotas = async (dni: number | undefined ) => { try { const token = Cookies.get('tokennn'); - const dni = Cookies.get('dni'); - + if (!dni) { + dni = parseInt(Cookies.get('dni') || '', 10); + } const response = await fetch(`http://localhost:8000/api/cuotas/alumno/${dni}/impagas/`, { method: 'GET', headers: { @@ -61,11 +62,12 @@ export const FetchGetCuotas = async () => { }; -export const FetchResumenPagos = async () => { +export const FetchResumenPagos = async (dni: number | undefined ) => { try { const token = Cookies.get('tokennn'); - const dni = Cookies.get('dni'); - + if (!dni) { + dni = parseInt(Cookies.get('dni') || '', 10); + } const response = await fetch(`http://localhost:8000/api/pagos/alumno/resumen_pagos/${dni}`, { method: 'GET', headers: { diff --git a/FrontAdmin/src/API/AbonaronCuota.ts b/FrontAdmin/src/API/AbonaronCuota.ts index 953187f3..0c40b463 100644 --- a/FrontAdmin/src/API/AbonaronCuota.ts +++ b/FrontAdmin/src/API/AbonaronCuota.ts @@ -1,10 +1,13 @@ import Cookies from 'js-cookie'; -export const AbonaronCuota = async (fecha: string) => { +export const AbonaronCuota = async (fecha: string, limit:number, offset:number, valor?: string) => { try { const token = Cookies.get('tokennn'); - const response = await fetch(`http://localhost:8000/api/alumnos/pagaron-cuota/${fecha}/`, { + const url = valor + ? `http://localhost:8000/api/alumnos/pagaron-cuota/${fecha}/?limit=${limit}&offset=${offset}&valor=${valor}` + : `http://localhost:8000/api/alumnos/pagaron-cuota/${fecha}/?limit=${limit}&offset=${offset}`; + const response = await fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -27,12 +30,15 @@ export const AbonaronCuota = async (fecha: string) => { } }; -export const NoAbonaronCuota = async (fecha: string, limit: number, offset:number) => { - try { - +export const NoAbonaronCuota = async (fecha: string, limit: number, offset: number, valor?: string) => { + try { const token = Cookies.get('tokennn'); - const response = await fetch(`http://localhost:8000/api/alumnos/no-pagaron-cuota/${fecha}/?limit=${limit}&offset=${offset}&ordering=full_name`, { - method: 'GET', + const url = valor + ? `http://localhost:8000/api/alumnos/no-pagaron-cuota/${fecha}/?limit=${limit}&offset=${offset}&valor=${valor}` + : `http://localhost:8000/api/alumnos/no-pagaron-cuota/${fecha}/?limit=${limit}&offset=${offset}`; + + const response = await fetch(url, { + method: 'GET', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}`, diff --git a/FrontAdmin/src/API/AbonaronMatricula.ts b/FrontAdmin/src/API/AbonaronMatricula.ts new file mode 100644 index 00000000..afccc2bc --- /dev/null +++ b/FrontAdmin/src/API/AbonaronMatricula.ts @@ -0,0 +1,34 @@ +import Cookies from 'js-cookie'; + +const fetchAlumnosAbonaronMatricula = async (url: string): Promise => { + try { + const token = Cookies.get('tokennn'); + + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + }); + + if (response.ok) { + const data = await response.json(); + return data; + } else { + throw new Error('Error en la respuesta del servidor'); + } + } catch (error) { + throw new Error('Network error: ' + error); + } +}; + +export const FetchAbonaronMatricula = async (): Promise => { + const url = 'http://localhost:8000/api/alumnos/pagaron-matricula'; + return fetchAlumnosAbonaronMatricula(url); +}; + +export const FetchNoAbonaronMatricula = async (): Promise => { + const url = 'http://localhost:8000/api/alumnos/no-pagaron-matricula'; + return fetchAlumnosAbonaronMatricula(url); +}; \ No newline at end of file diff --git a/FrontAdmin/src/API/AlumnosAbonaronMatricula.ts b/FrontAdmin/src/API/AlumnosAbonaronMatricula.ts new file mode 100644 index 00000000..c1a1aa56 --- /dev/null +++ b/FrontAdmin/src/API/AlumnosAbonaronMatricula.ts @@ -0,0 +1,33 @@ +import Cookies from 'js-cookie'; + +const fetchAlumnosAbonaronMatricula = async (url: string): Promise => { + try { + const token = Cookies.get('tokennn'); + + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + }); + + if (response.ok) { + const data = await response.json(); + return data; + } else { + throw new Error('Error en la respuesta del servidor'); + } + } catch (error) { + throw new Error('Network error: ' + error); + } +}; + +export const FetchAbonaronMatricula = async (cuatrimestre: string, anio: number): Promise => { + const url = `http://localhost:8000/api/alumnos/pagaron-matricula/${cuatrimestre}/${anio}`; + return fetchAlumnosAbonaronMatricula(url); +}; +export const FetchNoAbonaronMatricula = async (cuatrimestre: string, anio: number): Promise => { + const url = `http://localhost:8000/api/alumnos/no-pagaron-matricula/${cuatrimestre}/${anio}`; + return fetchAlumnosAbonaronMatricula(url); +}; diff --git a/FrontAdmin/src/API/AlumnosCompromisoPago.ts b/FrontAdmin/src/API/AlumnosCompromisoPago.ts index 6b767e6c..de54f0b6 100644 --- a/FrontAdmin/src/API/AlumnosCompromisoPago.ts +++ b/FrontAdmin/src/API/AlumnosCompromisoPago.ts @@ -23,12 +23,12 @@ const fetchAlumnosCompromiso = async (url: string): Promise => { } }; -export const FetchFirmantes = async (): Promise => { - const url = 'http://localhost:8000/api/firmantes/alumnos-firmaron-ultimo-compromiso/'; +export const FetchFirmantes = async (cuatrimestre: string, anio: number): Promise => { + const url = `http://localhost:8000/api/alumnos/firmaron-compromiso/${cuatrimestre}/${anio}`; return fetchAlumnosCompromiso(url); }; -export const FetchNoFirmantes = async (): Promise => { - const url = 'http://localhost:8000/api/firmantes/alumnos-no-firmaron-ultimo-compromiso/'; +export const FetchNoFirmantes = async (cuatrimestre: string, anio: number): Promise => { + const url = `http://localhost:8000/api/alumnos/no-firmaron-compromiso/${cuatrimestre}/${anio}`; return fetchAlumnosCompromiso(url); -}; +}; \ No newline at end of file diff --git a/FrontAdmin/src/API/AlumnosPendienteFirma.ts b/FrontAdmin/src/API/AlumnosPendienteFirma.ts new file mode 100644 index 00000000..8aa48c01 --- /dev/null +++ b/FrontAdmin/src/API/AlumnosPendienteFirma.ts @@ -0,0 +1,27 @@ +import Cookies from 'js-cookie'; + +export const FetchPendientesFirma = async () => { + try { + const token = Cookies.get('tokennn'); + + const response = await fetch( + `http://localhost:8000/api/estadisticas/firmas_pendientes/`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + } + ); + + if (response.ok) { + const data = await response.json(); + return data; + } else { + throw new Error('Error en la respuesta del servidor'); + } + } catch (error) { + throw new Error('Network error: ' + error); + } +}; \ No newline at end of file diff --git a/FrontAdmin/src/API/EstadoCuentaAlumno.ts b/FrontAdmin/src/API/EstadoCuentaAlumno.ts index 394181f7..962ca163 100644 --- a/FrontAdmin/src/API/EstadoCuentaAlumno.ts +++ b/FrontAdmin/src/API/EstadoCuentaAlumno.ts @@ -1,10 +1,10 @@ import Cookies from 'js-cookie'; -export const FetchEstadoCuenta = async (dni: number) => { +export const FetchEstadoCuenta = async (dni: number, limit: number, offset: number) => { try { const token = Cookies.get('tokennn'); - const response = await fetch(`http://localhost:8000/api/cuotas/alumno/${dni}/`, { + const response = await fetch(`http://localhost:8000/api/cuotas/alumno/${dni}?limit=${limit}&offset=${offset}`, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -14,7 +14,7 @@ export const FetchEstadoCuenta = async (dni: number) => { if (response.ok) { const data = await response.json(); - return data.results; + return data; } else { throw new Error('Error en la respuesta del servidor'); } diff --git a/FrontAdmin/src/API/Inhabilitaciones.ts b/FrontAdmin/src/API/Inhabilitaciones.ts new file mode 100644 index 00000000..583e33e1 --- /dev/null +++ b/FrontAdmin/src/API/Inhabilitaciones.ts @@ -0,0 +1,69 @@ +import Cookies from 'js-cookie'; + +export const getInhabilitaciones = async (limit: number, offset: number) => { + try { + const token = Cookies.get('tokennn'); + const response = await fetch(`http://localhost:8000/api/alumnos/inhabilitados?limit=${limit}&offset=${offset}` , { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + }); + + if (response.ok) { + const data = await response.json(); + return data; + } else { + throw new Error('Error en la respuesta del servidor'); + } + } catch (error) { + throw new Error('Network error: ' + error); + } +}; + + +export const getAlumnosaInhabilitar = async () => { + try { + const token = Cookies.get('tokennn'); + const response = await fetch(`http://localhost:8000/api/alumnos/alumnos-a-inhabilitar` , { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + }); + + if (response.ok) { + const data = await response.json(); + return data; + } else { + throw new Error('Error en la respuesta del servidor'); + } + } catch (error) { + throw new Error('Network error: ' + error); + } + +}; + +export const alumnosaHabilitar = async () => { + const token = Cookies.get('tokennn'); + const response = await fetch('http://localhost:8000/api/alumnos/alumnos-a-habilitar', { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + } + }); + if (response.ok) { + const data = await response.json(); + return data; + } else { + const errorData = await response.json(); + throw new Error( + `Error en la respuesta del servidor: ${errorData.message}` + ); + } +} + + diff --git a/FrontAdmin/src/API/Login.ts b/FrontAdmin/src/API/Login.ts index 70d5e184..9ba288ad 100644 --- a/FrontAdmin/src/API/Login.ts +++ b/FrontAdmin/src/API/Login.ts @@ -1,38 +1,37 @@ import Cookies from 'js-cookie'; -const URL = import.meta.env.VITE_URL_DEV; -export const FetchLogin = async (password: string, account: string) => { - try { - const response = await fetch(`http://localhost:8000/api/auth/login/`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ email: account ,password }), - }); - if (response.ok) { - const data = await response.json(); - console.log(data); - const roles = data.user.groups[0]; - localStorage.setItem('userRol', JSON.stringify(roles)); - - Cookies.set('tokennn', data.access); - Cookies.set('dni', data.user.dni); - Cookies.set('refresh_token', data.refresh); - Cookies.set('access_expiration', data.access_expiration); - Cookies.set('refresh_expiration', data.refresh_expiration); - Cookies.set('full_name', data.user.full_name); +export const FetchLogin = async ( legajo: string, contrasenia: string,) => { + try { + const response = await fetch(`http://localhost:8000/api/sysacad/login/`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({legajo ,contrasenia }), + }); - return data; - } else { - const errorResponse = await response.json(); - throw new Error( - JSON.stringify(errorResponse) - ); + if (response.ok) { + const data = await response.json(); + const roles = data.user.groups[0]; + localStorage.setItem('userRol', JSON.stringify(roles)); + Cookies.set('tokennn', data.access); + Cookies.set('dni', data.user.dni); + Cookies.set('cuil', data.user.cuil); + Cookies.set('refresh_token', data.refresh); + Cookies.set('access_expiration', data.access_expiration); + Cookies.set('refresh_expiration', data.refresh_expiration); + Cookies.set('full_name', data.user.full_name); + + return data; + } else { + const errorResponse = await response.json(); + throw new Error( + JSON.stringify(errorResponse) + ); + } + } catch (error: any) { + throw new Error('' + error); } - } catch (error: any) { - throw new Error('' + error); } -}; diff --git a/FrontAdmin/src/API/Montos.ts b/FrontAdmin/src/API/Montos.ts index 0cba8307..86583563 100644 --- a/FrontAdmin/src/API/Montos.ts +++ b/FrontAdmin/src/API/Montos.ts @@ -18,7 +18,6 @@ export const FetchMontos = async (offset: number, limit: number) => { if (response.ok) { const data = await response.json(); - console.log(data); return data; } else { throw new Error('Error en la respuesta del servidor'); @@ -84,3 +83,28 @@ export const loadPDF = async (id :string,file: File) => { throw new Error('Network error: ' + JSON.stringify(error)); } }; + +export const deleteCompromiso = async (id: number) => { + try { + const token = Cookies.get('tokennn'); + + const response = await fetch(`http://localhost:8000/api/compromisos/${id}/`, { + method: 'DELETE', + headers: { + Authorization: `Bearer ${token}`, + }, + }); + + if (response.ok) { + const data = await response.json(); + return data; + } else { + const errorResponse = await response.json(); + throw new Error( + 'Error en la respuesta del servidor: ' + JSON.stringify(errorResponse) + ); + } + } catch (error) { + throw new Error('Network error: ' + error); + } +} \ No newline at end of file diff --git a/FrontAdmin/src/API/Pagos.ts b/FrontAdmin/src/API/Pagos.ts new file mode 100644 index 00000000..c86991a8 --- /dev/null +++ b/FrontAdmin/src/API/Pagos.ts @@ -0,0 +1,49 @@ +import Cookies from 'js-cookie'; + +export const GetPagos = async (inicio?: string, fin?: string) => { + + const token = Cookies.get('tokennn'); + const url = `http://localhost:8000/api/estadisticas/pagos_mes?end_date=${fin}&start_date=${inicio}`; + + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}`, + } + }); + + if (response.ok) { + const data = await response.json(); + return data; + } else { + const errorData = await response.json(); + throw new Error( + `Error en la respuesta del servidor: ${errorData.message}` + ); + } +}; + +export const GetDeuda = async () => { + + const token = Cookies.get('tokennn'); + const url = `http://localhost:8000/api/estadisticas/cuotas_vencidas/`; + + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}`, + } + }); + + if (response.ok) { + const data = await response.json(); + return data; + } else { + const errorData = await response.json(); + throw new Error( + `Error en la respuesta del servidor: ${errorData.message}` + ); + } + }; diff --git a/FrontAdmin/src/API/TareasProgramadas.ts b/FrontAdmin/src/API/TareasProgramadas.ts new file mode 100644 index 00000000..2a946cd1 --- /dev/null +++ b/FrontAdmin/src/API/TareasProgramadas.ts @@ -0,0 +1,82 @@ +import Cookies from 'js-cookie'; + + +export const actualizarpagos = async () => { + const token = Cookies.get('tokennn'); + const response = await fetch('http://localhost:8000/api/pagos/actualizar-pagos', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + } + }); + if (response.ok) { + const data = await response.json(); + return data; + } else { + const errorData = await response.json(); + throw new Error( + `Error en la respuesta del servidor: ${errorData.message}` + ); + } +}; + +export const actualizarinhabilitaciones = async () => { + const token = Cookies.get('tokennn'); + const response = await fetch('http://localhost:8000/api/alumnos/actualizar-inhabiliciones', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + } + }); + if (response.ok) { + const data = await response.json(); + return data; + } else { + const errorData = await response.json(); + throw new Error( + `Error en la respuesta del servidor: ${errorData.message}` + ); + } +}; + +export const actualizarmaterias = async () => { + const token = Cookies.get('tokennn'); + const response = await fetch('http://localhost:8000/api/materias/actualizar-materias', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + } + }); + if (response.ok) { + const data = await response.json(); + return data; + } else { + const errorData = await response.json(); + throw new Error( + `Error en la respuesta del servidor: ${errorData.message}` + ); + } +}; + +export const actualizarcuotas = async () => { + const token = Cookies.get('tokennn'); + const response = await fetch('http://localhost:8000/api/cuotas/actualizar-cuotas', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + } + }); + if (response.ok) { + const data = await response.json(); + return data; + } else { + const errorData = await response.json(); + throw new Error( + `Error en la respuesta del servidor: ${errorData.message}` + ); + } +}; diff --git a/FrontAdmin/src/App.tsx b/FrontAdmin/src/App.tsx index bfc1201e..8aef5f75 100644 --- a/FrontAdmin/src/App.tsx +++ b/FrontAdmin/src/App.tsx @@ -13,7 +13,7 @@ function App() { }, []); const { isAuthenticated, rolUser } = useAuth(); - console.log(isAuthenticated, rolUser); + const isAdmin = rolUser.includes('staff') || rolUser.includes('Administradores'); const isAlumno = rolUser.includes('Alumno'); diff --git a/FrontAdmin/src/Context.tsx b/FrontAdmin/src/Context.tsx index 4f4a3772..9c1a29a0 100644 --- a/FrontAdmin/src/Context.tsx +++ b/FrontAdmin/src/Context.tsx @@ -1,7 +1,7 @@ import { createContext, useState, ReactNode, useContext, useEffect } from 'react'; import Cookies from 'js-cookie'; import { FetchLogin } from './API/Login'; -const URL= import.meta.env.VITE_URL_DEV; + interface AuthContextType { isAuthenticated: boolean; @@ -26,12 +26,13 @@ const AuthProvider = ({ children }: { children: ReactNode }) => { const refreshToken = async () => { const refresh = Cookies.get('refresh_token'); if (!refresh) { + onLogout(); return; } try { - const response = await fetch(`${URL}/users/token/refresh/`, { + const response = await fetch(`http://localhost:8000/api/auth/token/refresh/`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -40,19 +41,20 @@ const AuthProvider = ({ children }: { children: ReactNode }) => { }); if (response.ok) { - console.log('Token refreshed'); + const data = await response.json(); - console.log(data); + Cookies.set('tokennn', data.access); Cookies.set('refresh_token', data.refresh); Cookies.set('access_expiration', data.access_expiration); Cookies.set('refresh_expiration', data.refresh_expiration); TokenRefresh(data.access_expiration); } else { + onLogout(); } } catch (error) { - console.error('Error refreshing token:', error); + onLogout(); } }; @@ -67,9 +69,9 @@ const AuthProvider = ({ children }: { children: ReactNode }) => { } }; - const onLogin = async (password: string, account: string) => { + const onLogin = async (legajo: string, contrasenia: string) => { try { - await FetchLogin(password, account); + await FetchLogin(legajo, contrasenia); setRolUser(JSON.parse(localStorage.getItem('userRol') || '[]')); setIsAuthenticated(true); @@ -90,7 +92,7 @@ const AuthProvider = ({ children }: { children: ReactNode }) => { }; const onLogout = () => { - console.log('logout'); + // Verificar y eliminar cookies const cookiesToRemove = [ @@ -106,9 +108,9 @@ const AuthProvider = ({ children }: { children: ReactNode }) => { cookiesToRemove.forEach(cookie => { if (Cookies.get(cookie)) { Cookies.remove(cookie, { path: '/', domain: window.location.hostname }); - console.log(`Cookie ${cookie} eliminada`); + } else { - console.log(`Cookie ${cookie} no encontrada`); + } }); diff --git a/FrontAdmin/src/components/Header/HeaderContent.tsx b/FrontAdmin/src/components/Header/HeaderContent.tsx index 48c20698..6bfc2048 100644 --- a/FrontAdmin/src/components/Header/HeaderContent.tsx +++ b/FrontAdmin/src/components/Header/HeaderContent.tsx @@ -10,6 +10,8 @@ import { Box, Text, useDisclosure, + Avatar, + useBreakpointValue } from '@chakra-ui/react'; import imgLogo from '../icons/Logos TUP_Mesa de trabajo 1.png'; import logoUser from '../icons/logo-user.png'; @@ -17,31 +19,36 @@ import { FiMenu } from 'react-icons/fi'; import { useAuth } from '../../Context'; import Cookies from 'js-cookie'; import Perfil from '../Modal/Perfil'; -import Contraseña from '../Modal/Contraseña'; export function HeaderContent({ onOpen }: { onOpen: any }) { const { onLogout } = useAuth(); - const user = Cookies.get('full_name'); - // Perfil + const user = Cookies.get('full_name') || ''; + + function formatUserName(fullName: string): string { + const parts = fullName.trim().split(','); + if (parts.length === 2) { + const lastName = parts[0].trim(); + const firstName = parts[1].trim(); + return `${firstName}, ${lastName}`; + } + return fullName.trim(); + } + + // Definir el ancho de la caja de SubMenuContent según el tamaño de la pantalla + const isMobile = useBreakpointValue({ base: true, xl: false }); + + // Perfil const { isOpen: isOpen1, onOpen: onOpen1, onClose: onClose1, } = useDisclosure(); - // Contraseña - const { - isOpen: isOpen2, - onOpen: onOpen2, - onClose: onClose2, - } = useDisclosure(); - const handleConfirmar = () => { - console.log('confirmar'); + // TODO: Implementar la lógica de confirmar } - return ( - - {user} - - + + {user} + + Ver Perfil - Cambiar Contraseña onLogout()}>Cerrar sesión @@ -90,10 +99,6 @@ export function HeaderContent({ onOpen }: { onOpen: any }) { onClose={onClose1} confirmar={handleConfirmar} /> - ); } diff --git "a/FrontAdmin/src/components/Modal/Contrase\303\261a.tsx" "b/FrontAdmin/src/components/Modal/Contrase\303\261a.tsx" deleted file mode 100644 index d203e82e..00000000 --- "a/FrontAdmin/src/components/Modal/Contrase\303\261a.tsx" +++ /dev/null @@ -1,132 +0,0 @@ -import {Button, Flex, Modal, ModalBody, ModalCloseButton, ModalContent, Text, ModalFooter, ModalHeader, ModalOverlay, Input, FormControl, FormLabel, IconButton, InputGroup, InputRightElement, FormErrorMessage} from '@chakra-ui/react'; -import { FetchDetalleAlumno } from '../../API/DetalleAlumno'; -import { useEffect, useState } from 'react'; -import Cookies from 'js-cookie'; -import React from 'react'; - -interface ModalComponentProps { - isOpen: boolean; - onClose: () => void; -}; - -export default function Contraseña({ isOpen, onClose }: ModalComponentProps) { - - - const [data, setData] = useState([]); - const [Contraseña, setContraseña] = useState(''); - const [Contraseña2, setContraseña2] = useState(''); - const [show, setShow] = React.useState(false) - const handleClick = () => setShow(!show) - const [show2, setShow2] = React.useState(false) - const handleClick2 = () => setShow2(!show2) - const [error, setError] = useState(''); - - - useEffect (() => { - setContraseña(''); - setContraseña2(''); - setError(''); - }, [isOpen]); - - const handleContraseñaChange = (e: React.ChangeEvent) => { - setContraseña(e.target.value); - }; - - const handleContraseña2Change = (e: React.ChangeEvent) => { - setContraseña2(e.target.value); - }; - - const handleConfirmar = () => { - if (Contraseña !== Contraseña2) { - setError('Las contraseñas no coinciden'); - return; - }; - const fetchCambiarContraseña = async () => { - try { - const response = await fetch(`http://localhost:8000/api/auth/password/change/`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${Cookies.get('tokennn')}`, - }, - body: JSON.stringify({ - new_password1: Contraseña, - new_password2: Contraseña2, - }), - }); - if (response.ok) { - onClose(); - } else { - setError('Error al cambiar la contraseña'); - } - } catch (error) { - console.error('Error:', error); - } - }; - fetchCambiarContraseña(); - onClose(); - }; - - return ( - - - - Cambiar Contraseña - - - - - - - - - - - - - - - - - {error && {error}} - - - - - - - - - - ); -} diff --git a/FrontAdmin/src/components/Modal/Perfil.tsx b/FrontAdmin/src/components/Modal/Perfil.tsx index 4f6a4726..948cc54c 100644 --- a/FrontAdmin/src/components/Modal/Perfil.tsx +++ b/FrontAdmin/src/components/Modal/Perfil.tsx @@ -1,6 +1,6 @@ -import {Button, Flex, Modal, ModalBody, ModalCloseButton, ModalContent, Text, ModalFooter, ModalHeader, ModalOverlay, Input, FormControl, FormLabel, IconButton} from '@chakra-ui/react'; +import { Button, Flex, Modal, ModalBody, ModalCloseButton, ModalContent, Text, ModalFooter, ModalHeader, ModalOverlay, Input, FormControl, FormLabel, IconButton, Avatar } from '@chakra-ui/react'; import { HiOutlineUserCircle } from "react-icons/hi"; -import {EditIcon} from '@chakra-ui/icons'; +import { EditIcon } from '@chakra-ui/icons'; import { FetchDetalleAlumno } from '../../API/DetalleAlumno'; import { useEffect, useState } from 'react'; import Cookies from 'js-cookie'; @@ -13,7 +13,8 @@ interface ModalComponentProps { export default function Perfil({ isOpen, onClose, confirmar }: ModalComponentProps) { - const handleconfirmar = () => { + const handleconfirmar = async () => { + await actualizarDatos(); confirmar(); onClose(); }; @@ -24,13 +25,13 @@ export default function Perfil({ isOpen, onClose, confirmar }: ModalComponentPro const [isEmailEditable, setIsEmailEditable] = useState(false); const [isTelefonoEditable, setIsTelefonoEditable] = useState(false); - useEffect (() => { + useEffect(() => { const fetchDetalleAlumno = async () => { try { const dni = Cookies.get('dni'); const data = await FetchDetalleAlumno(parseInt(dni!)); setData(data); - setEmail(data.email); + setEmail(data.email); setTelefono(data.telefono); } catch (error) { console.log(error); @@ -39,7 +40,7 @@ export default function Perfil({ isOpen, onClose, confirmar }: ModalComponentPro fetchDetalleAlumno(); setIsEmailEditable(false); setIsTelefonoEditable(false); - + }, [isOpen]); const handleEmailChange = (e: any) => { @@ -48,6 +49,41 @@ export default function Perfil({ isOpen, onClose, confirmar }: ModalComponentPro const handleTelefonoChange = (e: any) => { setTelefono(e.target.value); + }; + + const actualizarDatos = async () => { + try { + const dni = Cookies.get('dni'); + const token = Cookies.get('tokennn'); + const response = await fetch(`http://localhost:8000/api/alumnos/${dni}/`, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({ + + telefono: telefono + }), + }); + + if (!response.ok) { + throw new Error('Error al actualizar los datos'); + } + } catch (error) { + console.error('Error al actualizar los datos:', error); + } + }; + + + function formatUserName(fullName: string): string { + const parts = fullName.trim().split(','); + if (parts.length === 2) { + const lastName = parts[0].trim(); + const firstName = parts[1].trim(); + return `${firstName}, ${lastName}`; + } + return fullName.trim(); } return ( @@ -58,74 +94,67 @@ export default function Perfil({ isOpen, onClose, confirmar }: ModalComponentPro - - < HiOutlineUserCircle size={120} /> - - { (data.full_name)} - { new Intl.NumberFormat('es-Es').format(data.dni)} - {data.legajo} + + + + + {data.full_name} + {new Intl.NumberFormat('es-Es').format(data.dni)} + {data.legajo} + - - - - - Email: - - - } - variant={'light'} - borderRadius={3} - color={isEmailEditable ? 'gray.500' : 'black'} - ml={1} onClick={() => setIsEmailEditable(!isEmailEditable)} aria-label={''}> - + + + + Email: + + + + - - - Telefono: - - - } - variant={'light'} - borderRadius={3} - color={isTelefonoEditable ? 'gray.500' : 'black'} - ml={1} onClick={() => setIsTelefonoEditable(!isTelefonoEditable)} aria-label={''}> - + + Telefono: + + + + - - - + + diff --git a/FrontAdmin/src/components/NavBar/SidebarContent.tsx b/FrontAdmin/src/components/NavBar/SidebarContent.tsx index 91e0fd48..2d44b88d 100644 --- a/FrontAdmin/src/components/NavBar/SidebarContent.tsx +++ b/FrontAdmin/src/components/NavBar/SidebarContent.tsx @@ -29,6 +29,8 @@ export function SidebarContent({ onClose, LINK_ITEMS, ...rest }: SidebarProps) { borderRight="1px" borderColor="gray.300" w={{ base: 'full', md: '100px' }} + background='white' + zIndex='10' pos="fixed" h="100%" {...rest} diff --git a/FrontAdmin/src/components/Pages-Alumnos/CompromisoDePago.tsx b/FrontAdmin/src/components/Pages-Alumnos/CompromisoDePago.tsx index 6406dffd..57d9b2b2 100644 --- a/FrontAdmin/src/components/Pages-Alumnos/CompromisoDePago.tsx +++ b/FrontAdmin/src/components/Pages-Alumnos/CompromisoDePago.tsx @@ -1,40 +1,50 @@ import React from "react"; import { - Container, - Box, - Text, - VStack, - Table, - Thead, - Tbody, - Tr, - Th, - Td, - IconButton, - Flex, - Skeleton, - TableContainer, - Icon, - Button + Container, + Box, + Text, + VStack, + Table, + Thead, + Tbody, + Tr, + Th, + Td, + IconButton, + Flex, + Skeleton, + TableContainer, + Icon, + Button, + Alert, + AlertIcon, + useBreakpointValue, } from '@chakra-ui/react'; import { DownloadIcon, ViewIcon } from '@chakra-ui/icons'; import { FetchCompromisos, FetchUltimoCompromiso, FirmarCompromiso } from "../../API-Alumnos/Compromiso"; -import {useEffect, useState} from 'react'; -import {formatoFechaISOaDDMMAAAA} from "../../utils/general"; +import { FetchGetCuotas } from "../../API-Alumnos/Pagos"; +import { useEffect, useState } from 'react'; +import { formatoFechaISOaDDMMAAAA } from "../../utils/general"; import { useToast } from "../Toast/useToast"; import Cookies from 'js-cookie'; +import { set } from "date-fns"; export default function CompromisoDePago() { -const [compromisos, setCompromisos] = useState([]); -const [ultimoCompromiso, setUltimoCompromiso] = useState(false); -const [ultimo, setUltimo] = useState([]); -const [refresh, setRefresh] = useState(false); -const [pdfUrl, setPdfUrl] = useState(null); -const showToast = useToast(); + const [compromisos, setCompromisos] = useState([]); + const [ultimoCompromiso, setUltimoCompromiso] = useState(false); + const [adeuda, setAdeuda] = useState(false); + const [ultimo, setUltimo] = useState([]); + const [refresh, setRefresh] = useState(false); + const [pdfUrl, setPdfUrl] = useState(null); + const [error, setError] = useState(true); + const showToast = useToast(); -const handleViewPdf = async (url: string) => { + const isMobile = useBreakpointValue({ base: true, md: false }); + + const handleViewPdf = async (url: string) => { try { + setError(false); const token = Cookies.get('tokennn'); const response = await fetch(url, { headers: { @@ -47,124 +57,173 @@ const handleViewPdf = async (url: string) => { setPdfUrl(pdfUrl); } catch (error) { console.error('Error al obtener el PDF:', error); + }finally{ + setError(true); } }; -useEffect(() => { + useEffect(() => { const fetchCompromisos = async () => { - try{ - const data = await FetchCompromisos(); + try { + const dni = Number(Cookies.get('dni')); + const data = await FetchCompromisos(dni); setCompromisos(data.results); - console.log(data); - } catch (error) { - console.log(error) - } + + } catch (error) { + console.log(error) + } }; fetchCompromisos(); const fetchUltimoCompromiso = async () => { - try { - const data = await FetchUltimoCompromiso(); - handleViewPdf(data.archivo_pdf_url); - } catch (error) { - console.log(error); - } + try { + const data = await FetchUltimoCompromiso(); + handleViewPdf(data.archivo_pdf_url); + } catch (error) { + console.log(error); + } } fetchUltimoCompromiso(); -}, [refresh]); + const fetchAdeuda = async () => { + try { + const dni = Number(Cookies.get('dni')); + const data = await FetchGetCuotas(dni); + if (data.length > 0) { + setAdeuda(true); + } + } catch (error) { + console.log(error); + } + } + fetchAdeuda(); + }, [refresh]); -useEffect(() => { + useEffect(() => { if (compromisos.length > 0) { - setUltimo(compromisos[compromisos.length - 1]); + setUltimo(compromisos[compromisos.length - 1]); } -}, [compromisos]); + }, [compromisos]); -useEffect(() => { + useEffect(() => { if (ultimo) { - console.log(ultimo); - if (ultimo.firmo_ultimo_compromiso === true) { - setUltimoCompromiso(true); - } + if (ultimo.firmo_ultimo_compromiso === true) { + setUltimoCompromiso(true); + } } -}, [ultimo]); - - + }, [ultimo]); -const handleFirmar = async () => { + const handleFirmar = async () => { try { - await FirmarCompromiso(); - setRefresh(!refresh); - showToast('Exito', 'Compromiso de pago firmado con exito', 'success'); + await FirmarCompromiso(); + setRefresh(!refresh); + showToast('Éxito', 'Compromiso de pago firmado con éxito', 'success'); } catch (error) { - console.log(error); + console.log(error); } -}; - + }; -return ( + return ( + + {ultimoCompromiso && ( + + + + El compromiso de pago del periodo actual ya se encuentra firmado ({formatoFechaISOaDDMMAAAA(ultimo.fecha_firmado)}). + + + )} + {!ultimoCompromiso && adeuda && ( + + + + Aún adeuda cuotas. No puede firmar el compromiso de pago. + + + )} + + + + {pdfUrl ? ( +