cambios del 24 de abril

This commit is contained in:
2021-04-25 15:55:18 -05:00
parent 2b01e58388
commit 48dfb5e64f
19 changed files with 542 additions and 6462 deletions

View File

@@ -9,12 +9,13 @@
<base-input
label="Fecha"
v-model="newCompra.fecha"
type="Date"
type="Date" required
></base-input>
<base-input
label="Descripcion"
v-model="newCompra.detalle"
></base-input>
<base-input
label="Valor"
@@ -22,7 +23,7 @@
v-model="newCompra.valor"
></base-input>
<base-input label="Metodo de pago">
<select class="form-control" v-model="newCompra.metodo_pago">
<select class="form-control" v-model="newCompra.metodopago" >
<option v-for="metodo in metodos_pago">
{{ metodo.metodo }}
</option>

View File

@@ -10,7 +10,7 @@
rel="noopener"
class="nav-link"
>
Blog
Finanzas Personales
</a>
</li>
</ul>

View File

@@ -70,7 +70,7 @@
</li>
<div class="dropdown-divider"></div>
<li class="nav-link">
<a href="#" class="nav-item dropdown-item">Log out</a>
<a @click="salir()" class="nav-item dropdown-item">Log out</a>
</li>
</base-dropdown>
</ul>
@@ -122,6 +122,15 @@ export default {
},
toggleMenu() {
this.showMenu = !this.showMenu;
},
salir(){
localStorage.clear('auth');
this.$notify({
type: "danger",
icon: "tim-icons icon-alert-circle-exc",
message: "Sesión cerrada"
});
$nuxt.$router.push('/login');
}
}
};

95
APP/layouts/auth.vue Normal file
View File

@@ -0,0 +1,95 @@
<template>
<div class="wrapper">
<notifications></notifications>
<router-view name="header"></router-view>
<div :class="{ content: true }" style="margin-top: 100px;">
<zoom-center-transition :duration="200" mode="out-in">
<!-- your content here -->
<nuxt />
</zoom-center-transition>
</div>
</div>
</template>
<script>
/* eslint-disable no-new */
import PerfectScrollbar from "perfect-scrollbar";
import "perfect-scrollbar/css/perfect-scrollbar.css";
function hasElement(className) {
return document.getElementsByClassName(className).length > 0;
}
function initScrollbar(className) {
if (hasElement(className)) {
new PerfectScrollbar(`.${className}`);
} else {
// try to init it later in case this component is loaded async
setTimeout(() => {
initScrollbar(className);
}, 100);
}
}
import { SlideYDownTransition, ZoomCenterTransition } from "vue2-transitions";
export default {
name: "auth",
components: {
ZoomCenterTransition
},
data() {
return {
sidebarBackground: "primary" //vue|blue|orange|green|red|primary
};
},
methods: {
toggleSidebar() {
if (this.$sidebar.showSidebar) {
this.$sidebar.displaySidebar(false);
}
},
initScrollbar() {
let docClasses = document.body.classList;
let isWindows = navigator.platform.startsWith("Win");
if (isWindows) {
// if we are on windows OS we activate the perfectScrollbar function
initScrollbar("sidebar");
initScrollbar("main-panel");
initScrollbar("sidebar-wrapper");
docClasses.add("perfect-scrollbar-on");
} else {
docClasses.add("perfect-scrollbar-off");
}
}
},
mounted() {
this.initScrollbar();
}
};
</script>
<style lang="scss">
$scaleSize: 0.95;
@keyframes zoomIn95 {
from {
opacity: 0;
transform: scale3d($scaleSize, $scaleSize, $scaleSize);
}
to {
opacity: 1;
}
}
.main-panel .zoomIn {
animation-name: zoomIn95;
}
@keyframes zoomOut95 {
from {
opacity: 1;
}
to {
opacity: 0;
transform: scale3d($scaleSize, $scaleSize, $scaleSize);
}
}
.main-panel .zoomOut {
animation-name: zoomOut95;
}
</style>

View File

@@ -50,7 +50,7 @@
<!-- <sidebar-share :background-color.sync="sidebarBackground"> </sidebar-share> -->
<div class="main-panel" :data="sidebarBackground">
<dashboard-navbar></dashboard-navbar>
<router-view name="header"></router-view>
<!-- <router-view name="header"></router-view> -->
<div
:class="{ content: !isFullScreenRoute }"
@@ -91,6 +91,7 @@
import { SlideYDownTransition, ZoomCenterTransition } from 'vue2-transitions';
export default {
components: {
DashboardNavbar,
ContentFooter,

View File

@@ -0,0 +1,10 @@
//If the user does not have a token, we send it to login
//si el usuario no tiene token lo enviamos a login
export default function({ store, redirect }) {
store.dispatch("readToken");
if (!store.state.auth) {
return redirect("/login");
}
}

View File

@@ -0,0 +1,9 @@
//If the user has a token, we send it to index
//Si el usuario tiene token lo enviamos a index
export default function({ store, redirect }) {
store.dispatch('readToken');
if (store.state.auth) {
return redirect('/compras')
}
}

View File

@@ -59,7 +59,7 @@ export default {
// Axios module configuration (https://go.nuxtjs.dev/config-axios)
axios: {
baseURL: "http://127.0.0.1:3001/api"
baseURL: "http://127.0.0.1:4000/api"
},
/*

View File

@@ -2,7 +2,7 @@
<auth-layout class="not-found-page">
<div class="centered">
<h1><i class="not-found-icon nc-icon nc-puzzle-10"></i>404</h1>
<p>The page you requested could not be found.</p>
<p>The page you requested ccc could not be found.</p>
</div>
</auth-layout>
</template>

View File

@@ -1,6 +1,5 @@
<template>
<div>
<div class="row">
<card class="col-12">
<el-table
@@ -10,7 +9,7 @@
!search ||
data.detalle.toLowerCase().includes(search.toLowerCase()) ||
data.fecha.toLowerCase().includes(search.toLowerCase()) ||
data.metodo_pago.toLowerCase().includes(search.toLowerCase()) ||
data.metodopago.toLowerCase().includes(search.toLowerCase()) ||
data.categoria.toLowerCase().includes(search.toLowerCase())
)
"
@@ -22,7 +21,7 @@
</el-TableColumn>
<el-TableColumn prop="valor" label="Valor" sortable> </el-TableColumn>
<el-TableColumn prop="metodo_pago" label="Metodo de pago" sortable>
<el-TableColumn prop="metodopago" label="Metodo de pago" sortable>
</el-TableColumn>
<el-TableColumn prop="categoria" label="Categoria" sortable>
@@ -35,7 +34,7 @@
icon
size="sm"
class="btn-link"
@click="deleteCompra($index)"
@click="deleteCompra(row._id)"
>
<i class="el-icon-delete-solid"></i>
</base-button>
@@ -46,7 +45,7 @@
icon
size="sm"
class="btn-link"
@click="deleteCompra($index)"
@click="deleteCompra($_id)"
>
<i class="el-icon-edit"></i>
</base-button>
@@ -64,22 +63,20 @@
</el-table>
</card>
<Fcompras
<Fcompras
:categorias="categorias"
:metodos_pago="metodos_pago"
:newCompra="newCompra"
:saveCompra="saveCompra"
/>
/>
</div>
</div>
</template>
<script>
import { Table, TableColumn } from "element-ui";
import { Select, Option } from "element-ui";
export default {
middleware: "authenticated",
components: {
[Table.name]: Table,
[TableColumn.name]: TableColumn,
@@ -89,10 +86,10 @@ export default {
data() {
return {
newCompra: {
fecha:"",
fecha: "",
detalle: "",
valor: 0,
metodo_pago: "",
metodopago: "",
categoria: "",
},
compras: [],
@@ -122,27 +119,63 @@ export default {
};
},
mounted() {
this.getDate()
this.newCompra.fecha = this.$store.state.fecha;
this.getCompras();
},
methods: {
getCompras() {
const axiosHeader = {
headers: {
token: this.$store.state.auth.token,
},
};
this.$axios
.get("/compras", axiosHeader)
.then((res) => {
console.log(res.data.data);
this.compras = res.data.data;
})
.catch((e) => console.log(e));
},
saveCompra() {
var compra = JSON.stringify(this.newCompra);
this.compras.push(JSON.parse(compra));
console.log(compra);
const axiosHeader = {
headers: {
token: this.$store.state.auth.token,
},
};
const toSend = this.newCompra;
console.log(axiosHeader.data);
this.$axios
.post("/compra", toSend, axiosHeader)
.then((res) => {
this.clearFormCompra();
console.log(res.data.status);
this.getCompras();
})
.catch((e) => console.log(e));
},
deleteCompra(index) {
this.compras.splice(index, 1);
//console.log(index)
deleteCompra(id) {
const axiosHeader={
headers:{
token: this.$store.state.auth.token,
},
params:{
id:id
}
}
this.$axios.delete("/compra",axiosHeader).then(res=>{
console.log(res.data);
this.getCompras();
}).catch(e => console.log(e))
},
clearFormCompra() {
this.newCompra.detalle = "";
this.newCompra.valor = 0;
this.newCompra.metodopago = "";
this.newCompra.categoria = "";
},
getDate(){
let data = new Date();
let year= data.getFullYear();
let month = (data.getMonth() + 1)<9?"0"+(data.getMonth() + 1):(data.getMonth() + 1)
let day = data.getDate()<9?"0"+data.getDate():data.getDate()
let dataF=`${year}-${month}-${day}`
this.newCompra.fecha=dataF;
}
},
};
</script>

15
APP/pages/index.vue Normal file
View File

@@ -0,0 +1,15 @@
<template>
<div>
<Prueba />
</div>
</template>
<script>
export default {
middleware: 'authenticated',
}
</script>
<style>
</style>

View File

@@ -7,6 +7,7 @@
<script>
export default {
middleware: 'authenticated',
}
</script>

107
APP/pages/login.vue Normal file
View File

@@ -0,0 +1,107 @@
<template>
<div class="container login-page">
<div class="col-lg-4 col-md-6 ml-auto mr-auto">
<card class="card-login card-white">
<template slot="header">
<img src="img//card-info.png" alt="" />
<h1 class="card-title">Finanzas APP</h1>
</template>
<div>
<base-input
name="email"
v-model="user.email"
placeholder="Email"
addon-left-icon="tim-icons icon-email-85"
>
</base-input>
<base-input
name="password"
v-model="user.password"
type="password"
placeholder="Password"
addon-left-icon="tim-icons icon-lock-circle"
>
</base-input>
</div>
<div slot="footer">
<base-button
native-type="submit"
type="info"
class="mb-3"
size="lg"
@click="login()"
block
>
Login
</base-button>
</div>
</card>
</div>
</div>
</template>
<script>
const Cookie = process.client ? require("js-cookie") : undefined;
export default {
middleware: 'notAuthenticated',
name: "login-page",
layout: "auth",
data() {
return {
user: {
email: "",
password: ""
}
};
},
mounted() {
},
methods: {
login() {
this.$axios
.post("/login", this.user)
.then(res => {
//success! - Usuario creado.
//if (res.data.status == "success") {
this.$notify({
type: "success",
icon: "tim-icons icon-check-2",
message: "Success! Welcome " + res.data.userData.name
});
console.log(res.data)
const auth = {
token: res.data.token,
userData: res.data.userData
}
//token to de store - token a la tienda
this.$store.commit('setAuth', auth);
//set auth object in localStorage - Grabamos el token en localStorage
localStorage.setItem('auth', JSON.stringify(auth));
$nuxt.$router.push('/compras');
return;
//}
})
.catch(e => {
this.$notify({
type: "danger",
icon: "tim-icons icon-alert-circle-exc",
message: "Credenciales invalidas :("
});
return;
});
}
}
};
</script>
<style>
.navbar-nav .nav-item p {
line-height: inherit;
margin-left: 5px;
}
</style>

View File

@@ -4,6 +4,7 @@
<script>
export default {
middleware: 'authenticated',
}
</script>

105
APP/pages/register.vue Normal file
View File

@@ -0,0 +1,105 @@
<template>
<div class="container login-page">
<div class="col-lg-4 col-md-6 ml-auto mr-auto">
<card class="card-login card-white">
<template slot="header">
<img src="img//card-info.png" alt="" />
<h1 class="card-title">Finanzas APP</h1>
</template>
<div>
<base-input
name="name"
v-model="user.name"
placeholder="Name"
addon-left-icon="tim-icons icon-badge"
>
</base-input>
<base-input
name="email"
v-model="user.email"
placeholder="Email"
addon-left-icon="tim-icons icon-email-85"
>
</base-input>
<base-input
name="password"
v-model="user.password"
type="password"
placeholder="Password"
addon-left-icon="tim-icons icon-lock-circle"
>
</base-input>
</div>
<div slot="footer">
<base-button
native-type="submit"
type="info"
class="mb-3"
size="lg"
@click="register()"
block
>
Register
</base-button>
<div class="pull-left">
<h6>
<nuxt-link class="link footer-link" to="/login">
login
</nuxt-link>
</h6>
</div>
</div>
</card>
</div>
</div>
</template>
<script>
export default {
middleware: "notAuthenticated",
layout: "auth",
data() {
return {
user: {
name: "",
email: "",
password: "",
},
};
},
methods: {
register() {
this.$axios
.post("/register", this.user)
.then((res) => {
this.$notify({
type: "success",
icon: "tim-icons icon-check-2",
message: "Success! Now you can login...",
});
this.user.name = "";
this.user.password = "";
this.user.email = "";
})
.catch((e) => {
this.$notify({
type: "danger",
icon: "tim-icons icon-alert-circle-exc",
message: "User already exists :(",
});
});
},
},
};
</script>
<style>
.navbar-nav .nav-item p {
line-height: inherit;
margin-left: 5px;
}
</style>

70
APP/store/index.js Normal file
View File

@@ -0,0 +1,70 @@
export const state = () => ({
auth: null,
notifications: [],
fecha: fechaString(),
categorias:[],
metodos_de_pago:[]
});
export const mutations = {
setAuth(state, auth) {
state.auth = auth;
},
setNotifications(state, notifications) {
state.notifications = notifications;
},
setCategorias(state, categorias) {
state.categorias = categorias;
},
};
function fechaString(){
let data = new Date();
let year= data.getFullYear();
let month = (data.getMonth() + 1)<9?"0"+(data.getMonth() + 1):(data.getMonth() + 1)
let day = data.getDate()<9?"0"+data.getDate():data.getDate()
let dataF=`${year}-${month}-${day}`
return dataF;
}
export const actions = {
readToken() {
let auth = null;
try {
auth = JSON.parse(localStorage.getItem("auth"));
} catch (error) {
console.log(err);
}
//saving auth in state
this.commit("setAuth", auth);
},
getCategorias() {
const axiosHeader = {
headers: {
token: this.state.auth.token
}
};
this.$axios.get("/categoria", axiosHeader)
.then(res => {
console.log(res.data.data);
this.commit("setCategorias", res.data.data);
}).catch(error => {
console.log(error);
});
},
}

1
Insomnia_2021-04-24.json Normal file
View File

@@ -0,0 +1 @@
{"_type":"export","__export_format":4,"__export_date":"2021-04-24T16:55:10.126Z","__export_source":"insomnia.desktop.app:v2021.2.2","resources":[{"_id":"req_bacdb6fe62fc41d4a66f9954983df3e0","parentId":"fld_5a6d850875f14063941b6444e621d252","modified":1618790367094,"created":1618790000482,"url":"{{ _.host }}/compras","name":"Compras","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json","description":"","id":"pair_02cecdd51a164372a1c2ad69c152b9c5"},{"name":"token","value":"{{ _.token }}","description":"","id":"pair_10170987714541bdb47b153d97f6dcf2"}],"authentication":{},"metaSortKey":-1618790000482,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_5a6d850875f14063941b6444e621d252","parentId":"wrk_0a6e28fdd90541048b1ff22740cf2f76","modified":1618791644992,"created":1618786993777,"name":"API_FINANZAS","description":"","environment":{"host":"localhost:4000/api","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyRGF0YSI6eyJfaWQiOiI1Y2EwM2MzM2U4MzAzNjAwMTdmOGRkYjkiLCJuYW1lIjoiTWFydGluIENoYXBhcnJvIiwiZW1haWwiOiJtZGNoYXBhcnJvckB1bmFsLmVkdS5jbyIsImRhdGUiOiIyMDE5LTAzLTMxVDA0OjA0OjAzLjMxNVoiLCJfX3YiOjB9LCJpYXQiOjE2MTg3OTE2MDQsImV4cCI6MTYyMTM4MzYwNH0.Zib1CPwU-McovWyq1IsELxuXs1FDlFUNT3MqV_4l_LE"},"environmentPropertyOrder":{"&":["host","token"]},"metaSortKey":-1618786993777,"_type":"request_group"},{"_id":"wrk_0a6e28fdd90541048b1ff22740cf2f76","parentId":null,"modified":1618786939580,"created":1618786939580,"name":"Insomnia","description":"","scope":"collection","_type":"workspace"},{"_id":"req_9b054b25cd8a44fcb69fd3641c1d1964","parentId":"fld_5a6d850875f14063941b6444e621d252","modified":1618791602686,"created":1618788181720,"url":"{{ _.host }}/login","name":"Login","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"email\":\"mdchaparror@unal.edu.co\",\n\t\"password\":\"un260874\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json","description":"","id":"pair_e165853035d54b15ab880335e6c239b4"}],"authentication":{},"metaSortKey":-1618788181720,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_462c83a2830a45a88e220ad467729798","parentId":"fld_5a6d850875f14063941b6444e621d252","modified":1618791147728,"created":1618787053177,"url":"{{ _.host }}/register","name":"Register","description":"Registro de usuarios","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"name\":\"Prueba\",\n\t\"password\":\"un260874\",\n\t\"email\":\"mmunevar@gmail.com\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json","id":"pair_4fae4b5f40e34c3a9405688cf351928e"}],"authentication":{},"metaSortKey":-1618787053178,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"env_90e649a7f8f53834ad95ba7c68334fc9919b0028","parentId":"wrk_0a6e28fdd90541048b1ff22740cf2f76","modified":1618786939670,"created":1618786939670,"name":"Base Environment","data":{},"dataPropertyOrder":null,"color":null,"isPrivate":false,"metaSortKey":1618786939670,"_type":"environment"},{"_id":"jar_90e649a7f8f53834ad95ba7c68334fc9919b0028","parentId":"wrk_0a6e28fdd90541048b1ff22740cf2f76","modified":1618786939676,"created":1618786939676,"name":"Default Jar","cookies":[],"_type":"cookie_jar"},{"_id":"spc_54809161a8294aa3ac1b5699085bb91d","parentId":"wrk_0a6e28fdd90541048b1ff22740cf2f76","modified":1618786939584,"created":1618786939584,"fileName":"Insomnia","contents":"","contentType":"yaml","_type":"api_spec"}]}

6436
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -19,4 +19,44 @@ router.get("/compras", checkAuth, async (req, res) => {
)
});
router.post("/compra", checkAuth, async (req, res) => {
const { fecha, detalle, valor, metodopago, categoria } = req.body;
const newCompra = new Compra({
fecha,
detalle,
valor,
metodopago,
categoria,
});
console.log(newCompra)
newCompra.user = req.userData._id;
await newCompra.save();
res.json({
status:"OK"
})
});
router.delete("/compra", checkAuth, async (req, res) => {
try{
const userId = req.userData._id;
const id = req.query.id;
const resultado = await Compra.deleteOne({user:userId,_id:id});
return res.json({status:"ok",data: resultado})
}
catch(error){
console.log(error);
return res.status(500).json({status:"fail",error:error})
}
});
module.exports = router;