diff --git a/cosiap_api/cosiap_api/.env b/cosiap_api/cosiap_api/.env index 1b8c473086c249755da5edce9d772d86374b1358..efd2d313abce2ad842d937242cfe1013cdaab054 100644 --- a/cosiap_api/cosiap_api/.env +++ b/cosiap_api/cosiap_api/.env @@ -14,8 +14,8 @@ DATABASES_DEFAULT_PORT="3306" EMAIL_HOST="sandbox.smtp.mailtrap.io" EMAIL_FROM="cosiap@example.com" -EMAIL_HOST_USER="3b48193365f615" -EMAIL_HOST_PASSWORD="37f89fc1d98f48" +EMAIL_HOST_USER="dab27aa7ffd16a" +EMAIL_HOST_PASSWORD="59d827a27f4eda" EMAIL_PORT="2525" EMAIL_USE_TLS=True diff --git a/cosiap_api/static/css/colores.css b/cosiap_api/static/css/colores.css index 227521458c89ea6c72a0743614bf9d3bd97a3770..0d31fc59d49f60b0aa340d144a28902766e94d5f 100644 --- a/cosiap_api/static/css/colores.css +++ b/cosiap_api/static/css/colores.css @@ -1,57 +1,57 @@ :root { -/* ========================= + /* ========================= Estilos Básicos del Sitio ========================= */ - --principal-mc: rgb(252,226,228); - --principal-c: rgb(245,173,171); - --principal: rgb(226,116,110); - --principal-f: rgb(187,68,51); - --principal-mf: rgb(120,16,5); - - --secundario-mc:#e0e0e0; - --secundario-c: #c0c0c0; - --secundario: #a0a0a0; - --secundario-f: #808080; - --secundario-mf:#606060; - - --texto-general: #676767; - --pagina-fondo: #EEE5E5; - - --exito-f: #8abc94; - --exito: #B9E2C1; - --exito-c: #D5F5E2; - - --error-f: #C7564A; - --error: #E4756F; - --error-c: #E1B2AF; - - --precaucion-f: #d4bf47; - --precaucion: #e4d26f; - --precaucion-c: #f1e7a8; - - --cancelar-f: #B8A9A8; - --cancelar: #DCCBCA; - --cancelar-c: #E9DEDD; - - --informacion-f: #5b9bd5; - --informacion: #85c1e9; - --informacion-c: #cfe2f3; - - --neutral-f: #6c757d; - --neutral: #adb5bd; - --neutral-c: #dee2e6; - - --gris-principal: #b9b4b4; - --gris-0: #f8f8f8; - --gris-1: #efefef; - --gris-2: #e0e0e0; - --gris-3: #c0c0c0; - --gris-4: #a0a0a0; - --gris-5: #808080; - --gris-6: #606060; - --gris-7: #404040; - --gris-8: #202020; - --blanco: #FFFFFF; - --negro: #000000; - -} \ No newline at end of file + --principal-mc: rgb(252, 226, 228); + --principal-c: rgb(245, 173, 171); + --principal: rgb(226, 116, 110); + --principal-f: rgb(187, 68, 51); + --principal-mf: rgb(120, 16, 5); + + --secundario-mc: #e0e0e0; + --secundario-c: #c0c0c0; + --secundario: #a0a0a0; + --secundario-f: #808080; + --secundario-mf: #606060; + + --texto-general: #676767; + --pagina-fondo: #eee5e5; + + --exito-f: #8abc94; + --exito: #b9e2c1; + --exito-c: #d5f5e2; + --exito-btn: #527f18; + + --error-f: #c7564a; + --error: #e4756f; + --error-c: #e1b2af; + + --precaucion-f: #d4bf47; + --precaucion: #e4d26f; + --precaucion-c: #f1e7a8; + + --cancelar-f: #b8a9a8; + --cancelar: #dccbca; + --cancelar-c: #e9dedd; + + --informacion-f: #5b9bd5; + --informacion: #85c1e9; + --informacion-c: #cfe2f3; + + --neutral-f: #6c757d; + --neutral: #adb5bd; + --neutral-c: #dee2e6; + + --gris-principal: #b9b4b4; + --gris-0: #f8f8f8; + --gris-1: #efefef; + --gris-2: #e0e0e0; + --gris-3: #c0c0c0; + --gris-4: #a0a0a0; + --gris-5: #808080; + --gris-6: #606060; + --gris-7: #404040; + --gris-8: #202020; + --blanco: #ffffff; + --negro: #000000; +} diff --git a/cosiap_frontend/src/App.jsx b/cosiap_frontend/src/App.jsx index ce4903609fadf6b14799f082dd1ab2f9de4c4d7a..87450145e3aa1d3a6643719487a59744b131336c 100644 --- a/cosiap_frontend/src/App.jsx +++ b/cosiap_frontend/src/App.jsx @@ -1,93 +1,118 @@ -import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; -import {PaginaHead} from "@/components/common/utility/PaginaHead"; -import {Autenticador} from "@/components/common/utility/Autenticador"; -import { useAutenticacion } from '@/components/common/utility/Autenticador'; +import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom"; +import { PaginaHead } from "@/components/common/utility/PaginaHead"; +import { Autenticador } from "@/components/common/utility/Autenticador"; +import { useAutenticacion } from "@/components/common/utility/Autenticador"; -import {LoginRequiredRoute, IsAdminRequiredRoute, IsLogged} from "@/components/common/utility/LoginRequiredRoute" +import { + LoginRequiredRoute, + IsAdminRequiredRoute, + IsLogged, +} from "@/components/common/utility/LoginRequiredRoute"; import "./App.css"; -import PageLoader from '@/components/common/ui/PageLoader'; +import PageLoader from "@/components/common/ui/PageLoader"; // Importaciones de componentes de autenticacion -import { Login } from '@/components/users/Login/Login'; -import Register from '@/components/users/Register/Register'; -import ResetPassword from '@/components/users/Password/ResetPassword'; -import NoAutorizado from '@/components/users/NoAutorizado'; -import PageNotFound from '@/components/users/PageNotFound'; +import { Login } from "@/components/users/Login/Login"; +import Register from "@/components/users/Register/Register"; +import ResetPassword from "@/components/users/Password/ResetPassword"; +import NoAutorizado from "@/components/users/NoAutorizado"; +import PageNotFound from "@/components/users/PageNotFound"; import Inicio from "@/components/Inicio"; -import { useState } from 'react'; +import { useState } from "react"; // Importaciones de layoutsBase -import LayoutBaseAuthenticator from '@/components/common/layouts/LayoutBaseAuthenticator'; -import LayoutBaseNavigation from '@/components/common/layouts/LayoutBaseNavigation'; - - - +import LayoutBaseAuthenticator from "@/components/common/layouts/LayoutBaseAuthenticator"; +import LayoutBaseNavigation from "@/components/common/layouts/LayoutBaseNavigation"; +import Modalidades from "@/components/modalidades/Modalidades"; function App() { const [viewPageLoader, setViewPageLoader] = useState(false); - return ( + return ( - Sistema de apoyos COZCyT - - + Sistema de apoyos COZCyT + + - { - viewPageLoader && - } - + {viewPageLoader && } + - - + ); } -function RoutesApp( {setViewPageLoader} ){ - const {token, isAdmin} = useAutenticacion(); - console.log(token) +function RoutesApp({ setViewPageLoader }) { + const { token } = useAutenticacion(); + return ( - } /> + + } + /> {/* Rutas públicas */} - {/* Componente del layout */} - }> + {/* Componente del layout */} + }> }> - {/* Componentes hijos del layout autenticador */} - } /> - } /> - } /> + {/* Componentes hijos del layout autenticador */} + } + /> + } + /> + } + /> - - {/* Rutas protegidas */} + + {/* Rutas protegidas */} }> - {/* Componentes del layout de navegación */} + {/* Componentes del layout de navegación */} }> {/* Componentes hijos del layout autenticador */} - + {/* Cualquier usuario puede acceder a estas url */} } /> - } /> + } + /> } /> } /> } /> } /> {/* Solo administradores pueden acceder a estas url */} - }> + + } + > } /> } /> - + } /> } /> - ); } -export default App; \ No newline at end of file +export default App; diff --git a/cosiap_frontend/src/assets/iconsImg/Money.svg b/cosiap_frontend/src/assets/iconsImg/Money.svg new file mode 100644 index 0000000000000000000000000000000000000000..7ca3d6b5c393609fd8b6db169fcd7acbcf1848d6 --- /dev/null +++ b/cosiap_frontend/src/assets/iconsImg/Money.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cosiap_frontend/src/assets/modalidad.png b/cosiap_frontend/src/assets/modalidad.png new file mode 100644 index 0000000000000000000000000000000000000000..61360d679964322b3a6ba500136d3373e363a247 Binary files /dev/null and b/cosiap_frontend/src/assets/modalidad.png differ diff --git a/cosiap_frontend/src/components/common/utility/DocumentInput.jsx b/cosiap_frontend/src/components/common/utility/DocumentInput.jsx new file mode 100644 index 0000000000000000000000000000000000000000..e364644ac0d8f6783fc38f024a0f4a8e174e1e62 --- /dev/null +++ b/cosiap_frontend/src/components/common/utility/DocumentInput.jsx @@ -0,0 +1,22 @@ +export default function DocumentInput({ title, description, children }) { + return ( + <> +
+

+ {/* (Título del documento) */} + {title} +

+
+

+ {/* (Descripción del documento) */} + {description} +

+
+
+ {/* Contenedores extra */} + {children} +
+
+ + ); +} diff --git a/cosiap_frontend/src/components/common/utility/HeaderSection.jsx b/cosiap_frontend/src/components/common/utility/HeaderSection.jsx new file mode 100644 index 0000000000000000000000000000000000000000..a372cca7cd14117220c68f2673c4d2f371e2ea86 --- /dev/null +++ b/cosiap_frontend/src/components/common/utility/HeaderSection.jsx @@ -0,0 +1,13 @@ +export default function HeaderSection({ title }) { + return ( +
+
+
+

+ {title} +

+
+
+
+ ); +} diff --git a/cosiap_frontend/src/components/common/utility/InputFile.jsx b/cosiap_frontend/src/components/common/utility/InputFile.jsx new file mode 100644 index 0000000000000000000000000000000000000000..daf4db1d150682b53fedb1860e4a92dbf37adb99 --- /dev/null +++ b/cosiap_frontend/src/components/common/utility/InputFile.jsx @@ -0,0 +1,15 @@ +export default function InputFile({ titleBtn, descBtn }) { + return ( + + ); +} diff --git a/cosiap_frontend/src/components/common/utility/InputMonto.jsx b/cosiap_frontend/src/components/common/utility/InputMonto.jsx new file mode 100644 index 0000000000000000000000000000000000000000..4c61b9f3401937997129d00014be85e79a171f83 --- /dev/null +++ b/cosiap_frontend/src/components/common/utility/InputMonto.jsx @@ -0,0 +1,21 @@ +export default function InputMonto() { + return ( +
+ +
+ +
+
+ MXN +
+
+ ); +} \ No newline at end of file diff --git a/cosiap_frontend/src/components/common/utility/MainContainer.jsx b/cosiap_frontend/src/components/common/utility/MainContainer.jsx new file mode 100644 index 0000000000000000000000000000000000000000..4774e03649a642d9089827224c6d4b5b9ec6e51a --- /dev/null +++ b/cosiap_frontend/src/components/common/utility/MainContainer.jsx @@ -0,0 +1,17 @@ +export default function MainContainer({ title, children }) { + return ( + <> +
+
+

+ {title} +

+
+
+
+
+ {children} +
+ + ); +} diff --git a/cosiap_frontend/src/components/common/utility/StatusDocument.jsx b/cosiap_frontend/src/components/common/utility/StatusDocument.jsx new file mode 100644 index 0000000000000000000000000000000000000000..19784a6b784b3738719adf8f1374c15681a27fd4 --- /dev/null +++ b/cosiap_frontend/src/components/common/utility/StatusDocument.jsx @@ -0,0 +1,12 @@ +export default function StatusDocument({ title, description }) { + return ( +
+

+ {title} +

+

+ {description} +

+
+ ); +} diff --git a/cosiap_frontend/src/components/modalidades/ListaModalidades.jsx b/cosiap_frontend/src/components/modalidades/ListaModalidades.jsx new file mode 100644 index 0000000000000000000000000000000000000000..318e22a176f50d4c08000b9d01b988c19690f8ab --- /dev/null +++ b/cosiap_frontend/src/components/modalidades/ListaModalidades.jsx @@ -0,0 +1,67 @@ +/* eslint-disable react/jsx-no-comment-textnodes */ +// import { useNavigate } from "react-router-dom"; +import { ModalidadCard } from "@/components/modalidades/ModalidadCard"; +import api from "@/api"; +import { useState, useEffect } from "react"; +import MainContainer from "@/components/common/utility/MainContainer"; + +export default function ListaModalidades({ + setViewPageLoader, + handleModalidadDetail, +}) { + const [modalidades, setModalidades] = useState([]); + + const obtenerModalidades = async () => { + setViewPageLoader(true); + + try { + const response = await api.modalidades.get(); + console.log("Modalidades extraidas"); + console.log(response.data.data); + setModalidades(response.data.data); + } catch (error) { + console.log("No fueron extraidas"); + } + setViewPageLoader(false); + }; + + useEffect(() => { + obtenerModalidades(); + }, []); + + return ( + +
+ {/** Tarjetas para mostrar modalidades disponibles */} + {modalidades.length > 0 ? ( + modalidades.map((item) => { + return ( + +

+
+ +
+
+ ); + }) + ) : ( +

+ No hay modalidades disponibles +

+ )} +
+
+ ); +} diff --git a/cosiap_frontend/src/components/modalidades/Modalidad.jsx b/cosiap_frontend/src/components/modalidades/Modalidad.jsx new file mode 100644 index 0000000000000000000000000000000000000000..988ae4dfa40ab2dce5eaa0a588a80576a77b6d73 --- /dev/null +++ b/cosiap_frontend/src/components/modalidades/Modalidad.jsx @@ -0,0 +1,145 @@ +import DocumentInput from "@/components/common/utility/DocumentInput"; +import HeaderSection from "@/components/common/utility/HeaderSection"; +import StatusDocument from "@/components/common/utility/StatusDocument"; +import InputMonto from "@/components/common/utility/InputMonto"; +import InputFile from "@/components/common/utility/InputFile"; +import api from "@/api"; +import { useEffect, useState } from "react"; + +// eslint-disable-next-line react-refresh/only-export-components +export { useNavigate } from "react-router-dom"; + +export default function Modalidad({ id, setViewPageLoader }) { + const [modalidad, setModalidad] = useState(); + + const obtenerModalidad = async () => { + setViewPageLoader(true); + try { + const response = await api.modalidades.getById(Number(id)); + setModalidad(response.data.data); + console.log("Modalidad extraída con éxito", response); + console.log(response.data); + } catch (error) { + console.error("Modalidad no extraída", error); + } + setViewPageLoader(false); + }; + + useEffect(() => { + obtenerModalidad(); + }, [id]); + + /* Función para mostrar el monto_maximo en formato de pesos MXN */ + const formatCurrency = (amount) => { + return new Intl.NumberFormat("es-MX", { + style: "currency", + currency: "MXN", + }).format(amount); + }; + + return ( + modalidad && ( +
+
+
+ Modalidad +
+
+
+

+ Modalidad: +

+
+

+ {modalidad.nombre} +

+
+
+

+ {modalidad.descripcion} +

+
+
+

+ {formatCurrency(modalidad.monto_maximo)} +

+
+
+
+
+ +
+
+
+ + {/* Campos para subir documentación. */} +
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ + +
+ +
+
+
+
+ + +
+
+ ) + ); +} diff --git a/cosiap_frontend/src/components/modalidades/ModalidadCard.jsx b/cosiap_frontend/src/components/modalidades/ModalidadCard.jsx new file mode 100644 index 0000000000000000000000000000000000000000..b9d4fd2b18a157ee621fd9e28351cb2949b20f53 --- /dev/null +++ b/cosiap_frontend/src/components/modalidades/ModalidadCard.jsx @@ -0,0 +1,60 @@ +export function ModalidadCard({ title, description, monto, image, children }) { + /* Formatear monto con separadores de miles */ + const formatCurrency = (amount) => { + return new Intl.NumberFormat("es-MX", { + style: "currency", + currency: "MXN", + }).format(amount); + }; + + return ( +
+
+
+ Modalidad + {`http://localhost:8000${image}`} +
+
+
+
+
+
+ +
+
+

+ {/* (NOMBRE DE LA MODALIDAD) */} + {title} +

+
+
+
+
+

+ {/* (Descripción de la modalidad) */} + {description} +

+
+

+
+

{formatCurrency(monto)}

+
+ {children} +
+
+
+ ); +} diff --git a/cosiap_frontend/src/components/modalidades/Modalidades.jsx b/cosiap_frontend/src/components/modalidades/Modalidades.jsx new file mode 100644 index 0000000000000000000000000000000000000000..767dbc57eef3556e5480b6e17077209a08a64dc4 --- /dev/null +++ b/cosiap_frontend/src/components/modalidades/Modalidades.jsx @@ -0,0 +1,29 @@ +import ListaModalidades from "@/components/modalidades/ListaModalidades"; +import { useState } from "react"; +import Modalidad from "@/components/modalidades/Modalidad"; + +export default function Modalidades({ setViewPageLoader }) { + const [viewModalidades, setViewModalidades] = useState(true); + const [viewModalidadDetail, setViewModalidadDetail] = useState(false); + const [selectedId, setSelectedId] = useState(null); + + const handleModalidadDetail = (id) => { + setViewModalidades(false); + setViewModalidadDetail(true); + setSelectedId(id); + }; + + return ( + <> + {viewModalidades && ( + + )} + {viewModalidadDetail && selectedId && ( + + )} + + ); +}