Implement authentication and routing features with login and dashboard pages
This commit is contained in:
parent
f35cd90cd6
commit
282118b93f
|
|
@ -0,0 +1,31 @@
|
|||
export function renderLogin(onLogin) {
|
||||
const loginContainer = document.createElement('div');
|
||||
loginContainer.className = 'login-container';
|
||||
|
||||
loginContainer.innerHTML = `
|
||||
<div class="login-card">
|
||||
<h2 class="login-title">Iniciar Sesión</h2>
|
||||
<form id="login-form">
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" name="email" required autocomplete="email">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Contraseña</label>
|
||||
<input type="password" id="password" name="password" required autocomplete="current-password">
|
||||
</div>
|
||||
<button type="submit" class="login-button">Ingresar</button>
|
||||
</form>
|
||||
<p id="login-error" class="login-error"></p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
loginContainer.querySelector('#login-form').addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
const email = loginContainer.querySelector('#email').value;
|
||||
const password = loginContainer.querySelector('#password').value;
|
||||
onLogin(email, password);
|
||||
});
|
||||
|
||||
return loginContainer;
|
||||
}
|
||||
24
src/main.js
24
src/main.js
|
|
@ -1,24 +1,4 @@
|
|||
import './style.css'
|
||||
import javascriptLogo from './javascript.svg'
|
||||
import viteLogo from '/vite.svg'
|
||||
import { setupCounter } from './counter.js'
|
||||
import { initRouter } from './router.js'
|
||||
|
||||
document.querySelector('#app').innerHTML = `
|
||||
<div>
|
||||
<a href="https://vite.dev" target="_blank">
|
||||
<img src="${viteLogo}" class="logo" alt="Vite logo" />
|
||||
</a>
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank">
|
||||
<img src="${javascriptLogo}" class="logo vanilla" alt="JavaScript logo" />
|
||||
</a>
|
||||
<h1>Hello Vite!</h1>
|
||||
<div class="card">
|
||||
<button id="counter" type="button"></button>
|
||||
</div>
|
||||
<p class="read-the-docs">
|
||||
Click on the Vite logo to learn more
|
||||
</p>
|
||||
</div>
|
||||
`
|
||||
|
||||
setupCounter(document.querySelector('#counter'))
|
||||
initRouter()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
import { auth } from '../services/auth.js';
|
||||
|
||||
export function renderDashboard() {
|
||||
const user = auth.getUser();
|
||||
const container = document.createElement('div');
|
||||
container.className = 'dashboard';
|
||||
|
||||
container.innerHTML = `
|
||||
<div class="dashboard-header">
|
||||
<h1>Bienvenido, ${user?.email || 'Usuario'}</h1>
|
||||
<button id="logout-button" class="logout-button">Cerrar Sesión</button>
|
||||
</div>
|
||||
<div class="dashboard-content">
|
||||
<p>Dashboard protegido</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
container.querySelector('#logout-button').addEventListener('click', () => {
|
||||
auth.logout();
|
||||
window.location.hash = '#login';
|
||||
});
|
||||
|
||||
return container;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import { auth } from '../services/auth.js';
|
||||
import { renderLogin } from '../components/Login.js';
|
||||
|
||||
export function renderLoginPage(onLoginSuccess) {
|
||||
const container = document.createElement('div');
|
||||
container.className = 'login-page';
|
||||
|
||||
const loginComponent = renderLogin((email, password) => {
|
||||
if (auth.login(email, password)) {
|
||||
if (onLoginSuccess) {
|
||||
onLoginSuccess();
|
||||
} else {
|
||||
window.location.hash = '#dashboard';
|
||||
}
|
||||
} else {
|
||||
const error = container.querySelector('#login-error');
|
||||
error.textContent = 'Credenciales inválidas';
|
||||
}
|
||||
});
|
||||
|
||||
container.appendChild(loginComponent);
|
||||
return container;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import { auth } from './services/auth.js';
|
||||
import { renderLoginPage } from './pages/LoginPage.js';
|
||||
import { renderDashboard } from './pages/DashboardPage.js';
|
||||
|
||||
export function initRouter() {
|
||||
const app = document.querySelector('#app');
|
||||
|
||||
function navigate() {
|
||||
const hash = window.location.hash || '#login';
|
||||
|
||||
if (!auth.checkAuth() && hash !== '#login') {
|
||||
window.location.hash = '#login';
|
||||
return;
|
||||
}
|
||||
|
||||
app.innerHTML = '';
|
||||
|
||||
switch (hash) {
|
||||
case '#login':
|
||||
app.appendChild(renderLoginPage(() => {
|
||||
window.location.hash = '#dashboard';
|
||||
}));
|
||||
break;
|
||||
case '#dashboard':
|
||||
app.appendChild(renderDashboard());
|
||||
break;
|
||||
default:
|
||||
window.location.hash = '#login';
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('hashchange', navigate);
|
||||
navigate();
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
export class Auth {
|
||||
constructor() {
|
||||
this.currentUser = null;
|
||||
this.isAuthenticated = false;
|
||||
}
|
||||
|
||||
login(email, password) {
|
||||
if (email && password) {
|
||||
this.currentUser = { email };
|
||||
this.isAuthenticated = true;
|
||||
localStorage.setItem('user', JSON.stringify(this.currentUser));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.currentUser = null;
|
||||
this.isAuthenticated = false;
|
||||
localStorage.removeItem('user');
|
||||
}
|
||||
|
||||
checkAuth() {
|
||||
const user = localStorage.getItem('user');
|
||||
if (user) {
|
||||
this.currentUser = JSON.parse(user);
|
||||
this.isAuthenticated = true;
|
||||
}
|
||||
return this.isAuthenticated;
|
||||
}
|
||||
|
||||
getUser() {
|
||||
return this.currentUser;
|
||||
}
|
||||
}
|
||||
|
||||
export const auth = new Auth();
|
||||
113
src/style.css
113
src/style.css
|
|
@ -94,3 +94,116 @@ button:focus-visible {
|
|||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
|
||||
.login-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
background: #2a2a2a;
|
||||
padding: 2.5rem;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
color: #fff;
|
||||
margin: 0 0 2rem 0;
|
||||
font-size: 1.8rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
color: #fff;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid #444;
|
||||
border-radius: 6px;
|
||||
background: #1a1a1a;
|
||||
color: #fff;
|
||||
font-size: 1rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-group input:focus {
|
||||
outline: none;
|
||||
border-color: #646cff;
|
||||
}
|
||||
|
||||
.login-button {
|
||||
width: 100%;
|
||||
padding: 0.875rem;
|
||||
background-color: #646cff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.25s;
|
||||
}
|
||||
|
||||
.login-button:hover {
|
||||
background-color: #535bf2;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.login-error {
|
||||
color: #ff6b6b;
|
||||
text-align: center;
|
||||
margin-top: 1rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.dashboard {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.dashboard-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.dashboard-header h1 {
|
||||
font-size: 2rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.dashboard-content {
|
||||
background: #2a2a2a;
|
||||
padding: 2rem;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.logout-button {
|
||||
background-color: #ff6b6b;
|
||||
color: white;
|
||||
padding: 0.5rem 1rem;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.logout-button:hover {
|
||||
background-color: #fa5252;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue