From b4b3edd08875752f609c17e7b8897e81b927b1d9 Mon Sep 17 00:00:00 2001 From: fede Date: Tue, 21 Oct 2025 18:02:33 -0300 Subject: [PATCH] cumplida segunda consigna --- bun.lock | 10 +++++ package.json | 4 +- src/App.css | 11 +++-- src/App.tsx | 66 ++++++++++++++++-------------- src/Components/Alumno.css | 19 --------- src/Components/Alumno.tsx | 44 -------------------- src/Components/ComponenteAdmin.tsx | 28 +++++++++++++ src/Components/Dashboard.tsx | 3 ++ src/Components/NavBar.tsx | 27 ++++++++++++ src/Components/Seccion.tsx | 9 ++++ src/Router/AppRouter.tsx | 38 +++++++++++++++++ src/Router/RutaProtegida.tsx | 18 ++++++++ src/main.tsx | 17 ++++---- src/services/useUsuario.ts | 21 ++++++++++ src/types/usuario.ts | 11 +++-- vite.config.ts | 8 ++-- 16 files changed, 220 insertions(+), 114 deletions(-) delete mode 100644 src/Components/Alumno.css delete mode 100644 src/Components/Alumno.tsx create mode 100644 src/Components/ComponenteAdmin.tsx create mode 100644 src/Components/Dashboard.tsx create mode 100644 src/Components/NavBar.tsx create mode 100644 src/Components/Seccion.tsx create mode 100644 src/Router/AppRouter.tsx create mode 100644 src/Router/RutaProtegida.tsx create mode 100644 src/services/useUsuario.ts diff --git a/bun.lock b/bun.lock index 9cd0d01..b6f0c45 100644 --- a/bun.lock +++ b/bun.lock @@ -6,6 +6,8 @@ "dependencies": { "react": "^19.1.1", "react-dom": "^19.1.1", + "react-router": "^7.9.4", + "react-router-dom": "^7.9.4", }, "devDependencies": { "@eslint/js": "^9.36.0", @@ -230,6 +232,8 @@ "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + "cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="], + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], @@ -406,6 +410,10 @@ "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="], + "react-router": ["react-router@7.9.4", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-SD3G8HKviFHg9xj7dNODUKDFgpG4xqD5nhyd0mYoB5iISepuZAvzSr8ywxgxKJ52yRzf/HWtVHc9AWwoTbljvA=="], + + "react-router-dom": ["react-router-dom@7.9.4", "", { "dependencies": { "react-router": "7.9.4" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-f30P6bIkmYvnHHa5Gcu65deIXoA2+r3Eb6PJIAddvsT9aGlchMatJ51GgpU470aSqRRbFX22T70yQNUGuW3DfA=="], + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], @@ -418,6 +426,8 @@ "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="], + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], diff --git a/package.json b/package.json index ea3a909..6e35c6b 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,9 @@ }, "dependencies": { "react": "^19.1.1", - "react-dom": "^19.1.1" + "react-dom": "^19.1.1", + "react-router": "^7.9.4", + "react-router-dom": "^7.9.4" }, "devDependencies": { "@eslint/js": "^9.36.0", diff --git a/src/App.css b/src/App.css index 902778b..56737d8 100644 --- a/src/App.css +++ b/src/App.css @@ -1,6 +1,9 @@ #root { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} +p { + margin: 0; } diff --git a/src/App.tsx b/src/App.tsx index 8ecdded..c17c7f0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,37 +1,41 @@ -import { useEffect, useState } from 'react'; -import './App.css'; -import Alumno from './Components/Alumno'; -import { ObtenerUsuarios } from './services/servicioUsuario'; +import "./App.css"; +import { Link } from "react-router"; +import { AppRouter } from "./Router/AppRouter"; +import { Navbar } from "./Components/NavBar"; +import { useUsuario } from "./services/useUsuario"; +import { Seccion } from "./Components/Seccion"; +import type { PermissionLevel } from "./types/usuario"; function App() { - const [loading, setLoading] = useState(true); - const [alumnos, setAlumnos] = useState([]); - - useEffect(() => { - async function cargarDatos() { - setLoading(true); - try { - const data = await ObtenerUsuarios(); - setAlumnos(data); - } catch (error) { - console.error('Error al obtener usuarios:', error); - } finally { - setLoading(false); + const { usuario, setPermissionLevel } = useUsuario(); + return ( + <> + + + Home + {usuario?.permissionLevel.includes("ADMIN") && ( + Admin + )} + analytics + About + + + El permiso el usuario es: + + + + + + ); } export default App; diff --git a/src/Components/Alumno.css b/src/Components/Alumno.css deleted file mode 100644 index c37595c..0000000 --- a/src/Components/Alumno.css +++ /dev/null @@ -1,19 +0,0 @@ -.alumno{ - padding: 1rem 1rem 1rem 1rem; -} -.b{ - border:3px solid; - border-radius: 10px; -} - -.b-rojo{ - border-color: red; -} - -.b-verde{ - border-color: green; -} - -p{ - margin:0; -} diff --git a/src/Components/Alumno.tsx b/src/Components/Alumno.tsx deleted file mode 100644 index 85e8cd8..0000000 --- a/src/Components/Alumno.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { useState } from "react"; -import "./Alumno.css" -import type { Usuario } from "../types/usuario"; - -export default function Alumno({data}: {data: Usuario}){ - const [alumno, setAlumno] = useState({ presente: false }); - return ( -
- {(alumno.presente === true ? ( -

- Presente -

- ) : ( -

- Ausente -

- ))} - -
-
-

- Nombre: {data.name} -

- -

- Usuario: {data.username} -

- -

- Usuario: {data.email} -

-
-
- - -
- ); -} diff --git a/src/Components/ComponenteAdmin.tsx b/src/Components/ComponenteAdmin.tsx new file mode 100644 index 0000000..b0a750b --- /dev/null +++ b/src/Components/ComponenteAdmin.tsx @@ -0,0 +1,28 @@ +import { useEffect, useState } from "react"; +import { ObtenerUsuarios } from "../services/servicioUsuario"; +import type { Usuario } from "../types/usuario"; + +export function ComponenteAdmin() { + const [usuarios, setUsuarios] = useState([]); + + useEffect(() => { + async function fetchUsuarios() { + const data = await ObtenerUsuarios(); + setUsuarios(data); + } + fetchUsuarios(); + }, []); + + return ( + <> +

Panel Admin

+ {usuarios.length > 0 && ( +
    + {usuarios.map((x: Usuario) => ( +
  • {x.username}
  • + ))} +
+ )} + + ); +} diff --git a/src/Components/Dashboard.tsx b/src/Components/Dashboard.tsx new file mode 100644 index 0000000..0432a17 --- /dev/null +++ b/src/Components/Dashboard.tsx @@ -0,0 +1,3 @@ +export function Dashboard() { + return

Dashboard

; +} diff --git a/src/Components/NavBar.tsx b/src/Components/NavBar.tsx new file mode 100644 index 0000000..4998e7c --- /dev/null +++ b/src/Components/NavBar.tsx @@ -0,0 +1,27 @@ +import React, { type ReactNode } from "react"; + +type NavbarProps = { + children?: ReactNode; +}; + +export const Navbar: React.FC = ({ children }) => { + return ( + + ); +}; diff --git a/src/Components/Seccion.tsx b/src/Components/Seccion.tsx new file mode 100644 index 0000000..b541f98 --- /dev/null +++ b/src/Components/Seccion.tsx @@ -0,0 +1,9 @@ +import type { ReactNode } from "react"; + +interface Prop { + children?: ReactNode; +} + +export function Seccion({ children }: Prop) { + return
{children}
; +} diff --git a/src/Router/AppRouter.tsx b/src/Router/AppRouter.tsx new file mode 100644 index 0000000..5e4fab4 --- /dev/null +++ b/src/Router/AppRouter.tsx @@ -0,0 +1,38 @@ +import { useEffect, useState } from "react"; +import type { Usuario } from "../types/usuario"; +import { Routes } from "react-router"; +import { Route } from "react-router"; +import { Navigate } from "react-router"; +import { RutaProtegida } from "./RutaProtegida"; +import { ComponenteAdmin } from "../Components/ComponenteAdmin"; +import { Dashboard } from "../Components/Dashboard"; +import { useUsuario } from "../services/useUsuario"; + +export function AppRouter() { + const { usuario } = useUsuario(); + + return ( + + } /> + } /> + }> + About}> + Estadisticas}> + + + + + } + > + } /> + + ); +} diff --git a/src/Router/RutaProtegida.tsx b/src/Router/RutaProtegida.tsx new file mode 100644 index 0000000..2f9532c --- /dev/null +++ b/src/Router/RutaProtegida.tsx @@ -0,0 +1,18 @@ +import type { ReactNode } from "react"; +import { Navigate, Outlet } from "react-router"; + +interface RutaProtegidaProp { + estaPermitido: boolean; + children?: ReactNode; + redirectTo?: string; +} + +export function RutaProtegida({ + estaPermitido, + children, + redirectTo = "/home", +}: RutaProtegidaProp) { + if (!estaPermitido) return ; + + return children ? children : ; +} diff --git a/src/main.tsx b/src/main.tsx index bef5202..1e4ba21 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,10 +1,13 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import './index.css' -import App from './App.tsx' +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import "./index.css"; +import App from "./App.tsx"; +import { BrowserRouter } from "react-router"; -createRoot(document.getElementById('root')!).render( +createRoot(document.getElementById("root")!).render( - + + + , -) +); diff --git a/src/services/useUsuario.ts b/src/services/useUsuario.ts new file mode 100644 index 0000000..73283d9 --- /dev/null +++ b/src/services/useUsuario.ts @@ -0,0 +1,21 @@ +import { useState } from "react"; +import type { PermissionLevel, Usuario } from "../types/usuario"; + +export const useUsuario = () => { + const [usuario, setUsuario] = useState({ + id: 1, + name: "Juan Pepe", + username: "jpepe", + email: "", + permissionLevel: ["GUEST"], + }); + + function setPermissionLevel(arg: PermissionLevel) { + setUsuario({ ...usuario, permissionLevel: [arg] }); + } + + return { + usuario, + setPermissionLevel, + }; +}; diff --git a/src/types/usuario.ts b/src/types/usuario.ts index 5fa7335..53e3087 100644 --- a/src/types/usuario.ts +++ b/src/types/usuario.ts @@ -1,6 +1,9 @@ export interface Usuario { - id: number, - name: string, - username: string, - email: string + id: number; + name: string; + username: string; + email: string; + permissionLevel: [PermissionLevel]; } + +export type PermissionLevel = "ADMIN" | "USER" | "GUEST"; diff --git a/vite.config.ts b/vite.config.ts index 4efe189..5f084e7 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,13 +1,13 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; // https://vite.dev/config/ export default defineConfig({ plugins: [ react({ babel: { - plugins: [['babel-plugin-react-compiler']], + plugins: [["babel-plugin-react-compiler"]], }, }), ], -}) +});