add: guard in router

This commit is contained in:
Alexandro Uc Santos
2023-11-24 21:07:42 -06:00
parent afa8e1983b
commit ec02b98272
18 changed files with 914 additions and 47 deletions

View File

@@ -5,6 +5,10 @@
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
/>
<title>Eta viaporte</title>
</head>
<body class="bg-body">
@@ -12,8 +16,8 @@
<script type="module" src="/src/main.js"></script>
</body>
<script src="https://kit.fontawesome.com/3675730ed5.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
</html>

181
package-lock.json generated
View File

@@ -10,6 +10,7 @@
"dependencies": {
"axios": "^1.6.2",
"pinia": "^2.1.7",
"sass": "^1.69.5",
"vue": "^3.3.4",
"vue-multiselect": "^3.0.0-beta.3",
"vue-router": "^4.2.5"
@@ -507,6 +508,18 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.8.tgz",
"integrity": "sha512-8PGwybFwM4x8pcfgqEQFy70NaQxASvOC5DJwLQfpArw1UDfUXrJkdxD3BhVTMS+0Lef/TU7YO0Jvr0jJY8T+mw=="
},
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -522,6 +535,51 @@
"proxy-from-env": "^1.1.0"
}
},
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"engines": {
"node": ">=8"
}
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dependencies": {
"fill-range": "^7.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
],
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -588,6 +646,17 @@
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
},
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/follow-redirects": {
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
@@ -624,7 +693,6 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@@ -634,6 +702,60 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/immutable": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz",
"integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA=="
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dependencies": {
"binary-extensions": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dependencies": {
"is-extglob": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/magic-string": {
"version": "0.30.5",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz",
@@ -681,11 +803,30 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pinia": {
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz",
@@ -768,6 +909,17 @@
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/rollup": {
"version": "3.29.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
@@ -784,6 +936,22 @@
"fsevents": "~2.3.2"
}
},
"node_modules/sass": {
"version": "1.69.5",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.69.5.tgz",
"integrity": "sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==",
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
},
"bin": {
"sass": "sass.js"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
@@ -792,6 +960,17 @@
"node": ">=0.10.0"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/vite": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz",

View File

@@ -10,6 +10,7 @@
"dependencies": {
"axios": "^1.6.2",
"pinia": "^2.1.7",
"sass": "^1.69.5",
"vue": "^3.3.4",
"vue-multiselect": "^3.0.0-beta.3",
"vue-router": "^4.2.5"

View File

@@ -1,3 +1,7 @@
<script setup>
import Notification from './components/ui/Notification.vue';
</script>
<template>
<main>
<RouterView />
@@ -5,12 +9,6 @@
<Notification/>
</template>
<script setup>
import Notification from './components/ui/Notification.vue';
</script>
<style scoped>
</style>

View File

@@ -2,9 +2,6 @@ body {
margin: 0px 0px;
padding: 0px;
}
.bg-body{
background-color: red;
}
.w-lg-45{
width: 45%;

View File

@@ -0,0 +1,50 @@
<script setup>
import { useAuthStore } from '../../stores/auth';
const auth = useAuthStore();
</script>
<template>
<div class="noty-fixed" v-if="auth.checking">
<div class="content-noty">
<div class="body">
<img src="/images/logo.png" alt="logo" class="logo animate__animated animate__rubberBand">
<h2>Cargando...</h2>
</div>
</div>
</div>
</template>
<style scoped>
.noty-fixed {
position: fixed;
right: 0px;
top: 0px;
left: 0px;
bottom: 0px;
}
.content-noty {
width: 100vw;
height: 100vh;
padding: 16px 32px;
background-color: #FFF;
/* opacity: 0.9; */
}
.body {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
align-content: center;
margin: 0 auto;
gap: 5rem;
/* align-content: center; */
justify-content: center;
}
.logo {
width: 240px;
}
</style>

View File

@@ -28,7 +28,7 @@
.content-noty {
width: 100%;
max-width: 500px;
padding: 14px 20px;
padding: 16px 32px;
background-color: white;
border-radius: 8px;

View File

@@ -8,6 +8,8 @@ export const validateEmail = (email) => {
export const messagesError = (msg) => {
switch (msg) {
case 'Invalid credentials':
return 'Email y/o password incorrectos';
case 'Email is not registered!':
return 'No se encontro una cuenta con este email';
case 'Wrong OTP':

View File

@@ -1,11 +1,305 @@
<template>
<RouterView />
</template>
<script setup>
import { RouterLink, useRoute, useRouter } from 'vue-router';
import { useAuthStore } from '../stores/auth';
import LoadingModal from '../components/ui/LoadingModal.vue';
const route = useRoute();
const router = useRouter();
const auth = useAuthStore();
$(document).ready(function() {
$('#sidebarCollapse').on('click', function () {
$('#sidebar').toggleClass('active');
});
});
const handleLogout = () => {
auth.$patch({
sesion: '',
token: '',
user: {},
});
localStorage.removeItem('session');
router.push({name: 'login'});
}
</script>
<style scoped>
<template>
<div class="wrapper">
<nav id="sidebar">
<div class="sidebar-header">
<div class="logo">
<!-- <img src="/images/logo.png" alt="Eta viaporte" width="120"> -->
<img src="/images/logo-eta.png" alt="Eta viaporte" width="120">
</div>
<h2 class="my-4">COVO</h2>
<p><i class="fa-solid fa-user"></i> <span class="ms-2">{{ auth.user?.first_name + ' ' + auth.user?.last_name }}</span></p>
<div class="divider"></div>
</div>
<div>
</div>
<ul class="list-unstyled components">
<li :class="[route.name === 'home' ? 'bg-nav-active' : '']">
<div>
<i class="fa-regular fa-building" :class="[route.name === 'home' ? 'router-link-active' : '']"></i>
<RouterLink
active-class="router-link-active"
class="nav-link" :to="{name: 'home'}">Empresa</RouterLink>
</div>
<!-- <i class="fa-solid fa-chevron-right"></i> -->
</li>
<li :class="[route.name === 'users' ? 'bg-nav-active' : '']">
<div>
<i class="fa-regular fa-user" :class="[route.name === 'users' ? 'router-link-active' : '']"></i>
<RouterLink
active-class="router-link-active"
class="nav-link" :to="{name: 'users'}">Usuarios</RouterLink>
</div>
<!-- <i class="fa-solid fa-chevron-right"></i> -->
</li>
<li :class="[route.name === 'calendar' ? 'bg-nav-active' : '']">
<div>
<i class="fa-regular fa-calendar" :class="[route.name === 'calendar' ? 'router-link-active' : '']"></i>
<RouterLink
active-class="router-link-active"
class="nav-link" :to="{name: 'calendar'}">Calendario</RouterLink>
</div>
<!-- <i class="fa-solid fa-chevron-right"></i> -->
</li>
<li :class="[route.name === 'loads' ? 'bg-nav-active' : '']">
<div>
<i class="fa-solid fa-box" :class="[route.name === 'loads' ? 'router-link-active' : '']"></i>
<RouterLink
active-class="router-link-active"
class="nav-link" :to="{name: 'loads'}">Cargas</RouterLink>
</div>
<!-- <i class="fa-solid fa-chevron-right"></i> -->
</li>
<li :class="[route.name === 'vehicles' ? 'bg-nav-active' : '']">
<div>
<i class="fa-solid fa-truck-fast" :class="[route.name === 'vehicles' ? 'router-link-active' : '']"></i>
<RouterLink
active-class=""
class="nav-link" :to="{name: 'vehicles'}">Vehiculos</RouterLink>
</div>
<!-- <i class="fa-solid fa-chevron-right"></i> -->
</li>
</ul>
<div class="eta-info">
<div class="divider"></div>
<a class="link-eta" href="">Aviso de privaciadad</a>
<a class="link-eta" href="">Terminos y condiciones</a>
<a class="link-eta" href="">FAQS</a>
<div class="d-flex align-items-center">
<i class="fa-solid fa-right-from-bracket"></i>
<a @click="handleLogout"
active-class=""
class="nav-link m-2">
Cerrar sesión
</a>
</div>
</div>
</nav>
<div id="content">
<nav class="navbar navbar-expand-lg navbar-light custom-navbar">
<div class="nav-items">
<button type="button" id="sidebarCollapse" class="btn btn-info btn-menu">
<i class="fas fa-align-left"></i>
</button>
<div class="nav-options">
<RouterLink
active-class="router-link-active"
class="nav-link" :to="{name: 'recovery'}">Embarques</RouterLink>
<RouterLink
active-class="router-link-active"
class="nav-link" :to="{name: 'recovery'}">Cargas</RouterLink>
</div>
</div>
</nav>
<div class="view">
<RouterView />
</div>
</div>
</div>
<LoadingModal/>
</template>
<style lang="scss" scoped>
.wrapper {
display: flex;
width: 100%;
align-items: stretch;
background-color: #f6f3f3;
}
#sidebar {
/* margin: 20px; */
display: flex;
flex-direction: column;
width: 220px;
min-height: 100vh;
/* background: #FFF;
color: #323030; */
background: #323030;
color: #FFF;
filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.10));
transition: all 0.3s;
}
#sidebar.active {
margin-left: -250px;
}
#sidebar .sidebar-header {
padding: 20px;
/* background: #FFF;
color: #323030; */
background: #323030;
color: #FFF;
margin-bottom: 8px;
}
.logo {
display: flex;
justify-content: center;
}
.sidebar-header h2 {
margin-top: 16px;
font-size: 1.4rem;
font-weight: 900;
}
#sidebar ul li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
margin-bottom: 5px;
/* background-color: #FFF; */
background-color: #323030;
}
#sidebar ul li div{
display: flex;
align-items: center;
gap: 1rem;
}
#sidebar ul li i{
font-size: 20px;
color: #897c7c;
}
#sidebar ul li.active > a, a[aria-expanded="true"] {
color: #fff;
background: #6d7fcc;
}
a[data-toggle="collapse"] {
position: relative;
}
.custom-navbar {
display: block;
width: calc(100vw - 220px);
background-color: #FFF;
}
.btn-menu {
display: none;
}
.dropdown-toggle::after {
display: block;
position: absolute;
top: 50%;
right: 20px;
transform: translateY(-50%);
}
.view {
margin: 24px 16px;
}
.nav-items {
display: flex;
flex-direction: row;
justify-content: end;
}
.nav-options {
margin-left: 32px;
display: flex;
}
.nav-link{
cursor: pointer;
/* color: #5f5c5c; */
color: #ebd6d6;
font-size: 1.2rem;
margin-right: 1.2rem;
font-weight: 500;
}
.nav-link:hover{
/* color: #413f3c; */
color: #FFF;
}
.nav-link:focus{
/* color: #413f3c; */
color: #FFF;
}
.router-link-active{
/* color: #413f3c !important; */
color: #FFF !important;
}
.bg-nav-active {
/* background-color: #e4eff2 !important;; */
background-color: #373738 !important;;
}
.eta-info {
// position: fixed;
display: flex;
flex-direction: column;
margin-top: 20px;
bottom: 10px;
gap: 1rem;
// background-color: red;
align-items: start;
padding: 10px 16px;
}
.link-eta {
font-size: 14px;
text-decoration: none;
font-weight: 400;
color: #FFF;
opacity: 0.6;
}
@media (max-width: 768px) {
.custom-navbar {
width: 100vw;
}
.nav-items {
justify-content: space-between;
}
.btn-menu {
display: flex;
}
#sidebar {
margin-left: -220px;
}
#sidebar.active {
margin-left: 0;
}
}
</style>

View File

@@ -1,6 +1,5 @@
import { createRouter, createWebHistory } from 'vue-router'
import AuthLayout from '../layouts/AuthLayout.vue'
import LoginView from '../views/LoginView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
@@ -25,21 +24,77 @@ const router = createRouter({
name: 'recovery',
component: () => import('../views/RecoveryPasswordView.vue'),
},
{
path: 'empresa',
name: 'company',
component: () => import('../views/CompleteRegisterView.vue')
}
]
},
{
path: '/dashboard',
name: 'dashboard',
component: () => import('../layouts/AdminLayout.vue'),
meta: { requiresAuth: true },
children: [
{
path: 'inicio',
name: 'inicio',
name: 'home',
component: () => import('../views/HomeView.vue'),
},
{
path: 'usuarios',
name: 'users',
component: () => import('../views/UsersView.vue'),
},
{
path: 'calendario',
name: 'calendar',
component: () => import('../views/CalendarView.vue'),
},
{
path: 'cargas',
name: 'loads',
component: () => import('../views/LoadsView.vue'),
},
{
path: 'vehiculos',
name: 'vehicles',
component: () => import('../views/VehiclesView.vue'),
},
]
}
]
})
});
router.beforeEach( async(to, from, next) => {
const requiresAuth = to.matched.some(url => url.meta.requiresAuth)
const session = localStorage.getItem('session');
// console.log('--------------- SE EJECUTA -----------------');
// console.log(session);
// console.log('--------------- FIN -----------------');
if(requiresAuth) {
//Comprobamos si el usuario esta authenticado
if(session) {
// try {
// const resp = await renewToken();
// if(resp.msg == 'success') {
// next();
// } else {
// next({name: 'login'})
// }
// } catch (error) {
// console.log(error);
// next({name: 'login'})
// }
next();
} else {
next({name: 'login'})
}
} else {
// No esta protegido
next();
}
});
export default router

View File

@@ -1,6 +1,65 @@
import api from "../lib/axios";
import {messagesError} from '../helpers/validations';
export const login = async(body) => {
try {
const endpoint = "/account/authorize";
const {data} = await api.post(endpoint, body);
console.log(data);
console.log(data.accessToken);
if(data.accessToken !== null){
if(data.user.job_role !== 'driver'){
//TODO: Guardar token y datos del usuario
return {
msg: 'success',
data
};
} else {
//Remover datos de sesion
return 'Rol no autorizado';
}
} else {
return {
msg: "email y/o password incorrectos",
data: null
};
}
} catch (error) {
const errStr = error.response.data.error ?? 'Algo salio mal, intente más tarde';
return {
msg: messagesError(errStr),
data: null
};
}
}
export const renewToken = async() => {
const session = localStorage.getItem('session');
try {
const endpoint = `/account/authorize/${session}`;
const {data} = await api.get(endpoint);
console.log(data.user);
if(data.accessToken !== null){
return {
msg: 'success',
data
};
} else {
return {
msg: "Sesion expiro",
data: null
};
}
} catch (error) {
const errStr = error.response.data.error ?? 'Algo salio mal, intente más tarde';
return {
msg: 'Sesion expiro',
data: null
};
}
}
export const regiter = async(body) => {
try {
const endpoint = "/account/signup";

55
src/stores/auth.js Normal file
View File

@@ -0,0 +1,55 @@
import { defineStore } from "pinia";
import { ref, onMounted } from "vue";
import { useRouter } from 'vue-router';
import { renewToken } from '../services/auth';
import {useNotificationsStore} from './notifications';
export const useAuthStore = defineStore('auth', () => {
const router = useRouter();
const noty = useNotificationsStore();
const sesion = ref('')
const checking = ref(false);
const token = ref('')
const user = ref(null)
onMounted( async() => {
console.log('Se ejecuta onMounted auth');
checkSession();
});
const checkSession = async() => {
checking.value = true;
const resp = await renewToken();
if(resp.msg === 'success') {
localStorage.setItem('session', resp.data.session_token);
sesion.value = resp.data.session_token;
token.value = resp.data.accessToken;
user.value = resp.data.user;
checking.value = false;
} else {
noty.show = true;
noty.text = 'Sesión ha expirado, ingresa nuevamente';
noty.error = true;
checking.value = false;
router.push({name: 'login'});
}
}
const logout = () => {
localStorage.removeItem('session');
router.push({name: 'login'});
sesion.value = '';
token.value = '';
user.value = null;
}
return {
sesion,
logout,
token,
user,
checking
}
});

View File

@@ -0,0 +1,13 @@
<script setup>
</script>
<template>
<div>
<h2 class="title">Calendario</h2>
</div>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,99 @@
<script setup>
</script>
<template>
<h2 class="title">Complete su registro</h2>
<div class="card-info flex-column">
<p>¿Como te quieres registrar?</p>
<label class="container">Embarcador
<input type="radio" checked="checked" name="radio">
<span class="checkmark"></span>
</label>
<label class="container">Transportista
<input type="radio" name="radio">
<span class="checkmark"></span>
</label>
<label class="container">Broker (Embarcador)
<input type="radio" name="radio">
<span class="checkmark"></span>
</label>
<label class="container">Broker (Transportista)
<input type="radio" name="radio">
<span class="checkmark"></span>
</label>
</div>
</template>
<style lang="scss" scoped>
.container {
display: block;
position: relative;
padding-left: 35px;
margin-bottom: 12px;
cursor: pointer;
font-size: 22px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* Hide the browser's default radio button */
.container input {
position: absolute;
opacity: 0;
cursor: pointer;
}
/* Create a custom radio button */
.checkmark {
position: absolute;
top: 0;
left: 0;
height: 25px;
width: 25px;
background-color: #eee;
border-radius: 50%;
}
/* On mouse-over, add a grey background color */
.container:hover input ~ .checkmark {
background-color: #ccc;
}
/* When the radio button is checked, add a blue background */
.container input:checked ~ .checkmark {
background-color: #2196F3;
}
/* Create the indicator (the dot/circle - hidden when not checked) */
.checkmark:after {
content: "";
position: absolute;
display: none;
}
/* Show the indicator (dot/circle) when checked */
.container input:checked ~ .checkmark:after {
display: block;
}
/* Style the indicator (dot/circle) */
.container .checkmark:after {
top: 9px;
left: 9px;
width: 8px;
height: 8px;
border-radius: 50%;
background: white;
}
</style>
<!-- ¿Como te quieres registrar? (Opciones a elegir)
1 - Embarcador
2 - Transportista
3 - Broker (Embarcador)
4 - Broker (Transportista) -->

13
src/views/LoadsView.vue Normal file
View File

@@ -0,0 +1,13 @@
<script setup>
</script>
<template>
<div>
<h2 class="title">Cargas</h2>
</div>
</template>
<style scoped>
</style>

View File

@@ -4,14 +4,19 @@
import NotificationBadge from '../components/ui/NotificationBadge.vue';
import {validateEmail} from '../helpers/validations';
import Spiner from '../components/ui/Spiner.vue';
import { RouterLink } from 'vue-router';
import { login } from '../services/auth';
import { RouterLink, useRouter } from 'vue-router';
import { useAuthStore } from '../stores/auth';
const form = reactive({
email: '',
password: '',
email: 'alexandro.uc.santos@gmail.com',
password: 'Password0',
});
const router = useRouter();
const auth = useAuthStore();
const loading = ref(false);
const msgError = ref('');
const msgSuccess = ref('');
@@ -31,7 +36,24 @@ import { RouterLink } from 'vue-router';
email: form.email,
password: form.password
}
console.log(data);
const resp = await login(data);
if(resp.msg === 'success') {
console.log(resp.data.user);
if(resp.data.user.first_name && resp.data.user.last_name) {
localStorage.setItem('session', resp.data.session_token);
router.push({name: 'home'});
auth.$patch({
sesion: resp.data.session_token,
token: resp.data.accessToken,
user: resp.data.user,
})
} else {
router.push({name: 'company'});
}
} else {
msgError.value = resp.msg;
}
clearMessages();
loading.value = false;
}
}

13
src/views/UsersView.vue Normal file
View File

@@ -0,0 +1,13 @@
<script setup>
</script>
<template>
<div>
<h2 class="title">Usuarios</h2>
</div>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,13 @@
<script setup>
</script>
<template>
<div>
<h2 class="title">Vehiculos</h2>
</div>
</template>
<style scoped>
</style>