
App.vue and replace the image that was before. In addition, edit the styles: <style lang="scss"> @import "./assets/styles"; body { background: url('./assets/images/background.jpg') no-repeat center center fixed; background-size: cover; &:after { content: ''; position: fixed; width: 100%; height: 100%; top: 0; left: 0; background-color: $background-tint; opacity: .3; z-index: -1; } .application { background: none; } } </style> background-size: cover property and the following construction: .application { background: none; } App.vue file, App.vue 's make some changes to the template: <template> <v-app> <v-container> <router-view/> </v-container> </v-app> </template> div id="app" to a v-app , this is the main component from Vuetify.Authentication.vue component file and make some changes to the styles: <style lang="scss"> @import "./../../../assets/styles"; .l-auth { background-color: $background-color; padding: 15px; margin: 45px auto; min-width: 272px; max-width: 320px; animation: bounceIn 1s forwards ease; label, input, .icon { color: #29b6f6!important; } .input-group__details { &:before { background-color: $border-color-input !important; } } } .l-signup { @extend .l-auth; animation: slideInFromLeft 1s forwards ease; } </style> v-app . In addition, we expanded the l-auth class, since our l-signup class is exactly the same, the differences are only in the animation. As a result, the application will look like this:
index.js , which is located in the Authentication folder. First, we will make changes to the authenticate method: authenticate (context, credentials, redirect) { Axios.post(`${BudgetManagerAPI}/api/v1/auth`, credentials) .then(({data}) => { context.$cookie.set('token', data.token, '1D') context.$cookie.set('user_id', data.user._id, '1D') context.validLogin = true this.user.authenticated = true if (redirect) router.push(redirect) }).catch(({response: {data}}) => { context.snackbar = true context.message = data.message }) }, data object, we extract the user ID from it, since we intend to store this id .signup method: signup (context, credentials, redirect) { Axios.post(`${BudgetManagerAPI}/api/v1/signup`, credentials) .then(() => { context.validSignUp = true this.authenticate(context, credentials, redirect) }).catch(({response: {data}}) => { context.snackbar = true context.message = data.message }) }, authenticate method.signup method, add the signout method: signout (context, redirect) { context.$cookie.delete('token') context.$cookie.delete('user_id') this.user.authenticated = false if (redirect) router.push(redirect) }, signout method, signout make small changes to the checkAuthentication method: checkAuthentication () { const token = document.cookie this.user.authenticated = !!token }, token constant to a boolean value, use the ternary comparison operator. this.user.authenticated = token ? true : false components folder and create a file Header.vue : <template> <header class="l-header-container"> <v-layout row wrap> <v-flex xs12 md5> <v-text-field v-model="search" label="Search" append-icon="search" color="light-blue lighten-1"> </v-text-field> </v-flex> <v-flex xs12 offset-md1 md1> <v-btn block color="light-blue lighten-1">Clients</v-btn> </v-flex> <v-flex xs12 offset-md1 md2> <v-select label="Status" color="light-blue lighten-1" v-model="status" :items="statusItems" single-line> </v-select> </v-flex> <v-flex xs12 offset-md1 md1> <v-btn block color="red lighten-1 white--text" @click.native="submitSignout()">Sign out</v-btn> </v-flex> </v-layout> </header> </template> <script> import Authentication from '@/components/pages/Authentication' export default { data () { return { search: '', status: '', statusItems: [ 'All', 'Approved', 'Denied', 'Waiting', 'Writing', 'Editing' ] } }, methods: { submitSignout () { Authentication.signout(this, '/login') } } } </script> <style lang="scss"> @import "./../assets/styles"; .l-header-container { background-color: $background-color; margin: 0 auto; padding: 0 15px; min-width: 272px; label, input, .icon, .input-group__selections__comma { color: #29b6f6!important; } .input-group__details { &:before { background-color: $border-color-input !important; } } .btn { margin-top: 15px; } } </style> search , a button to go to the clients page, which we will deal with later, a switch to filter documents and a button to exit the system._variables template, add color information there, and set the background-color transparency to 0.7 : // Colors $background-tint: #1734C1; $background-color: rgba(0, 0, 0, .7); $border-color-input: rgba(255, 255, 255, 0.42); index.js file in the router folder and bring it to this form: // Pages import Home from '@/components/pages/Home' import Authentication from '@/components/pages/Authentication/Authentication' // Global components import Header from '@/components/Header' // Register components Vue.component('app-header', Header) Vue.use(Router) Home component, then the Header component, and then register it, keeping in mind that the @ sign when using the webpack is a pseudonym for the src folder. App-header is the tag name that we will use to output the Header component. const router = new Router({ routes: [ { path: '/', name: 'Home', components: { default: Home, header: Header }, meta: { requiredAuth: true } }, { path: '/login', name: 'Authentication', component: Authentication } ] }) Home , and also include the Header component on this page. Please note that here we do not make any changes to the route to enter the system. The Header component representing the page Header is not needed there.Header component later, but at this stage of work we are satisfied with its current state.pages folder and open the Home.vue file: <template> <main class="l-home-page"> <app-header></app-header> <div class="l-home"> <h4 class="white--text text-xs-center my-0"> Focus Budget Manager </h4> <budget-list> <budget-list-header slot="budget-list-header"></budget-list-header> <budget-list-body slot="budget-list-body" :budgets="budgets"></budget-list-body> </budget-list> </div> </main> </template> <script> import Axios from 'axios' import Authentication from '@/components/pages/Authentication' import BudgetListHeader from './../Budget/BudgetListHeader' import BudgetListBody from './../Budget/BudgetListBody' const BudgetManagerAPI = `http://${window.location.hostname}:3001` export default { components: { 'budget-list-header': BudgetListHeader, 'budget-list-body': BudgetListBody }, data () { return { budgets: [] } }, mounted () { this.getAllBudgets() }, methods: { getAllBudgets () { Axios.get(`${BudgetManagerAPI}/api/v1/budget`, { headers: { 'Authorization': Authentication.getAuthenticationHeader(this) }, params: { user_id: this.$cookie.get('user_id') } }).then(({data}) => (this.budgets = data)) } } } </script> <style lang="scss" scoped> @import "./../../assets/styles"; .l-home { background-color: $background-color; margin: 25px auto; padding: 15px; min-width: 272px; } </style> h4 tag, containing the name of the application. The following classes are assigned to it:white--text : used to color the text in white.text-xs-center : used to center the text along the x axis.my-0 : used to set the y axis fields to 0 .budget-list component, which we will create below. It includes the budget-list-header and budget-list-body components, which play the role of data slots.budget-list-body array of financial budgets documents, the data from which are extracted when the component is mounted. We pass the Authorization header, which gives us the opportunity to work with the API. It is also transmitted here as a parameter, user_id , which makes it possible to indicate which user is requesting data.components folder and create a new folder called Budget in it. Inside this folder, create a component file BudgetListHeader.vue : <template> <header class="l-budget-header"> <div class="md-budget-header white--text">Client</div> <div class="md-budget-header white--text">Title</div> <div class="md-budget-header white--text">Status</div> <div class="md-budget-header white--text">Actions</div> </header> </template> <script> export default {} </script> <style lang="scss"> @import "./../../assets/styles"; .l-budget-header { display: none; width: 100%; @media (min-width: 601px) { margin: 25px 0 0; display: flex; } .md-budget-header { width: 100%; background-color: $background-color; border: 1px solid $border-color-input; padding: 0 15px; display: flex; height: 45px; align-items: center; justify-content: center; font-size: 22px; @media (min-width: 601px) { justify-content: flex-start; } } } </style> BudgetListBody.vue : <template> <section class="l-budget-body"> <div class="md-budget" v-if="budgets != null" v-for="budget in budgets"> <div class="md-budget-info white--text">{{ budget.client }}</div> <div class="md-budget-info white--text">{{ budget.title }}</div> <div class="md-budget-info white--text">{{ budget.state }}</div> <div class="l-budget-actions"> <v-btn small flat color="light-blue lighten-1"> <v-icon small>visibility</v-icon> </v-btn> <v-btn small flat color="yellow accent-1"> <v-icon>mode_edit</v-icon> </v-btn> <v-btn small flat color="red lighten-1"> <v-icon>delete_forever</v-icon> </v-btn> </div> </div> </section> </template> <script> export default { props: ['budgets'] } </script> <style lang="scss"> @import "./../../assets/styles"; .l-budget-body { display: flex; flex-direction: column; .md-budget { width: 100%; display: flex; flex-direction: column; margin: 15px 0; @media (min-width: 960px) { flex-direction: row; margin: 0; } .md-budget-info { flex-basis: 25%; width: 100%; background-color: rgba(0, 175, 255, 0.45); border: 1px solid $border-color-input; padding: 0 15px; display: flex; height: 35px; align-items: center; justify-content: center; &:first-of-type, &:nth-of-type(2) { text-transform: capitalize; } &:nth-of-type(3) { text-transform: uppercase; } @media (min-width: 601px) { justify-content: flex-start; } } .l-budget-actions { flex-basis: 25%; display: flex; background-color: rgba(0, 175, 255, 0.45); border: 1px solid $border-color-input; align-items: center; justify-content: center; .btn { min-width: 45px !important; margin: 0 5px !important; } } } } </style> BudgetList.vue file in the same folder and add the code of the corresponding component to it: <template> <section class="l-budget-list-container"> <slot name="budget-list-header"></slot> <slot name="budget-list-body"></slot> </section> </template> <script> export default {} </script> slot tags. In them we deduce components. These tags are called named slots.BudgetList component to the router: // ... // Global components import Header from '@/components/Header' import BudgetList from '@/components/Budget/BudgetList' // Register components Vue.component('app-header', Header) Vue.component('budget-list', BudgetList) // ... const router = new Router({ routes: [ { path: '/', name: 'Home', components: { default: Home, header: Header, budgetList: BudgetList }, meta: { requiredAuth: true } }, { path: '/login', name: 'Authentication', component: Authentication } ] }) // ... export default router Home component to use them.user.js from the services/BudgetManagerAPI/app/api folder and bring it to this form: const mongoose = require('mongoose'); const api = {}; api.signup = (User) => (req, res) => { if (!req.body.username || !req.body.password) res.json({ success: false, message: 'Please, pass an username and password.' }); else { const user = new User({ username: req.body.username, password: req.body.password }); user.save(error => { if (error) return res.status(400).json({ success: false, message: 'Username already exists.' }); res.json({ success: true, message: 'Account created successfully' }); }); } } module.exports = api; setup and index methods. The setup method is no longer needed, since we already have the means to create accounts. The index method is not required due to the fact that we are not going to display a list of all registered users. In addition, we got rid of console.log in the signup method, and from the empty array of clients in the method of creating a new user.user.js file, which is stored in the services/BudgetManagerAPI/app/routes folder: const models = require('@BudgetManager/app/setup'); module.exports = (app) => { const api = app.BudgetManagerAPI.app.api.user; app.route('/api/v1/signup') .post(api.signup(models.User)); } models folder, which is located at BudgetManagerAPI/app/ and make some improvements in the model. Open the file user.js Here we are going to modify the user data scheme: const Schema = mongoose.Schema({ username: { type: String, unique: true, required: true }, password: { type: String, required: true } }); client.js file: const mongoose = require('mongoose'); const Schema = mongoose.Schema({ name: { type: String, required: true }, email: { type: String, required: true }, phone: { type: String, required: true }, user_id: { type: mongoose.Schema.Types.ObjectId, ref: 'User' } }); mongoose.model('Client', Schema); budget.js file: const mongoose = require('mongoose'); const Schema = mongoose.Schema({ client: { type: String, required: true }, state: { type: String, required: true }, title: { type: String, required: true }, total_price: { type: Number, required: true }, client_id: { type: mongoose.Schema.Types.ObjectId, ref: 'Client' }, items: [{}] }); mongoose.model('Budget', Schema); ref and ObjectID .index.js file from the setup folder and bring it to this form: const mongoose = require('mongoose'), UserModel = require('@BudgetManagerModels/user'), BudgetModel = require('@BudgetManagerModels/budget'), ClientModel = require('@BudgetManagerModels/client'); const models = { User: mongoose.model('User'), Budget: mongoose.model('Budget'), Client: mongoose.model('Client') } module.exports = models; api folder and create a new client.js file client.js : const mongoose = require('mongoose'); const api = {}; api.store = (User, Client, Token) => (req, res) => { if (Token) { const client = new Client({ user_id: req.body.user_id, name: req.body.name, email: req.body.email, phone: req.body.phone, }); client.save(error => { if (error) return res.status(400).json(error); res.status(200).json({ success: true, message: "Client registration successfull" }); }) } else return res.status(403).send({ success: false, message: 'Unauthorized' }); } api.getAll = (User, Client, Token) => (req, res) => { if (Token) { Client.find({ user_id: req.query.user_id }, (error, client) => { if (error) return res.status(400).json(error); res.status(200).json(client); return true; }) } else return res.status(403).send({ success: false, message: 'Unauthorized' }); } module.exports = api; budget.js : const mongoose = require('mongoose'); const api = {}; api.store = (User, Budget, Client, Token) => (req, res) => { if (Token) { Client.findOne({ _id: req.body.client_id }, (error, client) => { if (error) res.status(400).json(error); if (client) { const budget = new Budget({ client_id: req.body.client_id, user_id: req.body.user_id, client: client.name, state: req.body.state, title: req.body.title, total_price: req.body.total_price, items: req.body.items }); budget.save(error => { if (error) res.status(400).json(error) res.status(200).json({ success: true, message: "Budget registered successfully" }) }) } else { res.status(400).json({ success: false, message: "Invalid client" }) } }) } else return res.status(403).send({ success: false, message: 'Unauthorized' }); } api.getAll = (User, Budget, Token) => (req, res) => { if (Token) { Budget.find({ user_id: req.query.user_id }, (error, budget) => { if (error) return res.status(400).json(error); res.status(200).json(budget); return true; }) } else return res.status(403).send({ success: false, message: 'Unauthorized' }); } api.getAllFromClient = (User, Budget, Token) => (req, res) => { if (Token) { Budget.find({ client_id: req.query.client_id }, (error, budget) => { if (error) return res.status(400).json(error); res.status(200).json(budget); return true; }) } else return res.status(403).send({ success: false, message: 'Unauthorized' }); } module.exports = api; routes folder and create a budget.js file budget.js : module.exports = (app) => { const api = app.BudgetManagerAPI.app.api.budget; app.route('/api/v1/budget') .post(passport.authenticate('jwt', config.session), api.store(models.User, models.Budget, models.Client, app.get('budgetsecret'))) .get(passport.authenticate('jwt', config.session), api.getAll(models.User, models.Budget, app.get('budgetsecret'))) .get(passport.authenticate('jwt', config.session), api.getAllFromClient(models.User, models.Budget, app.get('budgetsecret'))) } client.js file: const passport = require('passport'), config = require('@config'), models = require('@BudgetManager/app/setup'); module.exports = (app) => { const api = app.BudgetManagerAPI.app.api.client; app.route('/api/v1/client') .post(passport.authenticate('jwt', config.session), api.store(models.User, models.Client, app.get('budgetsecret'))) .get(passport.authenticate('jwt', config.session), api.getAll(models.User, models.Client, app.get('budgetsecret'))); } passport.authenticate method, and then the API methods with passing the models and the secret key to them.
Source: https://habr.com/ru/post/341874/
All Articles