From be6e6d1153d84f155ac0b12b7743bc16db5a00bc Mon Sep 17 00:00:00 2001 From: Nika254 Date: Thu, 6 Nov 2025 14:15:06 +0000 Subject: [PATCH 1/9] first --- src/api/routes.py | 104 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 94 insertions(+), 10 deletions(-) diff --git a/src/api/routes.py b/src/api/routes.py index 029589a3a1..b984a8d032 100644 --- a/src/api/routes.py +++ b/src/api/routes.py @@ -1,22 +1,106 @@ -""" -This module takes care of starting the API Server, Loading the DB and Adding the endpoints -""" -from flask import Flask, request, jsonify, url_for, Blueprint +from flask import request, jsonify, Blueprint +import secrets +from datetime import datetime, timedelta, timezone +import jwt +from werkzeug.security import check_password_hash from api.models import db, User -from api.utils import generate_sitemap, APIException +from werkzeug.security import generate_password_hash from flask_cors import CORS -api = Blueprint('api', __name__) -# Allow CORS requests to this API +def token_requerido(f): + def wrapper(*args, **kwargs): + auth = request.headers.get('Authorization') + if not auth or not auth.startswith('Bearer '): + return jsonify({"msg": "Token requerido"}), 401 + token = auth.split(' ')[1] + try: + jwt.decode(token, SECRET_KEY, algorithms=['HS256']) + except Exception: + return jsonify({"msg": "Token inválido"}), 401 + return f(*args, **kwargs) + wrapper.__name__ = f.__name__ + return wrapper + + +SECRET_KEY = "super-secret-key" + +api = Blueprint('api', __name__) CORS(api) +reset_tokens = {} + + +@api.route('/forgot-password', methods=['POST']) +def forgot_password(): + data = request.get_json() + email = data.get('email') + if not email: + return jsonify({"msg": "Falta correo o contraseña"}), 400 + user = User.query.filter_by(email=email).first() + if not user: + return jsonify({"msg": "Usuario no encontrado o no registrado"}), 404 + token = secrets.token_urlsafe(16) + reset_tokens[email] = token + return jsonify({"msg": "Token de recuperacion", "token": token}), 200 + + +@api.route('/reset-password', methods=['POST']) +def reset_password(): + data = request.get_json() + email = data.get('email') + token = data.get('token') + new_password = data.get('new_password') + if not email or not token or not new_password: + return jsonify({"msg": "Faltan datos"}), 400 + if reset_tokens.get(email) != token: + return jsonify({"msg": "Token inválido"}), 401 + user = User.query.filter_by(email=email).first() + if not user: + return jsonify({"msg": "Usuario no encontrado"}), 404 + user.password = generate_password_hash(new_password) + db.session.commit() + reset_tokens.pop(email) + return jsonify({"msg": "Cambio de contraseña"}), 200 + + +@api.route('/login', methods=['POST']) +def login(): + data = request.get_json() + email = data.get('email') + password = data.get('password') + if not email or not password: + return jsonify({"msg": "Falta correo o contraseña"}), 400 + user = User.query.filter_by(email=email).first() + if not user or not check_password_hash(user.password, password): + return jsonify({"msg": "Usuario o contraseña incorrectos"}), 401 + token = jwt.encode({ + 'user_id': user.id, + 'exp': datetime.now(timezone.utc) + timedelta(minutes=15) + }, SECRET_KEY, algorithm="HS256") + return jsonify({"token": token}) + + +@api.route('/register', methods=['POST']) +def register(): + data = request.get_json() + email = data.get('email') + password = data.get('password') + if not email or not password: + return jsonify({"msg": "Falta correo o contraseña"}), 400 + if User.query.filter_by(email=email).first(): + return jsonify({"msg": "El usuario ya existe"}), 400 + hashed_password = generate_password_hash(password) + new_user = User(email=email, password=hashed_password, is_active=True) + db.session.add(new_user) + db.session.commit() + return jsonify({"msg": "Usuario registrado exitosamente"}), 201 + @api.route('/hello', methods=['POST', 'GET']) +@token_requerido def handle_hello(): - response_body = { - "message": "Hello! I'm a message that came from the backend, check the network tab on the google inspector and you will see the GET request" + "message": "¡Hola! Acceso autorizado al backend." } - return jsonify(response_body), 200 From a77734248cb95c0d96609402f2f51f99b7a8c138 Mon Sep 17 00:00:00 2001 From: Mnrubn <126007823+Mnrubn@users.noreply.github.com> Date: Fri, 7 Nov 2025 19:36:45 +0000 Subject: [PATCH 2/9] commit --- package-lock.json | 56 ++++++++++--------------- src/front/components/Footer.jsx | 8 +--- src/front/components/Form.jsx | 74 +++++++++++++++++++++++++++++++++ src/front/index.css | 13 ++++++ src/front/pages/Login.jsx | 43 +++++++++++++++++++ src/front/pages/Register.jsx | 39 +++++++++++++++++ src/front/routes.jsx | 4 ++ 7 files changed, 196 insertions(+), 41 deletions(-) create mode 100644 src/front/components/Form.jsx create mode 100644 src/front/pages/Login.jsx create mode 100644 src/front/pages/Register.jsx diff --git a/package-lock.json b/package-lock.json index 8d43d98ab7..44f1ece2dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,6 +73,7 @@ "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -884,7 +885,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -997,14 +997,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/node": { - "version": "16.11.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", - "integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", @@ -1018,6 +1010,7 @@ "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1066,6 +1059,7 @@ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1294,6 +1288,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -1312,8 +1307,7 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/call-bind": { "version": "1.0.8", @@ -1797,6 +1791,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -3486,6 +3481,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -3498,6 +3494,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -3921,7 +3918,6 @@ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "optional": true, - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -3933,7 +3929,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "optional": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4081,7 +4076,6 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, - "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -4100,8 +4094,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/text-table": { "version": "0.2.0", @@ -4278,6 +4271,7 @@ "integrity": "sha512-qK9W4xjgD3gXbC0NmdNFFnVFLMWSNiR3swj957yutwzzN16xF/E7nmtAyp1rT9hviDroQANjE4HK3H4WqWdFtw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.18.10", "postcss": "^8.4.27", @@ -4500,6 +4494,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", "dev": true, + "peer": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -4950,7 +4945,6 @@ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, "optional": true, - "peer": true, "requires": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -5044,14 +5038,6 @@ "@babel/types": "^7.20.7" } }, - "@types/node": { - "version": "16.11.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", - "integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==", - "dev": true, - "optional": true, - "peer": true - }, "@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", @@ -5063,6 +5049,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", "dev": true, + "peer": true, "requires": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -5098,7 +5085,8 @@ "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "dev": true + "dev": true, + "peer": true }, "acorn-jsx": { "version": "5.3.2", @@ -5245,6 +5233,7 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, + "peer": true, "requires": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -5257,8 +5246,7 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "call-bind": { "version": "1.0.8", @@ -5600,6 +5588,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, + "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -6702,6 +6691,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "peer": true, "requires": { "loose-envify": "^1.1.0" } @@ -6710,6 +6700,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "peer": true, "requires": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -6988,7 +6979,6 @@ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "optional": true, - "peer": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -6999,8 +6989,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "optional": true, - "peer": true + "optional": true } } }, @@ -7100,7 +7089,6 @@ "integrity": "sha512-GWANVlPM/ZfYzuPHjq0nxT+EbOEDDN3Jwhwdg1D8TU8oSkktp8w64Uq4auuGLxFSoNTRDncTq2hQHX1Ld9KHkA==", "dev": true, "optional": true, - "peer": true, "requires": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -7113,8 +7101,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "optional": true, - "peer": true + "optional": true } } }, @@ -7228,6 +7215,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.9.tgz", "integrity": "sha512-qK9W4xjgD3gXbC0NmdNFFnVFLMWSNiR3swj957yutwzzN16xF/E7nmtAyp1rT9hviDroQANjE4HK3H4WqWdFtw==", "dev": true, + "peer": true, "requires": { "esbuild": "^0.18.10", "fsevents": "~2.3.2", diff --git a/src/front/components/Footer.jsx b/src/front/components/Footer.jsx index f06302dbd2..8361fa8a93 100644 --- a/src/front/components/Footer.jsx +++ b/src/front/components/Footer.jsx @@ -1,11 +1,5 @@ export const Footer = () => ( ); diff --git a/src/front/components/Form.jsx b/src/front/components/Form.jsx new file mode 100644 index 0000000000..a9b2241ea4 --- /dev/null +++ b/src/front/components/Form.jsx @@ -0,0 +1,74 @@ +import React, { useState, useEffect } from "react"; + +const Form = ({ mode, onSubmit, successMessage }) => { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [errorMsn, setErrorMsn] = useState(null); + + useEffect(() => { + if (successMessage) { + setErrorMsn(successMessage); + } + }, [successMessage]); + + const handleSubmit = async (e) => { + e.preventDefault(); + try { + await onSubmit({ email, password, setErrorMsn }); + setEmail(""); + setPassword(""); + } catch (error) { + setErrorMsn(error.message || "Error"); + console.error(error.message || "Error"); + } + }; + + return ( +
+
+
+

+ {mode === "register" ? "Registrarse" : "Iniciar Sesión"} +

+
+
+ + setEmail(e.target.value)} + required + /> +
+ +
+ + setPassword(e.target.value)} + required + /> +
+ + {errorMsn && ( +
+ {errorMsn} +
+ )} + + +
+
+
+
+ ); +}; + +export default Form; \ No newline at end of file diff --git a/src/front/index.css b/src/front/index.css index e69de29bb2..bd8850d3a3 100644 --- a/src/front/index.css +++ b/src/front/index.css @@ -0,0 +1,13 @@ +body { + min-height: 100vh; + margin: 0; + background: linear-gradient(180deg, #1e91ed 10%, #7f00b2 90%); + background-repeat: no-repeat; + background-attachment: fixed; +} + +.button{ + background-color:#1e91ed; + color: white; + +} diff --git a/src/front/pages/Login.jsx b/src/front/pages/Login.jsx new file mode 100644 index 0000000000..b447e1aab1 --- /dev/null +++ b/src/front/pages/Login.jsx @@ -0,0 +1,43 @@ +import React from "react"; +import { useNavigate, useLocation } from "react-router-dom"; +import Form from "../components/Form.jsx"; + +const Login = () => { + const navigate = useNavigate(); + const location = useLocation(); + const successMessage = location.state?.successMessage; + + const handleLogin = async ({ email, password, setErrorMsn }) => { + setErrorMsn(null); + const backendUrl = import.meta.env.VITE_BACKEND_URL; + + try { + const response = await fetch(`${backendUrl}/login`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ email, password }), + }); + + const data = await response.json(); + + if (!response.ok) { + setErrorMsn(data.msg || "Error en el inicio de sesión"); + console.error(data.msg || "Error en el inicio de sesión"); + return; + } + + localStorage.setItem("token", data.token); + + navigate("/private", { + state: { successMessage: "Inicio de sesión exitoso" }, + }); + } catch (error) { + setErrorMsn("Error al conectar con el servidor"); + console.error("Error al conectar con el servidor", error); + } + }; + + return
; +}; + +export default Login; \ No newline at end of file diff --git a/src/front/pages/Register.jsx b/src/front/pages/Register.jsx new file mode 100644 index 0000000000..9ea28f2b55 --- /dev/null +++ b/src/front/pages/Register.jsx @@ -0,0 +1,39 @@ +import React from "react"; +import { useNavigate } from "react-router-dom"; +import Form from "../components/Form.jsx"; + +const Register = () => { + const navigate = useNavigate(); + + const handleSignup = async ({ email, password, setErrorMsn }) => { + setErrorMsn(null); + const backendUrl = import.meta.env.VITE_BACKEND_URL; + + try { + const response = await fetch(`${backendUrl}/register`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ email, password }), + }); + + const data = await response.json(); + + if (!response.ok) { + setErrorMsn(data.msg || "Error en el registro"); + console.error(data.msg || "Error en el registro"); + return; + } + + navigate("/login", { + state: { successMessage: "Registro exitoso. Ahora puedes iniciar sesión." }, + }); + } catch (error) { + setErrorMsn("Error al conectar con el servidor"); + console.error("Error al conectar con el servidor", error); + } + }; + + return ; +}; + +export default Register; \ No newline at end of file diff --git a/src/front/routes.jsx b/src/front/routes.jsx index 0557df6141..02ff2c3aad 100644 --- a/src/front/routes.jsx +++ b/src/front/routes.jsx @@ -9,6 +9,8 @@ import { Layout } from "./pages/Layout"; import { Home } from "./pages/Home"; import { Single } from "./pages/Single"; import { Demo } from "./pages/Demo"; +import Register from "./pages/Register"; +import Login from "./pages/Login"; export const router = createBrowserRouter( createRoutesFromElements( @@ -25,6 +27,8 @@ export const router = createBrowserRouter( } /> } /> {/* Dynamic route for single items */} } /> + } /> + } /> ) ); \ No newline at end of file From 66a8e3a3b6551640dbe2eab6af3bbbcff2f19882 Mon Sep 17 00:00:00 2001 From: Nika254 Date: Fri, 7 Nov 2025 19:46:10 +0000 Subject: [PATCH 3/9] commit Abel --- README.md | 6 ++--- package-lock.json | 56 +++++++++++++++++++---------------------------- src/api/admin.py | 8 +++---- 3 files changed, 29 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 6b782b220d..63d4ff2e7b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Build web applications using React.js for the front end and python/flask for you ### 1) Installation: -> If you use Github Codespaces (recommended) or Gitpod this template will already come with Python, Node and the Posgres Database installed. If you are working locally make sure to install Python 3.10, Node +> If you use Github Codespaces (recommended) or Gitpod this template will already come with Python, Node and the Posgres Database installed. If you are working locally make sure to install Python 3.10, Node It is recomended to install the backend first, make sure you have Python 3.10, Pipenv and a database engine (Posgress recomended) @@ -61,11 +61,11 @@ And you will see the following message: ### **Important note for the database and the data inside it** -Every Github codespace environment will have **its own database**, so if you're working with more people eveyone will have a different database and different records inside it. This data **will be lost**, so don't spend too much time manually creating records for testing, instead, you can automate adding records to your database by editing ```commands.py``` file inside ```/src/api``` folder. Edit line 32 function ```insert_test_data``` to insert the data according to your model (use the function ```insert_test_users``` above as an example). Then, all you need to do is run ```pipenv run insert-test-data```. +Every Github codespace environment will have **its own database**, so if you're working with more people eveyone will have a different database and different records inside it. This data **will be lost**, so don't spend too much time manually creating records for testing, instead, you can automate adding records to your database by editing `commands.py` file inside `/src/api` folder. Edit line 32 function `insert_test_data` to insert the data according to your model (use the function `insert_test_users` above as an example). Then, all you need to do is run `pipenv run insert-test-data`. ### Front-End Manual Installation: -- Make sure you are using node version 20 and that you have already successfully installed and runned the backend. +- Make sure you are using node version 20 and that you have already successfully installed and runned the backend. 1. Install the packages: `$ npm install` 2. Start coding! start the webpack dev server `$ npm run start` diff --git a/package-lock.json b/package-lock.json index 8d43d98ab7..44f1ece2dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,6 +73,7 @@ "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -884,7 +885,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -997,14 +997,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/node": { - "version": "16.11.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", - "integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", @@ -1018,6 +1010,7 @@ "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1066,6 +1059,7 @@ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1294,6 +1288,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -1312,8 +1307,7 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/call-bind": { "version": "1.0.8", @@ -1797,6 +1791,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -3486,6 +3481,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -3498,6 +3494,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -3921,7 +3918,6 @@ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "optional": true, - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -3933,7 +3929,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "optional": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4081,7 +4076,6 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, - "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -4100,8 +4094,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/text-table": { "version": "0.2.0", @@ -4278,6 +4271,7 @@ "integrity": "sha512-qK9W4xjgD3gXbC0NmdNFFnVFLMWSNiR3swj957yutwzzN16xF/E7nmtAyp1rT9hviDroQANjE4HK3H4WqWdFtw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.18.10", "postcss": "^8.4.27", @@ -4500,6 +4494,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", "dev": true, + "peer": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -4950,7 +4945,6 @@ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, "optional": true, - "peer": true, "requires": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -5044,14 +5038,6 @@ "@babel/types": "^7.20.7" } }, - "@types/node": { - "version": "16.11.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", - "integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==", - "dev": true, - "optional": true, - "peer": true - }, "@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", @@ -5063,6 +5049,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", "dev": true, + "peer": true, "requires": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -5098,7 +5085,8 @@ "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "dev": true + "dev": true, + "peer": true }, "acorn-jsx": { "version": "5.3.2", @@ -5245,6 +5233,7 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, + "peer": true, "requires": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -5257,8 +5246,7 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "call-bind": { "version": "1.0.8", @@ -5600,6 +5588,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, + "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -6702,6 +6691,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "peer": true, "requires": { "loose-envify": "^1.1.0" } @@ -6710,6 +6700,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "peer": true, "requires": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -6988,7 +6979,6 @@ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "optional": true, - "peer": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -6999,8 +6989,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "optional": true, - "peer": true + "optional": true } } }, @@ -7100,7 +7089,6 @@ "integrity": "sha512-GWANVlPM/ZfYzuPHjq0nxT+EbOEDDN3Jwhwdg1D8TU8oSkktp8w64Uq4auuGLxFSoNTRDncTq2hQHX1Ld9KHkA==", "dev": true, "optional": true, - "peer": true, "requires": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -7113,8 +7101,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "optional": true, - "peer": true + "optional": true } } }, @@ -7228,6 +7215,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.9.tgz", "integrity": "sha512-qK9W4xjgD3gXbC0NmdNFFnVFLMWSNiR3swj957yutwzzN16xF/E7nmtAyp1rT9hviDroQANjE4HK3H4WqWdFtw==", "dev": true, + "peer": true, "requires": { "esbuild": "^0.18.10", "fsevents": "~2.3.2", diff --git a/src/api/admin.py b/src/api/admin.py index 3eecb64140..b054170fc8 100644 --- a/src/api/admin.py +++ b/src/api/admin.py @@ -1,17 +1,17 @@ - + import os from flask_admin import Admin from .models import db, User from flask_admin.contrib.sqla import ModelView + def setup_admin(app): app.secret_key = os.environ.get('FLASK_APP_KEY', 'sample key') app.config['FLASK_ADMIN_SWATCH'] = 'cerulean' - admin = Admin(app, name='4Geeks Admin', template_mode='bootstrap3') + admin = Admin(app, name='4Geeks Admin') - # Add your models here, for example this is how we add a the User model to the admin admin.add_view(ModelView(User, db.session)) # You can duplicate that line to add mew models - # admin.add_view(ModelView(YourModelName, db.session)) \ No newline at end of file + # admin.add_view(ModelView(YourModelName, db.session)) From b75a66726f5a1aeedde0d87380ceb36c1de26a5f Mon Sep 17 00:00:00 2001 From: JorgeCKR Date: Fri, 7 Nov 2025 20:07:10 +0000 Subject: [PATCH 4/9] Commit Jorge --- package-lock.json | 56 +++++++++++++-------------------- src/front/components/Navbar.jsx | 7 +++-- src/front/styles/navbar.css | 4 +++ 3 files changed, 31 insertions(+), 36 deletions(-) create mode 100644 src/front/styles/navbar.css diff --git a/package-lock.json b/package-lock.json index 8d43d98ab7..44f1ece2dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,6 +73,7 @@ "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -884,7 +885,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -997,14 +997,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/node": { - "version": "16.11.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", - "integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", @@ -1018,6 +1010,7 @@ "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1066,6 +1059,7 @@ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1294,6 +1288,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -1312,8 +1307,7 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/call-bind": { "version": "1.0.8", @@ -1797,6 +1791,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -3486,6 +3481,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -3498,6 +3494,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -3921,7 +3918,6 @@ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "optional": true, - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -3933,7 +3929,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "optional": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4081,7 +4076,6 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, - "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -4100,8 +4094,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/text-table": { "version": "0.2.0", @@ -4278,6 +4271,7 @@ "integrity": "sha512-qK9W4xjgD3gXbC0NmdNFFnVFLMWSNiR3swj957yutwzzN16xF/E7nmtAyp1rT9hviDroQANjE4HK3H4WqWdFtw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.18.10", "postcss": "^8.4.27", @@ -4500,6 +4494,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", "dev": true, + "peer": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -4950,7 +4945,6 @@ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, "optional": true, - "peer": true, "requires": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -5044,14 +5038,6 @@ "@babel/types": "^7.20.7" } }, - "@types/node": { - "version": "16.11.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", - "integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==", - "dev": true, - "optional": true, - "peer": true - }, "@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", @@ -5063,6 +5049,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", "dev": true, + "peer": true, "requires": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -5098,7 +5085,8 @@ "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "dev": true + "dev": true, + "peer": true }, "acorn-jsx": { "version": "5.3.2", @@ -5245,6 +5233,7 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, + "peer": true, "requires": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -5257,8 +5246,7 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "call-bind": { "version": "1.0.8", @@ -5600,6 +5588,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, + "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -6702,6 +6691,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "peer": true, "requires": { "loose-envify": "^1.1.0" } @@ -6710,6 +6700,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "peer": true, "requires": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -6988,7 +6979,6 @@ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "optional": true, - "peer": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -6999,8 +6989,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "optional": true, - "peer": true + "optional": true } } }, @@ -7100,7 +7089,6 @@ "integrity": "sha512-GWANVlPM/ZfYzuPHjq0nxT+EbOEDDN3Jwhwdg1D8TU8oSkktp8w64Uq4auuGLxFSoNTRDncTq2hQHX1Ld9KHkA==", "dev": true, "optional": true, - "peer": true, "requires": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -7113,8 +7101,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "optional": true, - "peer": true + "optional": true } } }, @@ -7228,6 +7215,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.9.tgz", "integrity": "sha512-qK9W4xjgD3gXbC0NmdNFFnVFLMWSNiR3swj957yutwzzN16xF/E7nmtAyp1rT9hviDroQANjE4HK3H4WqWdFtw==", "dev": true, + "peer": true, "requires": { "esbuild": "^0.18.10", "fsevents": "~2.3.2", diff --git a/src/front/components/Navbar.jsx b/src/front/components/Navbar.jsx index 30d43a2636..b5dff92514 100644 --- a/src/front/components/Navbar.jsx +++ b/src/front/components/Navbar.jsx @@ -6,11 +6,14 @@ export const Navbar = () => {