From 83e80073850a8cb1cd118d954267d4ee25221109 Mon Sep 17 00:00:00 2001 From: "Cristian O." <84862634+Criser2013@users.noreply.github.com> Date: Fri, 6 Mar 2026 21:00:38 +0000 Subject: [PATCH 1/3] =?UTF-8?q?Mejora=20de=20c=C3=B3digo=20en=20las=20func?= =?UTF-8?q?iones=20del=20contexto=20de=20credenciales.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/contexts/CredencialesContext.jsx | 196 +++++++++++---------------- 1 file changed, 76 insertions(+), 120 deletions(-) diff --git a/src/contexts/CredencialesContext.jsx b/src/contexts/CredencialesContext.jsx index b1710a7..ea90527 100644 --- a/src/contexts/CredencialesContext.jsx +++ b/src/contexts/CredencialesContext.jsx @@ -2,7 +2,7 @@ import { createContext, useState, useContext, useEffect } from "react"; import { initializeApp } from "firebase/app"; import { getAuth } from "firebase/auth"; import { getFirestore } from "firebase/firestore"; -import { AES_KEY, API_URL, ENTORNO } from "../../constants"; +import { AES_KEY, API_URL } from "../../constants"; import Cookies from "js-cookie"; import { AES, enc } from "crypto-js"; @@ -10,12 +10,12 @@ export const credencialesContext = createContext(); /** * Otorga acceso al contexto de credenciales de la aplicación. - * @returns React.Context + * @returns {import("react").Context} */ export const useCredenciales = () => { const context = useContext(credencialesContext); if (!context) { - console.log("Error creando el contexto."); + console.log("Error creando el contexto de credenciales."); } return context; }; @@ -28,77 +28,52 @@ export const useCredenciales = () => { */ export function CredencialesProvider({ children }) { - const [credsInfo, setCredsInfo] = useState({ - apiKey: null, authDomain: null, projectId: null, - storeBucket: null, messagingSenderId: null, - appId: null, measurementId: null, app: null, - db: null, auth: null, reCAPTCHA: null - }); - + const [claveRecaptcha, setClaveRecaptcha] = useState(null); + const [instanciaFirestore, setInstanciaFirestore] = useState(null); + const [instanciaFirebase, setInstanciaFirebase] = useState(null); + const [instanciaFirebaseAuth, setInstanciaFirebaseAuth] = useState(null); const [scopesDrive, setScopesDrive] = useState(null); /** - * Inicializa Firebase dependiendo del entorno de ejecución. + * Inicializa Firebase si las credenciales de la aplicación están en las cookies de sesión. */ useEffect(() => { - // Entorno de desarrollo solo frontend const res = cargarCredsCookies(); - if (ENTORNO == "0" && !res) { - inicializarFirebase({ - apiKey: import.meta.env.VITE_API_KEY, - authDomain: import.meta.env.VITE_AUTH_DOMAIN, - projectId: import.meta.env.VITE_PROJECT_ID, - storeBucket: import.meta.env.VITE_STORE_BUCKET, - messagingSenderId: import.meta.env.VITE_MESSAGING_SENDER_ID, - appId: import.meta.env.VITE_APP_ID, - measurementId: import.meta.env.VITE_MEASUREMENT_ID, - scopes: import.meta.env.VITE_DRIVE_SCOPES.split(","), - reCAPTCHA: import.meta.env.VITE_RECAPTCHA_SITE_KEY - }); - - setScopesDrive(import.meta.env.VITE_DRIVE_SCOPES.split(",")); - } else if (!res) { - // Producción o entorno de pruebas con backend funcionando + if (!res) { obtenerCredenciales(); } }, []); + /** + * Carga las credenciales de la aplicación desde el servidor. + * @returns {boolean} Resultado de la operación de carga de credenciales. + */ + const cargarCredenciales = async () => { + try { + const pet = await fetch(`$${API_URL}/credenciales`, { method: "GET" }); + if (pet.status == 200 && pet.ok) { + const json = await pet.json(); + inicializarFirebase(json, json.driveScopes, json.reCAPTCHA); + } + return pet.ok; + } catch (error) { + console.log("Error al cargar las credenciales: ", error); + return false; + } + }; + /** * Realiza una petición al servidor para obtener las credenciales de Firebase. * Reintenta hasta 4 veces en caso de error. Si tiene éxito, inicializa Firebase con las credenciales obtenidas. */ const obtenerCredenciales = async () => { - let intentos = 0; - let parar = false; - while (intentos < 4 && !parar) { - try { - const res = await fetch(`${API_URL}/credenciales`, { - method: "GET" - }); - - if (res.status == 200 && res.ok) { - parar = true; - const json = await res.json(); - inicializarFirebase({ - apiKey: json.apiKey, - authDomain: json.authDomain, - projectId: json.projectId, - storeBucket: json.storageBucket, - messagingSenderId: json.messagingSenderId, - appId: json.appId, - measurementId: json.measurementId, - scopes: json.driveScopes, - reCAPTCHA: json.reCAPTCHA - }); - - setScopesDrive(json.data.scopes); - } else { - intentos++; - } - } catch { - intentos++; - }; + for (let i = 0; i < 4; i++) { + const res = await cargarCredenciales(); + + if (res) { + break; + } } }; @@ -106,96 +81,77 @@ export function CredencialesProvider({ children }) { * Inicializa Firebase con la información de credenciales proporcionada. * @param {JSON} credsInfo */ - const inicializarFirebase = (credsInfo) => { - if (credsInfo != undefined && credsInfo != null) { - const scopes = credsInfo.scopes; - - delete credsInfo.scopes; + const inicializarFirebase = (credsFirebase, scopesDrive, tokenRecaptcha) => { + delete credsFirebase.driveScopes; + delete credsFirebase.reCAPTCHA; - const app = initializeApp(credsInfo); - const db = getFirestore(app); - const auth = getAuth(app); + const app = initializeApp(credsFirebase); + const db = getFirestore(app); + const auth = getAuth(app); - almacenarCredenciales(credsInfo, scopes); + almacenarCredenciales(credsFirebase, scopesDrive, tokenRecaptcha); - setScopesDrive(scopes); - setCredsInfo((x) => ({ ...x, app: app, db: db, auth: auth, reCAPTCHA: credsInfo.reCAPTCHA })); - } + setInstanciaFirebase(app); + setInstanciaFirestore(db); + setInstanciaFirebaseAuth(auth); + setClaveRecaptcha(tokenRecaptcha); + setScopesDrive(scopesDrive); }; /** - * Almacena las dredenciales de los servicios de la aplicación en una cookie de sesión. + * Almacena las dredenciales de los servicios de la aplicación en las cookies de sesión. * @param {JSON} firebaseCreds - Credenciales de Firebase. - * @param {Array} scopes - Scopes de acceso a Google Drive. + * @param {Array} scopesDrive - Scopes de acceso a Google Drive. + * @param {string} tokenRecaptcha - Clave del cliente de reCAPTCHA. */ - const almacenarCredenciales = (firebaseCreds, scopes) => { - const json = AES.encrypt(JSON.stringify(firebaseCreds), AES_KEY).toString(); - Cookies.set("session-credentials", json); - Cookies.set("session-drive-scopes", scopes); + const almacenarCredenciales = (credsFirebase, scopesDrive, tokenRecaptcha) => { + const txtCreds = JSON.stringify(credsFirebase); + const encCreds = AES.encrypt(txtCreds, AES_KEY).toString(); + const encCaptcha = AES.encrypt(tokenRecaptcha, AES_KEY).toString(); + + Cookies.set("session-credentials", encCreds); + Cookies.set("session-recaptcha", encCaptcha); + Cookies.set("session-drive-scopes", scopesDrive); }; /** - * Carga las credenciales de los servicios desde las cookies. - * Devuelve el resultado de las operación. - * @returns {Boolean} + * Carga las credenciales de los servicios desde las cookies. + * @returns {boolean} Resultado de la operación de carga de las credenciales desde las cookies. */ const cargarCredsCookies = () => { const firebaseCreds = Cookies.get("session-credentials"); - const driveScopes = Cookies.get("session-drive-scopes"); - let res = (firebaseCreds != undefined && firebaseCreds != null); + const tokenRecaptcha = Cookies.get("session-recaptcha"); + const scopesDrive = Cookies.get("session-drive-scopes"); + let res = [firebaseCreds, tokenRecaptcha, scopesDrive].every((x) => x != undefined && x != null); - if (res && (driveScopes != undefined && driveScopes != null)) { - const creds = JSON.parse(AES.decrypt(firebaseCreds, AES_KEY).toString(enc.Utf8)); + if (res) { + const txtCreds = AES.decrypt(firebaseCreds, AES_KEY).toString(enc.Utf8); + const tokenCaptcha = AES.decrypt(tokenRecaptcha, AES_KEY).toString(enc.Utf8); + const creds = JSON.parse(txtCreds); - setScopesDrive(driveScopes.split(",")); - setCredsInfo((x) => ({ ...x, ...creds })); + setScopesDrive(scopesDrive.split(",")); + setClaveRecaptcha(tokenCaptcha); - creds.scopes = driveScopes.split(","); - - inicializarFirebase(creds); - - res &= true; + inicializarFirebase(creds, scopesDrive.split(","), tokenCaptcha); } return res; }; /** - * Obtiene la instancia de Firestore. - * @returns {Object} - */ - const obtenerInstanciaDB = () => { - return credsInfo.db; - }; - - /** - * Obtiene la instancia de autenticación de Firebase. - * @returns {Object} - */ - const obtenerInstanciaAuth = () => { - return credsInfo.auth; - }; - - /** - * Verificar si las credenciales de Firebase están cargadas. - * @returns {Boolean} - */ - const verSiCredsFirebaseEstancargadas = () => { - return credsInfo.app != null && credsInfo.db != null && credsInfo.auth != null; - }; - - /** - * Obtiene la clave de reCAPTCHA de las credenciales. - * @returns {String} + * Verificar si las instancias de los servicios de Firebase fueron + * inicializadas correctamente. + * @returns {boolean} */ - const obtenerRecaptcha = () => { - return credsInfo.reCAPTCHA; + const verFirebaseIniciado = () => { + return [instanciaFirebase, instanciaFirestore, instanciaFirebaseAuth].every((x) => x != null); }; return ( {children} From 71efd3df618c4c114e4a90aa6ddda56324eb1e83 Mon Sep 17 00:00:00 2001 From: "Cristian O." <84862634+Criser2013@users.noreply.github.com> Date: Fri, 6 Mar 2026 21:56:24 +0000 Subject: [PATCH 2/3] =?UTF-8?q?Ajustes=20en=20la=20aplicaci=C3=B3n=20con?= =?UTF-8?q?=20el=20nuevo=20contexto=20de=20credenciales.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 28 ++++++++++--------- src/components/forms/FormDiagnostico.jsx | 9 ++---- src/components/layout/NavBar.jsx | 2 +- src/components/layout/Sidebar.jsx | 1 - src/components/menu/MenuAdministrador.jsx | 9 +++--- src/components/menu/MenuUsuario.jsx | 9 +++--- src/contexts/AuthContext.jsx | 7 ++--- src/contexts/CredencialesContext.jsx | 17 ++++++----- src/pages/auth/IniciarSesionPage.jsx | 11 ++------ src/pages/diagnosticos/VerDiagnosticoPage.jsx | 16 +++++------ .../diagnosticos/VerDiagnosticosPage.jsx | 19 ++++++------- src/pages/usuarios/VerUsuariosPage.jsx | 5 ++-- 12 files changed, 61 insertions(+), 72 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 03aedc2..7d0b577 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -21,7 +21,7 @@ export default function App() { const auth = useAuth(); const { t } = useTranslation(); const navegacion = useNavegacion(); - const credenciales = useCredenciales(); + const { firebaseAuth, scopesDrive } = useCredenciales(); const [modal, setModal] = useState({ mostrar: false, mensaje: "" }); @@ -30,22 +30,24 @@ export default function App() { }); /** - * Actualiza las instancia de Firebase y permisos de Drive - * cuando se cargan las credenciales. - */ + * Configura el formato en que se mostrarán las fechas de la aplicación según + * el idioma seleccionado por el usuario. + */ useEffect(() => { import("dayjs/locale/es").then(() => { const idioma = localStorage.getItem("i18nextLng"); - if (idioma != null) { - dayjs.locale(idioma); - } else { - dayjs.locale("es"); - } + dayjs.locale(idioma != null ? idioma : "es"); }); - auth.setAuth(credenciales.obtenerInstanciaAuth()); - auth.setDb(credenciales.obtenerInstanciaDB()); - auth.setScopes(credenciales.scopesDrive); - }, [credenciales]); + }); + + /** + * Actualiza las instancia de Firebase y permisos de Drive + * cuando se cargan las credenciales. + */ + useEffect(() => { + auth.setAuth(firebaseAuth); + auth.setScopes(scopesDrive); + }, [firebaseAuth, scopesDrive]); useEffect(() => { if (auth.autenticado != null && !auth.autenticado) { diff --git a/src/components/forms/FormDiagnostico.jsx b/src/components/forms/FormDiagnostico.jsx index 6d8c097..fdd16aa 100644 --- a/src/components/forms/FormDiagnostico.jsx +++ b/src/components/forms/FormDiagnostico.jsx @@ -54,7 +54,7 @@ const valoresPredet = { export default function FormDiagnostico({ listadoPestanas, tituloHeader, pacientes = [], esDiagPacientes = false, manejadorRecarga = null }) { const auth = useAuth(); const navegacion = useNavegacion(); - const credenciales = useCredenciales(); + const { reCAPTCHA, firestore } = useCredenciales(); const { t } = useTranslation(); const navigate = useNavigate(); const [desactivarBtn, setDesactivarBtn] = useState(true); @@ -69,9 +69,6 @@ export default function FormDiagnostico({ listadoPestanas, tituloHeader, pacient return 3; } }, [navegacion.dispositivoMovil, navegacion.ancho, navegacion.orientacion]); - const reCAPTCHAApi = useMemo(() => { - return credenciales.obtenerRecaptcha(); - }, [credenciales.obtenerRecaptcha]); const [cargandoBtn, setCargandoBtn] = useState(false); const [antTema, setAntTema] = useState(navegacion.tema); const CAPTCHA = useRef(null); @@ -225,7 +222,7 @@ export default function FormDiagnostico({ listadoPestanas, tituloHeader, pacient fecha: Timestamp.now(), validado: 2, paciente: paciente, lime: resultado.lime }; - const res = await cambiarDiagnostico(id, uid, instancia, credenciales.obtenerInstanciaDB()); + const res = await cambiarDiagnostico(id, uid, instancia, firestore); if (res.success) { const url = esDiagPacientes ? "/diagnostico-paciente" : "/diagnostico-anonimo"; @@ -610,7 +607,7 @@ export default function FormDiagnostico({ listadoPestanas, tituloHeader, pacient diff --git a/src/components/layout/NavBar.jsx b/src/components/layout/NavBar.jsx index c39f759..87abcf6 100644 --- a/src/components/layout/NavBar.jsx +++ b/src/components/layout/NavBar.jsx @@ -9,7 +9,7 @@ import MenuOpenIcon from "@mui/icons-material/MenuOpen"; import AccountCircleIcon from "@mui/icons-material/AccountCircle"; import BtnTema from "../layout/BtnTema"; import LogoutIcon from '@mui/icons-material/Logout'; -import { CODIGO_ADMIN, URL_MANUAL_ADMIN, URL_MANUAL_USUARIO } from "../../../constants"; +import { URL_MANUAL_ADMIN, URL_MANUAL_USUARIO } from "../../../constants"; import ArticleIcon from '@mui/icons-material/Article'; import SwitchLabel from "../tabs/SwitchLabel"; import { useTranslation } from "react-i18next"; diff --git a/src/components/layout/Sidebar.jsx b/src/components/layout/Sidebar.jsx index 6c93389..eab4554 100644 --- a/src/components/layout/Sidebar.jsx +++ b/src/components/layout/Sidebar.jsx @@ -7,7 +7,6 @@ import { detAbrirMenu } from "../../utils/Responsividad"; import { useAuth } from "../../contexts/AuthContext"; import PeopleIcon from '@mui/icons-material/People'; import { useMemo } from "react"; -import { CODIGO_ADMIN } from "../../../constants"; import { useTranslation } from "react-i18next"; /** diff --git a/src/components/menu/MenuAdministrador.jsx b/src/components/menu/MenuAdministrador.jsx index 34532ed..9adbf07 100644 --- a/src/components/menu/MenuAdministrador.jsx +++ b/src/components/menu/MenuAdministrador.jsx @@ -24,7 +24,7 @@ import { useTranslation } from "react-i18next"; */ export default function MenuAdministrador() { const auth = useAuth(); - const credenciales = useCredenciales(); + const { firestore } = useCredenciales(); const navegacion = useNavegacion(); const { t } = useTranslation(); const [cargando, setCargando] = useState(true); @@ -46,7 +46,6 @@ export default function MenuAdministrador() { return 4; } }, [navegacion]); - const DB = useMemo(() => credenciales.obtenerInstanciaDB(), [credenciales]); const diagnosticosMesActual = useMemo(() => obtenerDatosMesActual(datosDiagnosticos, fechaActual, navegacion.idioma) , [datosDiagnosticos, fechaActual, navegacion.idioma]); const usuariosMesActual = useMemo(() => obtenerDatosMesActual(datosUsuarios, fechaActual, navegacion.idioma) @@ -95,12 +94,12 @@ export default function MenuAdministrador() { useEffect(() => { const { user } = auth.authInfo; - if (user != null && DB != null) { + if (user != null && firestore != null) { cargarUsuarios(user.accessToken).then((x) => { - cargarDiagnosticos(DB, x.map((x) => x.uid)); + cargarDiagnosticos(firestore, x.map((x) => x.uid)); }); } - }, [auth.authInfo, DB]); + }, [auth.authInfo, firestore]); /** * Actualiza el gráfico de barras con los datos de diagnósticos y usuarios. diff --git a/src/components/menu/MenuUsuario.jsx b/src/components/menu/MenuUsuario.jsx index f731b86..732192d 100644 --- a/src/components/menu/MenuUsuario.jsx +++ b/src/components/menu/MenuUsuario.jsx @@ -26,7 +26,7 @@ import { AES_KEY } from "../../../constants"; */ export default function MenuUsuario() { const auth = useAuth(); - const credenciales = useCredenciales(); + const { firestore } = useCredenciales(); const navegacion = useNavegacion(); const { t } = useTranslation(); const drive = useDrive(); @@ -42,7 +42,6 @@ export default function MenuUsuario() { const { orientacion, dispositivoMovil, ancho } = navegacion; return (dispositivoMovil && orientacion == "vertical") || (!dispositivoMovil && (ancho <= 700)) ? 1 : 2; }, [navegacion]); - const DB = useMemo(() => credenciales.obtenerInstanciaDB(), [credenciales.obtenerInstanciaDB]); const diagnosticosMesActual = useMemo(() => obtenerDatosMesActual(datosDiagnosticos, fechaActual, navegacion.idioma) , [datosDiagnosticos, fechaActual, navegacion.idioma]); const pacientesMesActual = useMemo(() => obtenerDatosMesActual(datosPacientes, fechaActual, navegacion.idioma) @@ -89,12 +88,12 @@ export default function MenuUsuario() { const descargar = sessionStorage.getItem("descargando-drive"); const { uid } = auth.authInfo; - if (uid != null && drive.token != null && (descargar == null || descargar == "false") && DB != null) { + if (uid != null && drive.token != null && (descargar == null || descargar == "false") && firestore != null) { sessionStorage.setItem("descargando-drive", "true"); cargarPacientes(); - cargarDiagnosticos(uid, DB); + cargarDiagnosticos(uid, firestore); } - }, [auth.authInfo, drive.token, DB]); + }, [auth.authInfo, drive.token, firestore]); /** * Actualiza el gráfico de barras con los datos de diagnósticos y usuarios. diff --git a/src/contexts/AuthContext.jsx b/src/contexts/AuthContext.jsx index 57c679b..8bc9394 100644 --- a/src/contexts/AuthContext.jsx +++ b/src/contexts/AuthContext.jsx @@ -33,7 +33,6 @@ export function AuthProvider({ children }) { // Instancia de autenticación de Firebase const [auth, setAuth] = useState(null); // Instancia de la base de datos de Firebase - const [db, setDb] = useState(null); const [tokenDrive, setTokenDrive] = useState(null); // Información del usuario autenticado const [authInfo, setAuthInfo] = useState({ @@ -77,10 +76,10 @@ export function AuthProvider({ children }) { */ useEffect(() => { const ruta = window.location.pathname == "/"; - if (auth != null && scopes != null && db != null && ruta) { + if (auth != null && scopes != null && ruta) { setCargando(false); } - }, [auth, db, scopes]); + }, [auth, scopes]); /** * Recupera la sesión si el usuario no la ha cerrado. También refresca los tokens @@ -429,7 +428,7 @@ export function AuthProvider({ children }) { return ( diff --git a/src/contexts/CredencialesContext.jsx b/src/contexts/CredencialesContext.jsx index ea90527..aa6f73a 100644 --- a/src/contexts/CredencialesContext.jsx +++ b/src/contexts/CredencialesContext.jsx @@ -1,10 +1,10 @@ -import { createContext, useState, useContext, useEffect } from "react"; import { initializeApp } from "firebase/app"; import { getAuth } from "firebase/auth"; import { getFirestore } from "firebase/firestore"; +import { createContext, useState, useContext, useEffect } from "react"; import { AES_KEY, API_URL } from "../../constants"; -import Cookies from "js-cookie"; import { AES, enc } from "crypto-js"; +import Cookies from "js-cookie"; export const credencialesContext = createContext(); @@ -27,7 +27,6 @@ export const useCredenciales = () => { * @returns {JSX.Element} */ export function CredencialesProvider({ children }) { - const [claveRecaptcha, setClaveRecaptcha] = useState(null); const [instanciaFirestore, setInstanciaFirestore] = useState(null); const [instanciaFirebase, setInstanciaFirebase] = useState(null); @@ -51,7 +50,7 @@ export function CredencialesProvider({ children }) { */ const cargarCredenciales = async () => { try { - const pet = await fetch(`$${API_URL}/credenciales`, { method: "GET" }); + const pet = await fetch(`${API_URL}/credenciales`, { method: "GET" }); if (pet.status == 200 && pet.ok) { const json = await pet.json(); inicializarFirebase(json, json.driveScopes, json.reCAPTCHA); @@ -65,21 +64,25 @@ export function CredencialesProvider({ children }) { /** * Realiza una petición al servidor para obtener las credenciales de Firebase. - * Reintenta hasta 4 veces en caso de error. Si tiene éxito, inicializa Firebase con las credenciales obtenidas. + * Reintenta hasta 5 veces en caso de error. Si tiene éxito, inicializa Firebase con las credenciales obtenidas. */ const obtenerCredenciales = async () => { - for (let i = 0; i < 4; i++) { + for (let i = 0; i < 5; i++) { const res = await cargarCredenciales(); if (res) { break; } + + setTimeout(null, 500); } }; /** * Inicializa Firebase con la información de credenciales proporcionada. - * @param {JSON} credsInfo + * @param {JSON} credsFirebase - Credenciales de Firebase. + * @param {Array[string]} scopesDrive - Scopes de acceso a Google Drive. + * @param {string} tokenRecaptcha - Clave del cliente de reCAPTCHA. */ const inicializarFirebase = (credsFirebase, scopesDrive, tokenRecaptcha) => { delete credsFirebase.driveScopes; diff --git a/src/pages/auth/IniciarSesionPage.jsx b/src/pages/auth/IniciarSesionPage.jsx index 1ee20da..b94317d 100644 --- a/src/pages/auth/IniciarSesionPage.jsx +++ b/src/pages/auth/IniciarSesionPage.jsx @@ -28,7 +28,7 @@ export default function IniciarSesionPage() { const auth = useAuth(); const navigate = useNavigate(); const navegacion = useNavegacion(); - const credenciales = useCredenciales(); + const { firebase, reCAPTCHA } = useCredenciales(); const CAPTCHA = useRef(null); const { t } = useTranslation(); const [desactivarBtn, setDesactivarBtn] = useState(true); @@ -39,9 +39,7 @@ export default function IniciarSesionPage() { const [modal, setModal] = useState({ mensaje: "", mostrar: false }); - const cargandoAuth = useMemo(() => { - return auth.cargando || !credenciales.verSiCredsFirebaseEstancargadas(); - }, [auth.cargando, credenciales.verSiCredsFirebaseEstancargadas]); + const cargandoAuth = useMemo(() => (auth.cargando || !firebase), [auth.cargando, firebase]); const width = useMemo(() => { const { dispositivoMovil, orientacion, ancho } = navegacion; if (!dispositivoMovil && (ancho >= 1020)) { @@ -66,9 +64,6 @@ export default function IniciarSesionPage() { const fondoImg = useMemo(() => { return temaCaptcha === "light" ? fondoClaro : fondoOscuro; }, [temaCaptcha]); - const reCAPTCHAApi = useMemo(() => { - return credenciales.obtenerRecaptcha(); - }, [credenciales.obtenerRecaptcha]); /** * Verifica la autenticación del usuario y redirige si ya está autenticado. @@ -228,7 +223,7 @@ export default function IniciarSesionPage() { diff --git a/src/pages/diagnosticos/VerDiagnosticoPage.jsx b/src/pages/diagnosticos/VerDiagnosticoPage.jsx index 08ec907..cbff916 100644 --- a/src/pages/diagnosticos/VerDiagnosticoPage.jsx +++ b/src/pages/diagnosticos/VerDiagnosticoPage.jsx @@ -39,7 +39,7 @@ export default function VerDiagnosticoPage() { const auth = useAuth(); const drive = useDrive(); const { t } = useTranslation(); - const credenciales = useCredenciales(); + const { firestore } = useCredenciales(); const navegacion = useNavegacion(); const navigate = useNavigate(); const location = useLocation(); @@ -128,7 +128,6 @@ export default function VerDiagnosticoPage() { } }, [admin, persona.nombre, datos.personales.id, navegacion.idioma]); const id = useMemo(() => params.get("id"), [params]); - const DB = useMemo(() => credenciales.obtenerInstanciaDB(), [credenciales.obtenerInstanciaDB]); /** * Carga el token de sesión y comienza a descargar el archivo de pacientes. @@ -148,10 +147,10 @@ export default function VerDiagnosticoPage() { */ useEffect(() => { const exp = (!admin || persona.nombre == ""); - if (admin != null && DB != null && exp) { + if (admin != null && firestore != null && exp) { cargarDatosDiagnostico(auth.authInfo.user.accessToken); } - }, [drive.descargando, auth.authInfo.user, admin, persona, DB]); + }, [drive.descargando, auth.authInfo.user, admin, persona, firestore]); /** * Cuando el admin cambia el modo usuario se fuerza a recargar la página. @@ -200,7 +199,7 @@ export default function VerDiagnosticoPage() { */ const cargarDatosDiagnostico = async (token) => { const uid = id.split(/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}-/); - const datos = await verDiagnostico(uid[1], id, DB); + const datos = await verDiagnostico(uid[1], id, firestore); if (datos.success && datos.data != []) { setDiagOriginal({ ...datos.data }); @@ -216,7 +215,7 @@ export default function VerDiagnosticoPage() { } preprocesarDiag(datos.data); - } else if (DB != null && !datos.success) { + } else if (firestore != null && !datos.success) { volverPestanaAnterior(); } }; @@ -372,7 +371,7 @@ export default function VerDiagnosticoPage() { */ const eliminarDiagnostico = async () => { const uid = id.split(/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}-/); - const res = await eliminarDiagnosticos(uid[1], id, DB); + const res = await eliminarDiagnosticos(uid[1], id, firestore); if (res.success) { navegacion.setPaginaAnterior("/diagnosticos"); @@ -393,14 +392,13 @@ export default function VerDiagnosticoPage() { const validarDiagnostico = async () => { setCargando(true); setErrorDiagnostico(false); - const DB = credenciales.obtenerInstanciaDB(); const { id, medico } = diagOriginal; const aux = { ...diagOriginal }; delete aux.id; delete aux.medico; - const res = await cambiarDiagnostico(id, medico, { ...aux, validado: diagnostico }, DB); + const res = await cambiarDiagnostico(id, medico, { ...aux, validado: diagnostico }, firestore); if (res.success) { window.history.replaceState({}, ''); diff --git a/src/pages/diagnosticos/VerDiagnosticosPage.jsx b/src/pages/diagnosticos/VerDiagnosticosPage.jsx index 03e8d9a..5c469d6 100644 --- a/src/pages/diagnosticos/VerDiagnosticosPage.jsx +++ b/src/pages/diagnosticos/VerDiagnosticosPage.jsx @@ -38,7 +38,7 @@ export default function VerDiagnosticosPage() { const { t } = useTranslation(); const navigate = useNavigate(); const navegacion = useNavegacion(); - const credenciales = useCredenciales(); + const { firestore } = useCredenciales(); const [cargando, setCargando] = useState(true); const [modal, setModal] = useState({ mostrar: false, titulo: "", mensaje: "", icono: null @@ -57,7 +57,6 @@ export default function VerDiagnosticosPage() { const [preprocesar, setPreprocesar] = useState(false); const [guardarDrive, setGuardarDrive] = useState(false); const admin = useMemo(() => auth.authInfo.rolVisible, [auth.authInfo.rolVisible]); - const DB = useMemo(() => credenciales.obtenerInstanciaDB(), [credenciales.obtenerInstanciaDB]); const camposVariables = useMemo(() => !admin ? [ { id: "id", label: "ID", componente: null, ordenable: true }, { id: "nombre", label: t("txtPaciente"), componente: null, ordenable: true }, @@ -149,11 +148,11 @@ export default function VerDiagnosticosPage() { const descargar = sessionStorage.getItem("descargando-drive"); const exp = (descargar == null || descargar == "false"); - if (admin != null && uid != null && DB != null && drive.token != null && exp && !archivoDescargado) { + if (admin != null && uid != null && firestore != null && drive.token != null && exp && !archivoDescargado) { sessionStorage.setItem("descargando-drive", "true"); - manejadorRecargar(drive.token, uid, admin, DB); + manejadorRecargar(drive.token, uid, admin, firestore); } - }, [auth.authInfo.uid, drive.token, admin, DB, archivoDescargado]); + }, [auth.authInfo.uid, drive.token, admin, firestore, archivoDescargado]); useEffect(() => { document.title = admin ? t("txtDatosRecolectados") : t("txtHistorialDiagnosticos"); @@ -202,7 +201,7 @@ export default function VerDiagnosticosPage() { const credencial = (admin || token == null) ? auth.authInfo.user.accessToken : token; const uid = (usuario == null) ? auth.authInfo.uid : usuario; const rolUsuario = (cargo == null) ? admin : cargo; - const BD = (db == null) ? DB : db; + const BD = (db == null) ? firestore : db; if (!cargando) { setCargando(true); @@ -386,7 +385,7 @@ export default function VerDiagnosticosPage() { diagnosticos.forEach((x, i) => { const uid = x.split(/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}-/); - peticiones[i] = eliminarDiagnosticos(uid[1], x, DB); + peticiones[i] = eliminarDiagnosticos(uid[1], x, firestore); }); for (let i = 0; i < peticiones.length; i++) { @@ -396,7 +395,7 @@ export default function VerDiagnosticosPage() { if (peticiones.every((x) => x.success)) { setCargando(true); const usuarios = await cargarPacientes(auth.authInfo.user.accessToken); - cargarDiagnosticos(auth.authInfo.uid, admin, DB, usuarios); + cargarDiagnosticos(auth.authInfo.uid, admin, firestore, usuarios); } else { setModoModal(0); setActivar2Btn(false); @@ -433,11 +432,11 @@ export default function VerDiagnosticosPage() { delete diagnostico.id; delete diagnostico.medico; - const res = await cambiarDiagnostico(id, medico, { ...diagnostico, validado: validar }, DB); + const res = await cambiarDiagnostico(id, medico, { ...diagnostico, validado: validar }, firestore); if (res.success) { const pacientes = await cargarPacientes(auth.authInfo.user.accessToken); - cargarDiagnosticos(auth.authInfo.uid, admin, DB, pacientes); + cargarDiagnosticos(auth.authInfo.uid, admin, firestore, pacientes); } else { setActivar2Btn(false); setModoModal(0); diff --git a/src/pages/usuarios/VerUsuariosPage.jsx b/src/pages/usuarios/VerUsuariosPage.jsx index 2f84b12..f220c46 100644 --- a/src/pages/usuarios/VerUsuariosPage.jsx +++ b/src/pages/usuarios/VerUsuariosPage.jsx @@ -29,7 +29,7 @@ import { Trans, useTranslation } from "react-i18next"; export default function VerUsuariosPage() { const auth = useAuth(); const navigate = useNavigate(); - const credenciales = useCredenciales(); + const { firestore } = useCredenciales(); const navegacion = useNavegacion(); const { t } = useTranslation(); const listadoPestanas = useMemo(() => [{ @@ -108,7 +108,6 @@ export default function VerUsuariosPage() { } }, [navegacion]); const admin = useMemo(() => auth.authInfo.rolVisible, [auth.authInfo.rolVisible]); - const DB = useMemo(() => credenciales.obtenerInstanciaDB(), [credenciales.obtenerInstanciaDB]); /** * Coloca el título de la página. @@ -164,7 +163,7 @@ export default function VerUsuariosPage() { * @param {Array[string]} usuarios - Lista de UID de los médicos. */ const cargarDiagnosticos = async (usuarios) => { - const res = await verDiagnosticos(DB, usuarios); + const res = await verDiagnosticos(firestore, usuarios); if (!res.success) { setDiagnosticos([]); setModoModal(2); From a53e35cceda641b09844875c444f8b8d1621e33f Mon Sep 17 00:00:00 2001 From: "Cristian O." <84862634+Criser2013@users.noreply.github.com> Date: Fri, 6 Mar 2026 22:02:24 +0000 Subject: [PATCH 3/3] =?UTF-8?q?Documentaci=C3=B3n=20actualizada.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 21 --------------------- constants.js | 1 - 2 files changed, 22 deletions(-) diff --git a/README.md b/README.md index 8c9065e..cfe4a86 100644 --- a/README.md +++ b/README.md @@ -36,27 +36,6 @@ VITE_URL_CONDICIONES= # URL al documento que contiene los términ VITE_AES_KEY= # Clave AES utilizada para encriptar las credenciales ``` -## Ejecución del frontend sin backend - -Es posible ejecutar la aplicación sin necesidad de tener activo el servidor backend, para esto se debe proveer las credenciales de Firebase y los permisos de drive en un archivo `.env`. Se provee el archivo `.env.example` como plantilla. - -Para iniciar el servidor de esta forma, establezca la siguiente variables de entorno: `VITE_ENTORNO=0`. Esto puede ser realizado a través del comando `export VITE_ENTORNO=0` en Linux y `setx VITE_ENTORNO 0` en Windows. - -### Descripción de las variables de entorno - -``` -VITE_API_KEY= # API key del proyecto de Firebase -VITE_AUTH_DOMAIN= # Dominio de autenticación de Firebase -VITE_PROJECT_ID= # ID del proyecto en Firebase -VITE_STORE_BUCKET= # ID del bucket de Firestore -VITE_MESSAGING_SENDER_ID= # ID para envío de mensajes -VITE_APP_ID= # ID de la aplicación de Firebase -VITE_MEASUREMENT_ID= # ID de Google Analytics (métricas) -VITE_DRIVE_SCOPES= # URLs de permisos de Drive requeridos -VITE_ENTORNO= # Número de entorno de ejecución -VITE_RECAPTCHA_SITE_KEY= # Clave de reCAPTCHA para el sitio -``` - ## Dockerfile La imagen generada `Dockerfile` corresponde a una imagen de despliegue, para construirla use el comando: diff --git a/constants.js b/constants.js index 5855849..7a99dfb 100644 --- a/constants.js +++ b/constants.js @@ -1,5 +1,4 @@ export const API_URL = import.meta.env.VITE_API_URL || "http://localhost:5000"; -export const ENTORNO = import.meta.env.VITE_ENTORNO || "0"; // 0: local, 1: production export const DRIVE_API_URL = import.meta.env.VITE_DRIVE_API_URL || "https://www.googleapis.com/drive/v3"; export const DRIVE_UPLOAD_API_URL = import.meta.env.VITE_DRIVE_UPLOAD_API_URL || "https://www.googleapis.com/upload/drive/v3"; export const DRIVE_FILENAME = import.meta.env.VITE_DRIVE_FILENAME || "HADT - Pacientes.xlsx";