├── README.md
├── views
├── partials
│ ├── _sidebar.handlebars
│ ├── _footer.handlebars
│ └── _navbar.handlebars
├── pages
│ ├── categoria
│ │ ├── register.handlebars
│ │ └── _list.handlebars
│ ├── errors
│ │ ├── 500.handlebars
│ │ └── 404.handlebars
│ ├── produtos
│ │ ├── products.handlebars
│ │ └── product-datail.handlebars
│ └── user
│ │ ├── _login.handlebars
│ │ ├── _user-edit.handlebars
│ │ ├── _users-list.handlebars
│ │ └── _register.handlebars
├── layouts
│ └── main.handlebars
└── home.handlebars
├── .gitignore
├── .prettierrc.json
├── public
├── css
│ ├── .DS_Store
│ └── responsive.css
├── images
│ ├── voce.jpg
│ ├── items
│ │ ├── 1.jpg
│ │ ├── 2.jpg
│ │ ├── 4.jpg
│ │ └── 7.jpg
│ └── banners
│ │ └── bg-cpu.jpg
├── fonts
│ └── fontawesome
│ │ ├── .DS_Store
│ │ ├── webfonts
│ │ ├── fa-solid-900.eot
│ │ ├── fa-solid-900.ttf
│ │ ├── fa-brands-400.eot
│ │ ├── fa-brands-400.ttf
│ │ ├── fa-brands-400.woff
│ │ ├── fa-regular-400.eot
│ │ ├── fa-regular-400.ttf
│ │ ├── fa-solid-900.woff
│ │ ├── fa-solid-900.woff2
│ │ ├── fa-brands-400.woff2
│ │ ├── fa-regular-400.woff
│ │ └── fa-regular-400.woff2
│ │ ├── scss
│ │ ├── _fixed-width.scss
│ │ ├── _screen-reader.scss
│ │ ├── _core.scss
│ │ ├── _animated.scss
│ │ ├── _list.scss
│ │ ├── _larger.scss
│ │ ├── fontawesome.scss
│ │ ├── _bordered-pulled.scss
│ │ ├── _stacked.scss
│ │ ├── fa-brands.scss
│ │ ├── fa-solid.scss
│ │ ├── fa-regular.scss
│ │ ├── _rotated-flipped.scss
│ │ ├── _mixins.scss
│ │ └── _variables.scss
│ │ └── css
│ │ ├── fa-brands.min.css
│ │ ├── fa-solid.min.css
│ │ ├── fa-regular.min.css
│ │ ├── fa-brands.css
│ │ ├── fa-solid.css
│ │ ├── fa-regular.css
│ │ ├── fontawesome.min.css
│ │ └── fontawesome-all.min.css
├── plugins
│ ├── slickslider
│ │ ├── ajax-loader.gif
│ │ ├── fonts
│ │ │ ├── slick.eot
│ │ │ ├── slick.ttf
│ │ │ ├── slick.woff
│ │ │ └── slick.svg
│ │ ├── slick.css
│ │ └── slick-theme.css
│ ├── owlcarousel
│ │ └── assets
│ │ │ ├── ajax-loader.gif
│ │ │ ├── owl.video.play.png
│ │ │ ├── owl.theme.default.min.css
│ │ │ ├── owl.theme.green.min.css
│ │ │ ├── owl.theme.green.css
│ │ │ ├── owl.theme.default.css
│ │ │ ├── owl.carousel.min.css
│ │ │ └── owl.carousel.css
│ ├── prism
│ │ ├── prism.css
│ │ └── prism.js
│ └── fancybox
│ │ └── fancybox.min.css
└── js
│ └── script.js
├── .editorconfig
├── src
├── app.js
├── env.js
├── routes
│ ├── product.routes.js
│ └── user.routes.js
├── models
│ ├── customer.js
│ ├── user.js
│ ├── categoria.js
│ ├── order.js
│ └── product.js
├── middlewares
│ ├── authentication
│ │ └── jwt.js
│ └── authentication.js
├── controller
│ ├── product.js
│ ├── category.js
│ └── user.js
├── repositories
│ ├── product.js
│ └── user.js
└── config
│ └── server.js
└── package.json
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/views/partials/_sidebar.handlebars:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/views/pages/categoria/register.handlebars:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | yarn.lock
3 | package-lock.json
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "semi": true
4 | }
--------------------------------------------------------------------------------
/public/css/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/css/.DS_Store
--------------------------------------------------------------------------------
/public/images/voce.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/images/voce.jpg
--------------------------------------------------------------------------------
/public/images/items/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/images/items/1.jpg
--------------------------------------------------------------------------------
/public/images/items/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/images/items/2.jpg
--------------------------------------------------------------------------------
/public/images/items/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/images/items/4.jpg
--------------------------------------------------------------------------------
/public/images/items/7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/images/items/7.jpg
--------------------------------------------------------------------------------
/public/images/banners/bg-cpu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/images/banners/bg-cpu.jpg
--------------------------------------------------------------------------------
/public/fonts/fontawesome/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/.DS_Store
--------------------------------------------------------------------------------
/public/plugins/slickslider/ajax-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/plugins/slickslider/ajax-loader.gif
--------------------------------------------------------------------------------
/public/plugins/slickslider/fonts/slick.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/plugins/slickslider/fonts/slick.eot
--------------------------------------------------------------------------------
/public/plugins/slickslider/fonts/slick.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/plugins/slickslider/fonts/slick.ttf
--------------------------------------------------------------------------------
/public/plugins/slickslider/fonts/slick.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/plugins/slickslider/fonts/slick.woff
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | charset = utf-8
7 | trim_trailing_whitespace = false
8 | insert_final_newline = false
--------------------------------------------------------------------------------
/public/fonts/fontawesome/webfonts/fa-solid-900.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/webfonts/fa-solid-900.eot
--------------------------------------------------------------------------------
/public/fonts/fontawesome/webfonts/fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/webfonts/fa-solid-900.ttf
--------------------------------------------------------------------------------
/public/plugins/owlcarousel/assets/ajax-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/plugins/owlcarousel/assets/ajax-loader.gif
--------------------------------------------------------------------------------
/public/fonts/fontawesome/webfonts/fa-brands-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/webfonts/fa-brands-400.eot
--------------------------------------------------------------------------------
/public/fonts/fontawesome/webfonts/fa-brands-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/webfonts/fa-brands-400.ttf
--------------------------------------------------------------------------------
/public/fonts/fontawesome/webfonts/fa-brands-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/webfonts/fa-brands-400.woff
--------------------------------------------------------------------------------
/public/fonts/fontawesome/webfonts/fa-regular-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/webfonts/fa-regular-400.eot
--------------------------------------------------------------------------------
/public/fonts/fontawesome/webfonts/fa-regular-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/webfonts/fa-regular-400.ttf
--------------------------------------------------------------------------------
/public/fonts/fontawesome/webfonts/fa-solid-900.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/webfonts/fa-solid-900.woff
--------------------------------------------------------------------------------
/public/fonts/fontawesome/webfonts/fa-solid-900.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/webfonts/fa-solid-900.woff2
--------------------------------------------------------------------------------
/public/plugins/owlcarousel/assets/owl.video.play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/plugins/owlcarousel/assets/owl.video.play.png
--------------------------------------------------------------------------------
/public/fonts/fontawesome/webfonts/fa-brands-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/webfonts/fa-brands-400.woff2
--------------------------------------------------------------------------------
/public/fonts/fontawesome/webfonts/fa-regular-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/webfonts/fa-regular-400.woff
--------------------------------------------------------------------------------
/public/fonts/fontawesome/webfonts/fa-regular-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deyvisonborges/ecommerce-js-nodejs-mongodb/HEAD/public/fonts/fontawesome/webfonts/fa-regular-400.woff2
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/_fixed-width.scss:
--------------------------------------------------------------------------------
1 | // Fixed Width Icons
2 | // -------------------------
3 | .#{$fa-css-prefix}-fw {
4 | text-align: center;
5 | width: (20em / 16);
6 | }
7 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/_screen-reader.scss:
--------------------------------------------------------------------------------
1 | // Screen Readers
2 | // -------------------------
3 |
4 | .sr-only { @include sr-only; }
5 | .sr-only-focusable { @include sr-only-focusable; }
6 |
--------------------------------------------------------------------------------
/views/partials/_footer.handlebars:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const app = require('./config/server');
4 | const environments = require('./env');
5 |
6 | const port = environments.api.port;
7 | const host = environments.api.host;
8 |
9 | app.listen(environments.api.port, () => {
10 | console.log(`${host}:${port}`);
11 | });
12 |
--------------------------------------------------------------------------------
/src/env.js:
--------------------------------------------------------------------------------
1 | const environments = {
2 | api: {
3 | port: 3000,
4 | host: 'localhost',
5 | },
6 | database: {
7 | connection: process.env.connection || 'mongodb://127.0.0.1:27017/ecommerce',
8 | },
9 | authenticationToken: {
10 | secret: '232ioh3po4u23h42e23e03023ieh230he23',
11 | },
12 | };
13 |
14 | module.exports = environments;
15 |
--------------------------------------------------------------------------------
/src/routes/product.routes.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const express = require('express');
4 | const productRoutes = express.Router();
5 | const productControllers = require('../controller/product');
6 |
7 | productRoutes.get('/', productControllers.getAll);
8 | productRoutes.post('/cadastro', productControllers.create);
9 |
10 | module.exports = productRoutes;
11 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/_core.scss:
--------------------------------------------------------------------------------
1 | // Base Class Definition
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix},
5 | .fas,
6 | .far,
7 | .fal,
8 | .fab {
9 | -moz-osx-font-smoothing: grayscale;
10 | -webkit-font-smoothing: antialiased;
11 | display: inline-block;
12 | font-style: normal;
13 | font-variant: normal;
14 | text-rendering: auto;
15 | line-height: 1;
16 | }
17 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/_animated.scss:
--------------------------------------------------------------------------------
1 | // Animated Icons
2 | // --------------------------
3 |
4 | .#{$fa-css-prefix}-spin {
5 | animation: fa-spin 2s infinite linear;
6 | }
7 |
8 | .#{$fa-css-prefix}-pulse {
9 | animation: fa-spin 1s infinite steps(8);
10 | }
11 |
12 | @keyframes fa-spin {
13 | 0% {
14 | transform: rotate(0deg);
15 | }
16 |
17 | 100% {
18 | transform: rotate(360deg);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/_list.scss:
--------------------------------------------------------------------------------
1 | // List Icons
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-ul {
5 | list-style-type: none;
6 | margin-left: $fa-li-width * 5/4;
7 | padding-left: 0;
8 |
9 | > li { position: relative; }
10 | }
11 |
12 | .#{$fa-css-prefix}-li {
13 | left: -$fa-li-width;
14 | position: absolute;
15 | text-align: center;
16 | width: $fa-li-width;
17 | line-height: inherit;
18 | }
19 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/_larger.scss:
--------------------------------------------------------------------------------
1 | // Icon Sizes
2 | // -------------------------
3 |
4 | // makes the font 33% larger relative to the icon container
5 | .#{$fa-css-prefix}-lg {
6 | font-size: (4em / 3);
7 | line-height: (3em / 4);
8 | vertical-align: -.0667em;
9 | }
10 |
11 | .#{$fa-css-prefix}-xs {
12 | font-size: .75em;
13 | }
14 |
15 | .#{$fa-css-prefix}-sm {
16 | font-size: .875em;
17 | }
18 |
19 | @for $i from 1 through 10 {
20 | .#{$fa-css-prefix}-#{$i}x {
21 | font-size: $i * 1em;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/fontawesome.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com
3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @import 'variables';
6 | @import 'mixins';
7 | @import 'core';
8 | @import 'larger';
9 | @import 'fixed-width';
10 | @import 'list';
11 | @import 'bordered-pulled';
12 | @import 'animated';
13 | @import 'rotated-flipped';
14 | @import 'stacked';
15 | @import 'icons';
16 | @import 'screen-reader';
17 |
--------------------------------------------------------------------------------
/src/models/customer.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const mongoose = require('mongoose');
4 | const schema = mongoose.Schema;
5 |
6 | const customer_model = new schema(
7 | {
8 | name: {
9 | type: String,
10 | required: true,
11 | },
12 | email: {
13 | type: String,
14 | required: true,
15 | },
16 | password: {
17 | type: String,
18 | required: true,
19 | },
20 | },
21 | { versionKey: false }
22 | );
23 |
24 | module.exports = mongoose.model('Customer', customer_model);
25 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/_bordered-pulled.scss:
--------------------------------------------------------------------------------
1 | // Bordered & Pulled
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-border {
5 | border: solid .08em $fa-border-color;
6 | border-radius: .1em;
7 | padding: .2em .25em .15em;
8 | }
9 |
10 | .#{$fa-css-prefix}-pull-left { float: left; }
11 | .#{$fa-css-prefix}-pull-right { float: right; }
12 |
13 | .#{$fa-css-prefix},
14 | .fas,
15 | .far,
16 | .fal,
17 | .fab {
18 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; }
19 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; }
20 | }
21 |
--------------------------------------------------------------------------------
/views/pages/categoria/_list.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{#each categorias}}
5 |
6 |
7 |
{{titulo}}
8 |
{{descricao}}
9 |
10 |
11 | {{else}}
12 |
13 |
14 |
Nenhuma categoria encontrada!
15 |
16 |
17 | {{/each}}
18 |
19 |
--------------------------------------------------------------------------------
/src/middlewares/authentication/jwt.js:
--------------------------------------------------------------------------------
1 | const cookie = require('js-cookie');
2 |
3 |
4 | const authorize = (SECRET_AUTH) => async (req, res, next) => {
5 | try {
6 | if (!SECRET_AUTH) {
7 | throw new Error('Security token not injected');
8 | } else {
9 | const headerToken = req.headers['authorization'];
10 | const localToken = await cookie.get('login');
11 |
12 | if (!headerToken || !localToken) {
13 | throw new Error('Token not found');
14 | }
15 | return next();
16 | }
17 | } catch (err) {
18 | next(err.message);
19 | }
20 | };
21 |
22 | module.exports = {
23 | authorize,
24 | };
25 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/_stacked.scss:
--------------------------------------------------------------------------------
1 | // Stacked Icons
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-stack {
5 | display: inline-block;
6 | height: 2em;
7 | line-height: 2em;
8 | position: relative;
9 | vertical-align: middle;
10 | width: 2em;
11 | }
12 |
13 | .#{$fa-css-prefix}-stack-1x,
14 | .#{$fa-css-prefix}-stack-2x {
15 | left: 0;
16 | position: absolute;
17 | text-align: center;
18 | width: 100%;
19 | }
20 |
21 | .#{$fa-css-prefix}-stack-1x {
22 | line-height: inherit;
23 | }
24 |
25 | .#{$fa-css-prefix}-stack-2x {
26 | font-size: 2em;
27 | }
28 |
29 | .#{$fa-css-prefix}-inverse {
30 | color: $fa-inverse;
31 | }
32 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/css/fa-brands.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com
3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @font-face{font-family:Font Awesome\ 5 Brands;font-style:normal;font-weight:400;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:Font Awesome\ 5 Brands}
--------------------------------------------------------------------------------
/public/fonts/fontawesome/css/fa-solid.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com
3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @font-face{font-family:Font Awesome\ 5 Free;font-style:normal;font-weight:900;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:Font Awesome\ 5 Free;font-weight:900}
--------------------------------------------------------------------------------
/public/fonts/fontawesome/css/fa-regular.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com
3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @font-face{font-family:Font Awesome\ 5 Free;font-style:normal;font-weight:400;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.far{font-family:Font Awesome\ 5 Free;font-weight:400}
--------------------------------------------------------------------------------
/public/fonts/fontawesome/css/fa-brands.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com
3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @font-face {
6 | font-family: 'Font Awesome 5 Brands';
7 | font-style: normal;
8 | font-weight: normal;
9 | src: url("../webfonts/fa-brands-400.eot");
10 | src: url("../webfonts/fa-brands-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.woff") format("woff"), url("../webfonts/fa-brands-400.ttf") format("truetype"), url("../webfonts/fa-brands-400.svg#fontawesome") format("svg"); }
11 |
12 | .fab {
13 | font-family: 'Font Awesome 5 Brands'; }
14 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/css/fa-solid.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com
3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @font-face {
6 | font-family: 'Font Awesome 5 Free';
7 | font-style: normal;
8 | font-weight: 900;
9 | src: url("../webfonts/fa-solid-900.eot");
10 | src: url("../webfonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.woff") format("woff"), url("../webfonts/fa-solid-900.ttf") format("truetype"), url("../webfonts/fa-solid-900.svg#fontawesome") format("svg"); }
11 |
12 | .fa,
13 | .fas {
14 | font-family: 'Font Awesome 5 Free';
15 | font-weight: 900; }
16 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/css/fa-regular.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com
3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @font-face {
6 | font-family: 'Font Awesome 5 Free';
7 | font-style: normal;
8 | font-weight: 400;
9 | src: url("../webfonts/fa-regular-400.eot");
10 | src: url("../webfonts/fa-regular-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.woff") format("woff"), url("../webfonts/fa-regular-400.ttf") format("truetype"), url("../webfonts/fa-regular-400.svg#fontawesome") format("svg"); }
11 |
12 | .far {
13 | font-family: 'Font Awesome 5 Free';
14 | font-weight: 400; }
15 |
--------------------------------------------------------------------------------
/src/controller/product.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Produto = require('../repositories/product');
4 |
5 | // criando produto
6 | exports.create = async (req, res, next) => {
7 | try {
8 | const tags = req.body.tag;
9 | const produtoExiste = Produto.verifyProduct(req.body);
10 | if (!produtoExiste) {
11 | await Produto.create(req.body);
12 | return res.send('Produto cadastrado com sucesso!');
13 | } else {
14 | return res.send('Esse produto já foi cadastrado!');
15 | }
16 | } catch (err) {
17 | next(err);
18 | }
19 | };
20 |
21 | // buscando produtos
22 | exports.getAll = async (req, res, next) => {
23 | try {
24 | const products = await Produto.getAll();
25 | return res.json(products);
26 | } catch (err) {
27 | next(err);
28 | }
29 | };
30 |
--------------------------------------------------------------------------------
/src/models/user.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 |
3 | const usuario_model = new mongoose.Schema(
4 | {
5 | nome: {
6 | trim: true,
7 | createIndexes: true,
8 | required: true,
9 | type: String,
10 | },
11 | email: {
12 | type: String,
13 | unique: true,
14 | required: true,
15 | lowercase: true,
16 | },
17 | senha: {
18 | type: String,
19 | required: true,
20 | select: false, // pra nao retornar a senha quando for uma consulta publica
21 | },
22 | },
23 | { versionKey: false }
24 | );
25 |
26 | /*
27 | usuario_model.pre('save', async next => {
28 | const hash = await crypt.hash(this.senha, 10)
29 | this.senha = hash
30 | next()
31 | }) */
32 | module.exports = mongoose.model('Usuario', usuario_model);
33 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/fa-brands.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com
3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @import 'variables';
6 |
7 | @font-face {
8 | font-family: 'Font Awesome 5 Brands';
9 | font-style: normal;
10 | font-weight: normal;
11 | src: url('#{$fa-font-path}/fa-brands-400.eot');
12 | src: url('#{$fa-font-path}/fa-brands-400.eot?#iefix') format('embedded-opentype'),
13 | url('#{$fa-font-path}/fa-brands-400.woff2') format('woff2'),
14 | url('#{$fa-font-path}/fa-brands-400.woff') format('woff'),
15 | url('#{$fa-font-path}/fa-brands-400.ttf') format('truetype'),
16 | url('#{$fa-font-path}/fa-brands-400.svg#fontawesome') format('svg');
17 | }
18 |
19 | .fab {
20 | font-family: 'Font Awesome 5 Brands';
21 | }
22 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/fa-solid.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com
3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @import 'variables';
6 |
7 | @font-face {
8 | font-family: 'Font Awesome 5 Free';
9 | font-style: normal;
10 | font-weight: 900;
11 | src: url('#{$fa-font-path}/fa-solid-900.eot');
12 | src: url('#{$fa-font-path}/fa-solid-900.eot?#iefix') format('embedded-opentype'),
13 | url('#{$fa-font-path}/fa-solid-900.woff2') format('woff2'),
14 | url('#{$fa-font-path}/fa-solid-900.woff') format('woff'),
15 | url('#{$fa-font-path}/fa-solid-900.ttf') format('truetype'),
16 | url('#{$fa-font-path}/fa-solid-900.svg#fontawesome') format('svg');
17 | }
18 |
19 | .fa,
20 | .fas {
21 | font-family: 'Font Awesome 5 Free';
22 | font-weight: 900;
23 | }
24 |
--------------------------------------------------------------------------------
/src/models/categoria.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const mongoose = require('mongoose');
4 | const schema = mongoose.Schema;
5 |
6 | // definindo o modelo
7 | const categoria_model = new schema(
8 | {
9 | titulo: {
10 | trim: true,
11 | createIndexes: true,
12 | required: true,
13 | type: String,
14 | },
15 | descricao: {
16 | type: String,
17 | required: true,
18 | },
19 | dataCriacao: {
20 | type: Date,
21 | default: Date.now,
22 | },
23 | },
24 | { versionKey: false }
25 | );
26 |
27 | // antes de salvar ele verifica se foi setado a data
28 | categoria_model.pre('save', (next) => {
29 | let agora = new Date();
30 | if (!this.dataCriacao) {
31 | this.dataCriacao = agora;
32 | next(); // prossiga pro salvamento
33 | }
34 | });
35 |
36 | module.exports = mongoose.model('Categoria', categoria_model);
37 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/fa-regular.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com
3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @import 'variables';
6 |
7 | @font-face {
8 | font-family: 'Font Awesome 5 Free';
9 | font-style: normal;
10 | font-weight: 400;
11 | src: url('#{$fa-font-path}/fa-regular-400.eot');
12 | src: url('#{$fa-font-path}/fa-regular-400.eot?#iefix') format('embedded-opentype'),
13 | url('#{$fa-font-path}/fa-regular-400.woff2') format('woff2'),
14 | url('#{$fa-font-path}/fa-regular-400.woff') format('woff'),
15 | url('#{$fa-font-path}/fa-regular-400.ttf') format('truetype'),
16 | url('#{$fa-font-path}/fa-regular-400.svg#fontawesome') format('svg');
17 | }
18 |
19 | .far {
20 | font-family: 'Font Awesome 5 Free';
21 | font-weight: 400;
22 | }
23 |
--------------------------------------------------------------------------------
/src/middlewares/authentication.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const jwt = require('jsonwebtoken');
4 | const cookie = require('js-cookie').noConflict;
5 |
6 | const environments = require('../env');
7 |
8 | const authenticationToken = environments.authenticationToken.secret;
9 |
10 | module.exports.authorize = (req, res, next) => {
11 | try {
12 | const data = cookie.get('login');
13 | if (!data) {
14 | return res.send('Acesso restrito');
15 | }
16 | next();
17 | } catch (err) {
18 | next(err);
19 | }
20 | };
21 |
22 | // gerando token
23 | module.exports.generateToken = (data) => {
24 | return jwt.sign(data, authenticationToken, {
25 | expiresIn: 86400, // o meu token vai expirar em 1 dia
26 | });
27 | };
28 |
29 | // decodificando token
30 | module.exports.decoded = (token) => {
31 | const data = jwt.decode(token, authenticationToken);
32 | return data;
33 | };
34 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/_rotated-flipped.scss:
--------------------------------------------------------------------------------
1 | // Rotated & Flipped Icons
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); }
5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); }
6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); }
7 |
8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); }
9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); }
10 | .#{$fa-css-prefix}-flip-horizontal.#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(-1, -1, 2); }
11 |
12 | // Hook for IE8-9
13 | // -------------------------
14 |
15 | :root {
16 | .#{$fa-css-prefix}-rotate-90,
17 | .#{$fa-css-prefix}-rotate-180,
18 | .#{$fa-css-prefix}-rotate-270,
19 | .#{$fa-css-prefix}-flip-horizontal,
20 | .#{$fa-css-prefix}-flip-vertical {
21 | filter: none;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/routes/user.routes.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const express = require('express');
4 | const userRoutes = express.Router();
5 | const userControllers = require('../controller/user');
6 | const authentication = require('../middlewares/authentication');
7 |
8 | // GET for rotas
9 | userRoutes.get('/', userControllers.get);
10 | userRoutes.get('/registro', userControllers.getRegistro);
11 | userRoutes.get('/login', userControllers.getLogin);
12 | userRoutes.get('/logout', userControllers.logout);
13 | userRoutes.get('/edit/id/:id', authentication.authorize, userControllers.getById);
14 |
15 | // POST for rotas
16 | userRoutes.post('/registro', userControllers.postRegistro);
17 | userRoutes.post('/login', userControllers.postLogin);
18 | userRoutes.post('/edit', authentication.authorize, userControllers.update);
19 | userRoutes.post('/update/:id', authentication.authorize, userControllers.update);
20 | userRoutes.post('/delete/:id', authentication.authorize, userControllers.delete);
21 |
22 | module.exports = userRoutes;
23 |
--------------------------------------------------------------------------------
/src/repositories/product.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require('../models/product');
4 | const mongoose = require('mongoose');
5 | const product_model = mongoose.model('Produto');
6 |
7 | class Produto {
8 | // adicionando produto
9 | static async create(id, data) {
10 | const tags = data.tag.split(',');
11 | await product_model(data);
12 | await product_model.insertMany(tags);
13 | return await product_model.save();
14 | }
15 |
16 | // atualizando produto
17 | static async update(id, data) {
18 | return await product_model.findOneAndUpdate(id, { $set: data });
19 | }
20 |
21 | // deletando produto
22 | static async delete(id) {
23 | return await product_model.findByIdAndRemove(id);
24 | }
25 |
26 | // buscando
27 | static async getAll() {
28 | return await product_model.find({});
29 | }
30 |
31 | // verificando se o produto já existe
32 | static async verifyProduct(data) {
33 | return await product_model.findOne(data);
34 | }
35 | }
36 |
37 | module.exports = Produto;
38 |
--------------------------------------------------------------------------------
/src/models/order.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const mongoose = require('mongoose');
4 | const schema = mongoose.Schema;
5 |
6 | const order_model = new schema(
7 | {
8 | customer: {
9 | type: mongoose.Schema.Types.ObjectId,
10 | ref: 'Customer',
11 | },
12 | number: {
13 | type: String,
14 | required: true,
15 | },
16 | createDate: {
17 | type: Date,
18 | required: true,
19 | default: Date.now,
20 | },
21 | status: {
22 | type: String,
23 | required: true,
24 | enum: ['created', 'done'],
25 | default: 'created',
26 | },
27 | items: [
28 | {
29 | quantity: {
30 | type: Number,
31 | required: true,
32 | default: 1,
33 | },
34 | price: {
35 | type: Number,
36 | required: true,
37 | },
38 | },
39 | ],
40 | },
41 | { versionKey: false }
42 | );
43 |
44 | module.exports = mongoose.model('Order', order_model);
45 |
--------------------------------------------------------------------------------
/src/models/product.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const mongoose = require('mongoose');
4 | const schema = mongoose.Schema;
5 |
6 | const produto_model = new schema(
7 | {
8 | nome: {
9 | type: String,
10 | required: true,
11 | trim: true,
12 | index: true,
13 | },
14 | description: {
15 | type: String,
16 | required: true,
17 | },
18 | price: {
19 | type: Number,
20 | required: true,
21 | },
22 | active: {
23 | type: Boolean,
24 | required: true,
25 | default: true,
26 | },
27 | tag: [
28 | {
29 | type: String,
30 | required: true,
31 | },
32 | ],
33 | dataCriacao: {
34 | type: Date,
35 | default: Date.now,
36 | },
37 | },
38 | { versionKey: false }
39 | );
40 |
41 | produto_model.pre('save', (next) => {
42 | let agora = new Date();
43 | if (!this.dataCriacao) {
44 | this.dataCriacao = agora;
45 | next();
46 | }
47 | });
48 |
49 | module.exports = mongoose.model('Produto', produto_model);
50 |
--------------------------------------------------------------------------------
/public/plugins/owlcarousel/assets/owl.theme.default.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Owl Carousel v2.3.4
3 | * Copyright 2013-2018 David Deutsch
4 | * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
5 | */
6 | .owl-theme .owl-dots,.owl-theme .owl-nav{text-align:center;-webkit-tap-highlight-color:transparent}.owl-theme .owl-nav{margin-top:10px}.owl-theme .owl-nav [class*=owl-]{color:#FFF;font-size:14px;margin:5px;padding:4px 7px;background:#D6D6D6;display:inline-block;cursor:pointer;border-radius:3px}.owl-theme .owl-nav [class*=owl-]:hover{background:#869791;color:#FFF;text-decoration:none}.owl-theme .owl-nav .disabled{opacity:.5;cursor:default}.owl-theme .owl-nav.disabled+.owl-dots{margin-top:10px}.owl-theme .owl-dots .owl-dot{display:inline-block;zoom:1}.owl-theme .owl-dots .owl-dot span{width:10px;height:10px;margin:5px 7px;background:#D6D6D6;display:block;-webkit-backface-visibility:visible;transition:opacity .2s ease;border-radius:30px}.owl-theme .owl-dots .owl-dot.active span,.owl-theme .owl-dots .owl-dot:hover span{background:#869791}
--------------------------------------------------------------------------------
/public/plugins/owlcarousel/assets/owl.theme.green.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Owl Carousel v2.3.4
3 | * Copyright 2013-2018 David Deutsch
4 | * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
5 | */
6 | .owl-theme .owl-dots,.owl-theme .owl-nav{text-align:center;-webkit-tap-highlight-color:transparent}.owl-theme .owl-nav{margin-top:10px}.owl-theme .owl-nav [class*=owl-]{color:#FFF;font-size:14px;margin:5px;padding:4px 7px;background:#D6D6D6;display:inline-block;cursor:pointer;border-radius:3px}.owl-theme .owl-nav [class*=owl-]:hover{background:#4DC7A0;color:#FFF;text-decoration:none}.owl-theme .owl-nav .disabled{opacity:.5;cursor:default}.owl-theme .owl-nav.disabled+.owl-dots{margin-top:10px}.owl-theme .owl-dots .owl-dot{display:inline-block;zoom:1}.owl-theme .owl-dots .owl-dot span{width:10px;height:10px;margin:5px 7px;background:#D6D6D6;display:block;-webkit-backface-visibility:visible;transition:opacity .2s ease;border-radius:30px}.owl-theme .owl-dots .owl-dot.active span,.owl-theme .owl-dots .owl-dot:hover span{background:#4DC7A0}
--------------------------------------------------------------------------------
/src/repositories/user.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require('../models/user');
4 |
5 | const mongoose = require('mongoose');
6 | const userModel = mongoose.model('Usuario');
7 |
8 | class User {
9 | static async create(data) {
10 | return await userModel(data).save();
11 | }
12 |
13 | static async update(id, data) {
14 | return await userModel.findOneAndUpdate(id, { $set: data });
15 | }
16 |
17 | static async delete(id) {
18 | return userModel.findOneAndDelete(id);
19 | }
20 |
21 | static async getById(id) {
22 | return await userModel.findById(id);
23 | }
24 |
25 | static async getAll() {
26 | return await userModel.find({});
27 | }
28 |
29 | static async registerVerification(data) {
30 | const { email } = data;
31 | const user = await userModel.findOne({ email });
32 | return user;
33 | }
34 |
35 | static async loginVerification(data) {
36 | const { email, senha } = data;
37 | const user = await userModel.findOne({ email }).select('+senha');
38 | return user;
39 | }
40 |
41 | static async getUsersQtd() {
42 | const qtd = await userModel.collection.estimatedDocumentCount();
43 | return qtd;
44 | }
45 | }
46 |
47 | module.exports = User;
48 |
--------------------------------------------------------------------------------
/public/css/responsive.css:
--------------------------------------------------------------------------------
1 | @media (max-width: 1200px) {
2 | /* tablet devices */ }
3 | @media (max-width: 992px) {
4 | /* small tablet devices */
5 | .slider-main .item-slide {
6 | height: auto; }
7 |
8 | .menu-category .submenu {
9 | max-width: 100%;
10 | left: 0;
11 | top: 100%; }
12 |
13 | .border-cols > [class*="col-"] {
14 | border-width: 0 0 1px 1px; } }
15 | @media all and (max-width: 768px) {
16 | /* mobile devices */
17 | .navbar {
18 | padding: 1rem; }
19 |
20 | .navbar-landing {
21 | transition: .5s;
22 | padding-top: 7px;
23 | padding-bottom: 7px; }
24 |
25 | .nav-item .btn {
26 | margin: 7px 0 !important; }
27 |
28 | .list-inline-item {
29 | vertical-align: middle;
30 | margin-bottom: 5px;
31 | margin-top: 5px; }
32 |
33 | .section-header .logo, .header-main .logo {
34 | max-height: 30px;
35 | width: auto; }
36 | .section-header .logo-text, .header-main .logo-text {
37 | font-size: 24px; }
38 | .section-header .brand-wrap, .section-header .search-wrap, .section-header .widget-header, .header-main .brand-wrap, .header-main .search-wrap, .header-main .widget-header {
39 | margin-bottom: 1rem; } }
40 |
41 | /*# sourceMappingURL=responsive.css.map */
42 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ecommerce-nodejs",
3 | "version": "1.0.0",
4 | "main": "server.js",
5 | "bin": {
6 | "ionicFood": "express.js"
7 | },
8 | "dependencies": {
9 | "bcryptjs": "^2.4.3",
10 | "body-parser": "^1.18.3",
11 | "bulma": "^0.7.2",
12 | "connect-flash": "^0.1.1",
13 | "connect-mongo": "^2.0.3",
14 | "consolidate": "^0.15.1",
15 | "cookie-parser": "^1.4.3",
16 | "cors": "^2.8.5",
17 | "csrf": "^3.0.6",
18 | "ejs": "^2.6.1",
19 | "express": "^4.16.4",
20 | "express-flash": "0.0.2",
21 | "express-handlebars": "^3.0.0",
22 | "express-session": "^1.15.6",
23 | "express-validator": "^5.3.0",
24 | "flash": "^1.1.0",
25 | "js-cookie": "^2.2.1",
26 | "jsonwebtoken": "^8.4.0",
27 | "localtoken": "^0.1.2",
28 | "md5": "^2.2.1",
29 | "mongodb": "^3.1.10",
30 | "mongoose": "^5.3.13",
31 | "node-sessionstorage": "^1.0.0",
32 | "nodemon": "^1.18.9",
33 | "passport": "^0.4.0",
34 | "passport-local": "^1.0.0"
35 | },
36 | "devDependencies": {},
37 | "scripts": {
38 | "test": "echo \"Error: no test specified\" && exit 1",
39 | "start": "nodemon ./src/app.js"
40 | },
41 | "keywords": [],
42 | "author": "",
43 | "license": "ISC",
44 | "description": ""
45 | }
46 |
--------------------------------------------------------------------------------
/src/controller/category.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const Categoria = require('../repositories/category');
3 |
4 | exports.get = async (req, res, next) => {
5 | try {
6 | let categorias = await Categoria.getAll();
7 | res.render('pages/categoria/_list', { categorias: categorias });
8 | } catch (err) {
9 | next(err);
10 | }
11 | };
12 |
13 | exports.getById = async (req, res, next) => {
14 | try {
15 | let categoria = await Categoria.getById(req.params.id);
16 | res.send(categoria);
17 | } catch (err) {
18 | next(err);
19 | }
20 | };
21 |
22 | exports.post = async (req, res, next) => {
23 | try {
24 | await Categoria.create(req.body);
25 | res.redirect('/api/categoria');
26 | } catch (err) {
27 | next(err);
28 | }
29 | };
30 |
31 | exports.put = async (req, res, next) => {
32 | let resultado = await Categoria.update(req.params.id, req.body);
33 | res.send(resultado);
34 | };
35 |
36 | exports.delete = async (req, res) => {
37 | let deletado = await Categoria.delete(req.params.id);
38 | res.send(deletado);
39 | };
40 |
41 | exports.register = async (req, res, next) => {
42 | try {
43 | let categorias = await Categoria.getAll();
44 | res.render('pages/admin/register-category', { categorias: categorias });
45 | } catch (err) {
46 | next(err);
47 | }
48 | };
49 |
--------------------------------------------------------------------------------
/views/pages/errors/500.handlebars:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/config/server.js:
--------------------------------------------------------------------------------
1 | // módulos
2 | const express = require('express');
3 | const bodyParser = require('body-parser');
4 | const mongoose = require('mongoose');
5 | const hbs = require('express-handlebars');
6 |
7 | const environments = require('../env');
8 |
9 | // app
10 | const app = express();
11 |
12 | // chamando as rotas
13 | const userRoutes = require('../routes/user.routes');
14 | const productRoutes = require('../routes/product.routes');
15 |
16 | // configurando a conexao com o bando de dados
17 | mongoose.Promise = global.Promise;
18 | mongoose.connect(environments.database.connection, {
19 | useNewUrlParser: true,
20 | useUnifiedTopology: true,
21 | useCreateIndex: true,
22 | });
23 |
24 | // configurando o parse
25 | app.use(bodyParser.json({ limit: '5mb' }));
26 | app.use(bodyParser.urlencoded({ extended: true }));
27 |
28 | // definindo o meu template engine
29 | app.engine('handlebars', hbs({ defaultLayout: 'main' }));
30 |
31 | // definindo o motor de renderização
32 | app.set('view engine', 'handlebars');
33 |
34 | // carregando arquivos estáticos
35 | app.use(express.static('public'));
36 |
37 | // nomeando as rotas
38 | app.use('/api/usuario', userRoutes);
39 | app.use('/api/produto', productRoutes);
40 |
41 | app.use('/', (req, res, next) => {
42 | res.render('home');
43 | }); // rota principal
44 | app.use((req, res, next) => {
45 | res.render('pages/errors/404');
46 | }); // tratamento para erro 404
47 | app.use((err, req, res, next) => {
48 | res.send(err);
49 | }); // tratamento para demais erros
50 |
51 | module.exports = app;
52 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome/scss/_mixins.scss:
--------------------------------------------------------------------------------
1 | // Mixins
2 | // --------------------------
3 |
4 | @mixin fa-icon {
5 | -webkit-font-smoothing: antialiased;
6 | -moz-osx-font-smoothing: grayscale;
7 | display: inline-block;
8 | font-style: normal;
9 | font-variant: normal;
10 | font-weight: normal;
11 | line-height: 1;
12 | vertical-align: -.125em;
13 | }
14 |
15 | @mixin fa-icon-rotate($degrees, $rotation) {
16 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})";
17 | transform: rotate($degrees);
18 | }
19 |
20 | @mixin fa-icon-flip($horiz, $vert, $rotation) {
21 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)";
22 | transform: scale($horiz, $vert);
23 | }
24 |
25 |
26 | // Only display content to screen readers. A la Bootstrap 4.
27 | //
28 | // See: http://a11yproject.com/posts/how-to-hide-content/
29 |
30 | @mixin sr-only {
31 | border: 0;
32 | clip: rect(0, 0, 0, 0);
33 | height: 1px;
34 | margin: -1px;
35 | overflow: hidden;
36 | padding: 0;
37 | position: absolute;
38 | width: 1px;
39 | }
40 |
41 | // Use in conjunction with .sr-only to only display content when it's focused.
42 | //
43 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
44 | //
45 | // Credit: HTML5 Boilerplate
46 |
47 | @mixin sr-only-focusable {
48 | &:active,
49 | &:focus {
50 | clip: auto;
51 | height: auto;
52 | margin: 0;
53 | overflow: visible;
54 | position: static;
55 | width: auto;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/public/plugins/owlcarousel/assets/owl.theme.green.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Owl Carousel v2.3.4
3 | * Copyright 2013-2018 David Deutsch
4 | * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
5 | */
6 | /*
7 | * Green theme - Owl Carousel CSS File
8 | */
9 | .owl-theme .owl-nav {
10 | margin-top: 10px;
11 | text-align: center;
12 | -webkit-tap-highlight-color: transparent; }
13 | .owl-theme .owl-nav [class*='owl-'] {
14 | color: #FFF;
15 | font-size: 14px;
16 | margin: 5px;
17 | padding: 4px 7px;
18 | background: #D6D6D6;
19 | display: inline-block;
20 | cursor: pointer;
21 | border-radius: 3px; }
22 | .owl-theme .owl-nav [class*='owl-']:hover {
23 | background: #4DC7A0;
24 | color: #FFF;
25 | text-decoration: none; }
26 | .owl-theme .owl-nav .disabled {
27 | opacity: 0.5;
28 | cursor: default; }
29 |
30 | .owl-theme .owl-nav.disabled + .owl-dots {
31 | margin-top: 10px; }
32 |
33 | .owl-theme .owl-dots {
34 | text-align: center;
35 | -webkit-tap-highlight-color: transparent; }
36 | .owl-theme .owl-dots .owl-dot {
37 | display: inline-block;
38 | zoom: 1;
39 | *display: inline; }
40 | .owl-theme .owl-dots .owl-dot span {
41 | width: 10px;
42 | height: 10px;
43 | margin: 5px 7px;
44 | background: #D6D6D6;
45 | display: block;
46 | -webkit-backface-visibility: visible;
47 | transition: opacity 200ms ease;
48 | border-radius: 30px; }
49 | .owl-theme .owl-dots .owl-dot.active span, .owl-theme .owl-dots .owl-dot:hover span {
50 | background: #4DC7A0; }
51 |
--------------------------------------------------------------------------------
/public/plugins/owlcarousel/assets/owl.theme.default.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Owl Carousel v2.3.4
3 | * Copyright 2013-2018 David Deutsch
4 | * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
5 | */
6 | /*
7 | * Default theme - Owl Carousel CSS File
8 | */
9 | .owl-theme .owl-nav {
10 | margin-top: 10px;
11 | text-align: center;
12 | -webkit-tap-highlight-color: transparent; }
13 | .owl-theme .owl-nav [class*='owl-'] {
14 | color: #FFF;
15 | font-size: 14px;
16 | margin: 5px;
17 | padding: 4px 7px;
18 | background: #D6D6D6;
19 | display: inline-block;
20 | cursor: pointer;
21 | border-radius: 3px; }
22 | .owl-theme .owl-nav [class*='owl-']:hover {
23 | background: #869791;
24 | color: #FFF;
25 | text-decoration: none; }
26 | .owl-theme .owl-nav .disabled {
27 | opacity: 0.5;
28 | cursor: default; }
29 |
30 | .owl-theme .owl-nav.disabled + .owl-dots {
31 | margin-top: 10px; }
32 |
33 | .owl-theme .owl-dots {
34 | text-align: center;
35 | -webkit-tap-highlight-color: transparent; }
36 | .owl-theme .owl-dots .owl-dot {
37 | display: inline-block;
38 | zoom: 1;
39 | *display: inline; }
40 | .owl-theme .owl-dots .owl-dot span {
41 | width: 10px;
42 | height: 10px;
43 | margin: 5px 7px;
44 | background: #D6D6D6;
45 | display: block;
46 | -webkit-backface-visibility: visible;
47 | transition: opacity 200ms ease;
48 | border-radius: 30px; }
49 | .owl-theme .owl-dots .owl-dot.active span, .owl-theme .owl-dots .owl-dot:hover span {
50 | background: #869791; }
51 |
--------------------------------------------------------------------------------
/views/layouts/main.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Painel Administrativo
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
47 |
48 | {{>_navbar}}
49 | {{{body}}}
50 | {{>_footer}}
51 |
52 |
53 |
--------------------------------------------------------------------------------
/views/pages/produtos/products.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Primary file…
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Info file…
27 |
28 |
29 |
30 | Screen Shot 2017-07-29 at 15.54.25.png
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | Warning file…
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | Danger file…
62 |
63 |
64 |
65 | Screen Shot 2017-07-29 at 15.54.25.png
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/views/pages/user/_login.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Login
9 |
10 | {{#if error}}
11 |
12 | {{error}}
13 |
14 | {{/if}}
15 | {{#if success}}
16 |
17 | {{success}}
18 |
19 | {{/if}}
20 | {{#if token}}
21 |
22 | {{/if}}
23 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/views/pages/user/_user-edit.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Edição de usuário
9 |
10 | {{#if error}}
11 |
12 | {{error}}
13 |
14 | {{/if}}
15 | {{#if success}}
16 |
17 | {{success}}
18 |
19 | {{/if}}
20 | {{#if token}}
21 |
22 | {{/if}}
23 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/public/plugins/slickslider/fonts/slick.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Generated by Fontastic.me
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/views/pages/user/_users-list.handlebars:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/plugins/slickslider/slick.css:
--------------------------------------------------------------------------------
1 | /* Slider */
2 | .slick-slider
3 | {
4 | position: relative;
5 |
6 | display: block;
7 | box-sizing: border-box;
8 |
9 | -webkit-user-select: none;
10 | -moz-user-select: none;
11 | -ms-user-select: none;
12 | user-select: none;
13 |
14 | -webkit-touch-callout: none;
15 | -khtml-user-select: none;
16 | -ms-touch-action: pan-y;
17 | touch-action: pan-y;
18 | -webkit-tap-highlight-color: transparent;
19 | }
20 |
21 | .slick-list
22 | {
23 | position: relative;
24 |
25 | display: block;
26 | overflow: hidden;
27 |
28 | margin: 0;
29 | padding: 0;
30 | }
31 | .slick-list:focus
32 | {
33 | outline: none;
34 | }
35 | .slick-list.dragging
36 | {
37 | cursor: pointer;
38 | cursor: hand;
39 | }
40 |
41 | .slick-slider .slick-track,
42 | .slick-slider .slick-list
43 | {
44 | -webkit-transform: translate3d(0, 0, 0);
45 | -moz-transform: translate3d(0, 0, 0);
46 | -ms-transform: translate3d(0, 0, 0);
47 | -o-transform: translate3d(0, 0, 0);
48 | transform: translate3d(0, 0, 0);
49 | }
50 |
51 | .slick-track
52 | {
53 | position: relative;
54 | top: 0;
55 | left: 0;
56 |
57 | display: block;
58 | margin-left: auto;
59 | margin-right: auto;
60 | }
61 | .slick-track:before,
62 | .slick-track:after
63 | {
64 | display: table;
65 |
66 | content: '';
67 | }
68 | .slick-track:after
69 | {
70 | clear: both;
71 | }
72 | .slick-loading .slick-track
73 | {
74 | visibility: hidden;
75 | }
76 |
77 | .slick-slide
78 | {
79 | display: none;
80 | float: left;
81 |
82 | height: 100%;
83 | min-height: 1px;
84 | }
85 | [dir='rtl'] .slick-slide
86 | {
87 | float: right;
88 | }
89 | .slick-slide img
90 | {
91 | display: block; width:100%;
92 | }
93 | .slick-slide.slick-loading img
94 | {
95 | display: none;
96 | }
97 | .slick-slide.dragging img
98 | {
99 | pointer-events: none;
100 | }
101 | .slick-initialized .slick-slide
102 | {
103 | display: block;
104 | }
105 | .slick-loading .slick-slide
106 | {
107 | visibility: hidden;
108 | }
109 | .slick-vertical .slick-slide
110 | {
111 | display: block;
112 |
113 | height: auto;
114 |
115 | border: 1px solid transparent;
116 | }
117 | .slick-arrow.slick-hidden {
118 | display: none;
119 | }
120 |
--------------------------------------------------------------------------------
/views/pages/user/_register.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Registro
9 |
10 | {{#if error}}
11 |
12 | {{error}}
13 |
14 | {{/if}}
15 | {{#if success}}
16 |
17 | {{success}}
18 |
19 | {{/if}}
20 | {{#if token}}
21 |
22 | {{/if}}
23 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/public/plugins/prism/prism.css:
--------------------------------------------------------------------------------
1 | /* PrismJS 1.11.0
2 | http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */
3 | /**
4 | * prism.js default theme for JavaScript, CSS and HTML
5 | * Based on dabblet (http://dabblet.com)
6 | * @author Lea Verou
7 | */
8 |
9 | code[class*="language-"],
10 | pre[class*="language-"] {
11 | color: black;
12 | background: none;
13 | text-shadow: 0 1px white;
14 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
15 | text-align: left;
16 | white-space: pre;
17 | word-spacing: normal;
18 | word-break: normal;
19 | word-wrap: normal;
20 | line-height: 1.5;
21 |
22 | -moz-tab-size: 4;
23 | -o-tab-size: 4;
24 | tab-size: 4;
25 |
26 | -webkit-hyphens: none;
27 | -moz-hyphens: none;
28 | -ms-hyphens: none;
29 | hyphens: none;
30 | }
31 |
32 | pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
33 | code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
34 | text-shadow: none;
35 | background: #b3d4fc;
36 | }
37 |
38 | pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
39 | code[class*="language-"]::selection, code[class*="language-"] ::selection {
40 | text-shadow: none;
41 | background: #b3d4fc;
42 | }
43 |
44 | @media print {
45 | code[class*="language-"],
46 | pre[class*="language-"] {
47 | text-shadow: none;
48 | }
49 | }
50 |
51 | /* Code blocks */
52 | pre[class*="language-"] {
53 | padding: 0 1em;
54 | margin: 0 0;
55 | overflow: auto;
56 | }
57 |
58 | :not(pre) > code[class*="language-"],
59 | pre[class*="language-"] {
60 | background: #f5f2f0;
61 | }
62 |
63 | /* Inline code */
64 | :not(pre) > code[class*="language-"] {
65 | padding: .1em;
66 | border-radius: .3em;
67 | white-space: normal;
68 | }
69 |
70 | .token.comment,
71 | .token.prolog,
72 | .token.doctype,
73 | .token.cdata {
74 | color: slategray;
75 | }
76 |
77 | .token.punctuation {
78 | color: #999;
79 | }
80 |
81 | .namespace {
82 | opacity: .7;
83 | }
84 |
85 | .token.property,
86 | .token.tag,
87 | .token.boolean,
88 | .token.number,
89 | .token.constant,
90 | .token.symbol,
91 | .token.deleted {
92 | color: #905;
93 | }
94 |
95 | .token.selector,
96 | .token.attr-name,
97 | .token.string,
98 | .token.char,
99 | .token.builtin,
100 | .token.inserted {
101 | color: #690;
102 | }
103 |
104 | .token.operator,
105 | .token.entity,
106 | .token.url,
107 | .language-css .token.string,
108 | .style .token.string {
109 | color: #a67f59;
110 | background: hsla(0, 0%, 100%, .5);
111 | }
112 |
113 | .token.atrule,
114 | .token.attr-value,
115 | .token.keyword {
116 | color: #07a;
117 | }
118 |
119 | .token.function {
120 | color: #DD4A68;
121 | }
122 |
123 | .token.regex,
124 | .token.important,
125 | .token.variable {
126 | color: #e90;
127 | }
128 |
129 | .token.important,
130 | .token.bold {
131 | font-weight: bold;
132 | }
133 | .token.italic {
134 | font-style: italic;
135 | }
136 |
137 | .token.entity {
138 | cursor: help;
139 | }
140 |
141 |
--------------------------------------------------------------------------------
/public/plugins/owlcarousel/assets/owl.carousel.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Owl Carousel v2.3.4
3 | * Copyright 2013-2018 David Deutsch
4 | * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
5 | */
6 | .owl-carousel,.owl-carousel .owl-item{-webkit-tap-highlight-color:transparent;position:relative}.owl-carousel{display:none;width:100%;z-index:1}.owl-carousel .owl-stage{position:relative;-ms-touch-action:pan-Y;touch-action:manipulation;-moz-backface-visibility:hidden}.owl-carousel .owl-stage:after{content:".";display:block;clear:both;visibility:hidden;line-height:0;height:0}.owl-carousel .owl-stage-outer{position:relative;overflow:hidden;-webkit-transform:translate3d(0,0,0)}.owl-carousel .owl-item,.owl-carousel .owl-wrapper{-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0)}.owl-carousel .owl-item{min-height:1px;float:left;-webkit-backface-visibility:hidden;-webkit-touch-callout:none}.owl-carousel .owl-item img{display:block;width:100%}.owl-carousel .owl-dots.disabled,.owl-carousel .owl-nav.disabled{display:none}.no-js .owl-carousel,.owl-carousel.owl-loaded{display:block}.owl-carousel .owl-dot,.owl-carousel .owl-nav .owl-next,.owl-carousel .owl-nav .owl-prev{cursor:pointer;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.owl-carousel .owl-nav button.owl-next,.owl-carousel .owl-nav button.owl-prev,.owl-carousel button.owl-dot{border:none;font:inherit}.owl-carousel.owl-loading{opacity:0;display:block}.owl-carousel.owl-hidden{opacity:0}.owl-carousel.owl-refresh .owl-item{visibility:hidden}.owl-carousel.owl-drag .owl-item{-ms-touch-action:pan-y;touch-action:pan-y;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.owl-carousel.owl-grab{cursor:move;cursor:grab}.owl-carousel.owl-rtl{direction:rtl}.owl-carousel.owl-rtl .owl-item{float:right}.owl-carousel .animated{animation-duration:1s;animation-fill-mode:both}.owl-carousel .owl-animated-in{z-index:0}.owl-carousel .owl-animated-out{z-index:1}.owl-carousel .fadeOut{animation-name:fadeOut}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.owl-height{transition:height .5s ease-in-out}.owl-carousel .owl-item .owl-lazy{opacity:0;transition:opacity .4s ease}.owl-carousel .owl-item .owl-lazy:not([src]),.owl-carousel .owl-item .owl-lazy[src^=""]{max-height:0}.owl-carousel .owl-item img.owl-lazy{transform-style:preserve-3d}.owl-carousel .owl-video-wrapper{position:relative;height:100%;background:#000}.owl-carousel .owl-video-play-icon{position:absolute;height:80px;width:80px;left:50%;top:50%;margin-left:-40px;margin-top:-40px;background:url(owl.video.play.png) no-repeat;cursor:pointer;z-index:1;-webkit-backface-visibility:hidden;transition:transform .1s ease}.owl-carousel .owl-video-play-icon:hover{-ms-transform:scale(1.3,1.3);transform:scale(1.3,1.3)}.owl-carousel .owl-video-playing .owl-video-play-icon,.owl-carousel .owl-video-playing .owl-video-tn{display:none}.owl-carousel .owl-video-tn{opacity:0;height:100%;background-position:center center;background-repeat:no-repeat;background-size:contain;transition:opacity .4s ease}.owl-carousel .owl-video-frame{position:relative;z-index:1;height:100%;width:100%}
--------------------------------------------------------------------------------
/src/controller/user.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const User = require('../repositories/user'); // acessando repositorio do banco de dados
4 | const auth = require('../middlewares/authentication'); // token
5 | const crypt = require('bcryptjs'); // para criptografar a senha
6 | const cookie = require('js-cookie').noConflict;
7 |
8 | // buscando usuario
9 | exports.get = async (req, res, next) => {
10 | try {
11 | console.log('1');
12 | const users = await User.getAll();
13 | console.log(users);
14 | const qtd = await User.getUsersQtd();
15 | return res.render('pages/user/_users-list', { user: users, qtd: qtd });
16 | } catch (err) {
17 | next(err);
18 | }
19 | };
20 |
21 | // buscando usuario pela ID
22 | exports.getById = async (req, res, next) => {
23 | try {
24 | const user = await User.getById(req.params.id);
25 | if (user) {
26 | return res.render('pages/user/_user-edit', {
27 | user: user,
28 | success: 'Encontramos o usuário!',
29 | });
30 | } else {
31 | return res.render('pages/user/_user-edit', {
32 | error: 'Não conseguimos encontrar o usuário!',
33 | });
34 | }
35 | } catch (err) {
36 | next(err);
37 | }
38 | };
39 |
40 | // atualizando usuario
41 | exports.update = async (req, res, next) => {
42 | try {
43 | await User.update(req.params.id, req.body);
44 | return res.render('pages/user/_user-edit', {
45 | success: 'Dados atualizados com sucesso!',
46 | });
47 | } catch (err) {
48 | next(err);
49 | }
50 | };
51 |
52 | // deletando usuario
53 | exports.delete = async (req, res, next) => {
54 | try {
55 | await User.delete(req.params.id);
56 | return res.redirect('/api/usuario');
57 | } catch (err) {
58 | next(err);
59 | }
60 | };
61 |
62 | // GET for registro de usuário
63 | exports.getRegistro = (req, res) => {
64 | return res.render('pages/user/_register');
65 | };
66 |
67 | // POST for registro de usuário
68 | exports.postRegistro = async (req, res, next) => {
69 | try {
70 | const user = await User.registerVerification(req.body);
71 | if (!user) {
72 | await User.create(req.body);
73 | return res.render('pages/user/_register', {
74 | success: 'Usuário cadastrado com sucesso!',
75 | });
76 | } else {
77 | return res.render('pages/user/_register', {
78 | error: 'Usuário já foi cadastrado!',
79 | });
80 | }
81 | } catch (err) {
82 | next(err);
83 | }
84 | };
85 |
86 | // GET for login de usuário
87 | exports.getLogin = (req, res) => {
88 | return res.render('pages/user/_login');
89 | };
90 |
91 | // POST for login de usuário
92 | exports.postLogin = async (req, res, next) => {
93 | try {
94 | const user = await User.loginVerification(req.body);
95 |
96 | if (!user) {
97 | // se o usuario nao existe...
98 | return res.render('pages/user/_login', {
99 | error: 'O Usuário não foi encontrado!',
100 | });
101 | }
102 |
103 | if (!(await crypt.compare(req.body.senha, user.senha))) {
104 | // se as senhas nao combinam...
105 | return res.render('pages/user/_login', { error: 'Senha inválida!' });
106 | }
107 |
108 | const token = auth.generateToken({ user });
109 | console.log(token);
110 | cookie.set('login', token, { expires: 1 });
111 | console.log(cookie.getJSON('login'));
112 |
113 | return res.render('pages/user/_login', {
114 | success: 'Usuário logado com sucesso!',
115 | });
116 | } catch (err) {
117 | next(err);
118 | }
119 | };
120 |
121 | // logout - removendo token da 'sessão'
122 | exports.logout = (req, res, next) => {
123 | try {
124 | cookie.remove('login');
125 | return res.redirect('/');
126 | } catch (err) {
127 | next(err);
128 | }
129 | };
130 |
--------------------------------------------------------------------------------
/public/js/script.js:
--------------------------------------------------------------------------------
1 | // some scripts
2 |
3 | // jquery ready start
4 | $(document).ready(function() {
5 | // jQuery code
6 |
7 |
8 |
9 |
10 | /* ///////////////////////////////////////
11 |
12 | THESE FOLLOWING SCRIPTS ONLY FOR BASIC USAGE,
13 | For sliders, interactions and other
14 |
15 | */ ///////////////////////////////////////
16 |
17 |
18 | //////////////////////// Prevent closing from click inside dropdown
19 | $(document).on('click', '.dropdown-menu', function (e) {
20 | e.stopPropagation();
21 | });
22 |
23 | ///////////////// fixed menu on scroll for desctop
24 | if ($(window).width() > 768) {
25 |
26 | $(window).scroll(function(){
27 | if ($(this).scrollTop() > 125) {
28 | $('.navbar-landing').addClass("fixed-top");
29 | }else{
30 | $('.navbar-landing').removeClass("fixed-top");
31 | }
32 | });
33 | } // end if
34 |
35 | //////////////////////// Fancybox. /plugins/fancybox/
36 | if($("[data-fancybox]").length>0) { // check if element exists
37 | $("[data-fancybox]").fancybox();
38 | } // end if
39 |
40 | //////////////////////// Bootstrap tooltip
41 | if($('[data-toggle="tooltip"]').length>0) { // check if element exists
42 | $('[data-toggle="tooltip"]').tooltip()
43 | } // end if
44 |
45 | /////////////////////// Closes the Responsive Menu on Menu Item Click
46 | $('.navbar-collapse ul li a.page-scroll').click(function() {
47 | $('.navbar-toggler:visible').click();
48 | });
49 |
50 | //////////////////////// Menu scroll to section for landing
51 | $('a.page-scroll').click(function(event) {
52 | var $anchor = $(this);
53 | $('html, body').stop().animate({ scrollTop: $($anchor.attr('href')).offset().top - 50 }, 1000);
54 | event.preventDefault();
55 | });
56 |
57 | ///////////////// items slider. /plugins/slickslider/
58 | if ($('.slick-slider').length > 0) { // check if element exists
59 | $('.slick-slider').slick();
60 | } // end if
61 |
62 | ///////////////// items carousel. /plugins/owlcarousel/
63 | if ($('.owl-init').length > 0) { // check if element exists
64 |
65 | $(".owl-init").each(function(){
66 |
67 | var myOwl = $(this);
68 | var data_items = myOwl.data('items');
69 | var data_nav = myOwl.data('nav');
70 | var data_dots = myOwl.data('dots');
71 | var data_margin = myOwl.data('margin');
72 | var data_custom_nav = myOwl.data('custom-nav');
73 | var id_owl = myOwl.attr('id');
74 |
75 | myOwl.owlCarousel({
76 | loop: true,
77 | margin: data_margin,
78 | nav: eval(data_nav),
79 | dots: eval(data_dots),
80 | autoplay: false,
81 | items: data_items,
82 | navText: [" ", " "],
83 | //items: 4,
84 | responsive: {
85 | 0: {
86 | items: 1
87 | },
88 | 600: {
89 | items: data_items
90 | },
91 | 1000: {
92 | items: data_items
93 | }
94 | }
95 | });
96 |
97 | // for custom navigation. See example page: example-sliders.html
98 | $('.'+data_custom_nav+'.owl-custom-next').click(function(){
99 | $('#'+id_owl).trigger('next.owl.carousel');
100 | });
101 |
102 | $('.'+data_custom_nav+'.owl-custom-prev').click(function(){
103 | $('#'+id_owl).trigger('prev.owl.carousel');
104 | });
105 |
106 | }); // each end.//
107 | } // end if
108 |
109 |
110 | });
111 | // jquery end
112 |
113 |
--------------------------------------------------------------------------------
/public/plugins/slickslider/slick-theme.css:
--------------------------------------------------------------------------------
1 | @charset 'UTF-8';
2 | /* Slider */
3 | .slick-loading .slick-list
4 | {
5 | background: #fff url('./ajax-loader.gif') center center no-repeat;
6 | }
7 |
8 | /* Icons */
9 | @font-face
10 | {
11 | font-family: 'slick';
12 | font-weight: normal;
13 | font-style: normal;
14 |
15 | src: url('./fonts/slick.eot');
16 | src: url('./fonts/slick.eot?#iefix') format('embedded-opentype'), url('./fonts/slick.woff') format('woff'), url('./fonts/slick.ttf') format('truetype'), url('./fonts/slick.svg#slick') format('svg');
17 | }
18 | /* Arrows */
19 | .slick-prev,
20 | .slick-next
21 | {
22 | font-size: 0;
23 | line-height: 0;
24 |
25 | position: absolute;
26 | top: 50%;
27 |
28 | display: block;
29 |
30 | width: 20px;
31 | height: 20px;
32 | padding: 0;
33 | -webkit-transform: translate(0, -50%);
34 | -ms-transform: translate(0, -50%);
35 | transform: translate(0, -50%);
36 |
37 | cursor: pointer;
38 |
39 | color: transparent;
40 | border: none;
41 | outline: none;
42 | background: transparent;
43 | }
44 | .slick-prev:hover,
45 | .slick-prev:focus,
46 | .slick-next:hover,
47 | .slick-next:focus
48 | {
49 | color: transparent;
50 | outline: none;
51 | background: transparent;
52 | }
53 | .slick-prev:hover:before,
54 | .slick-prev:focus:before,
55 | .slick-next:hover:before,
56 | .slick-next:focus:before
57 | {
58 | opacity: 1;
59 | }
60 | .slick-prev.slick-disabled:before,
61 | .slick-next.slick-disabled:before
62 | {
63 | opacity: .25;
64 | }
65 |
66 | .slick-prev:before,
67 | .slick-next:before
68 | {
69 | font-family: 'slick';
70 | font-size: 20px;
71 | line-height: 1;
72 |
73 | opacity: .75;
74 | color: rgba(0,0,0,.3);
75 |
76 | -webkit-font-smoothing: antialiased;
77 | -moz-osx-font-smoothing: grayscale;
78 | }
79 |
80 | .slick-prev
81 | {
82 | left: -25px;
83 | }
84 | [dir='rtl'] .slick-prev
85 | {
86 | right: -25px;
87 | left: auto;
88 | }
89 | .slick-prev:before
90 | {
91 | content: '←';
92 | }
93 | [dir='rtl'] .slick-prev:before
94 | {
95 | content: '→';
96 | }
97 |
98 | .slick-next
99 | {
100 | right: -25px;
101 | }
102 | [dir='rtl'] .slick-next
103 | {
104 | right: auto;
105 | left: -25px;
106 | }
107 | .slick-next:before
108 | {
109 | content: '→';
110 | }
111 | [dir='rtl'] .slick-next:before
112 | {
113 | content: '←';
114 | }
115 |
116 | /* Dots */
117 | .slick-dotted.slick-slider
118 | {
119 | margin-bottom: 30px;
120 | }
121 |
122 | .slick-dots
123 | {
124 | position: absolute;
125 | bottom: -25px;
126 |
127 | display: block;
128 |
129 | width: 100%;
130 | padding: 0;
131 | margin: 0;
132 |
133 | list-style: none;
134 |
135 | text-align: center;
136 | }
137 | .slick-dots li
138 | {
139 | position: relative;
140 |
141 | display: inline-block;
142 |
143 | width: 20px;
144 | height: 20px;
145 | margin: 0 5px;
146 | padding: 0;
147 |
148 | cursor: pointer;
149 | }
150 | .slick-dots li button
151 | {
152 | font-size: 0;
153 | line-height: 0;
154 |
155 | display: block;
156 |
157 | width: 20px;
158 | height: 20px;
159 | padding: 5px;
160 |
161 | cursor: pointer;
162 |
163 | color: transparent;
164 | border: 0;
165 | outline: none;
166 | background: transparent;
167 | }
168 | .slick-dots li button:hover,
169 | .slick-dots li button:focus
170 | {
171 | outline: none;
172 | }
173 | .slick-dots li button:hover:before,
174 | .slick-dots li button:focus:before
175 | {
176 | opacity: 1;
177 | }
178 | .slick-dots li button:before
179 | {
180 | font-family: 'slick';
181 | font-size: 6px;
182 | line-height: 20px;
183 |
184 | position: absolute;
185 | top: 0;
186 | left: 0;
187 |
188 | width: 20px;
189 | height: 20px;
190 |
191 | content: '•';
192 | text-align: center;
193 |
194 | opacity: .25;
195 | color: black;
196 |
197 | -webkit-font-smoothing: antialiased;
198 | -moz-osx-font-smoothing: grayscale;
199 | }
200 | .slick-dots li.slick-active button:before
201 | {
202 | opacity: .75;
203 | color: black;
204 | }
205 |
--------------------------------------------------------------------------------
/views/partials/_navbar.handlebars:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/views/pages/errors/404.handlebars:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/plugins/owlcarousel/assets/owl.carousel.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Owl Carousel v2.3.4
3 | * Copyright 2013-2018 David Deutsch
4 | * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
5 | */
6 | /*
7 | * Owl Carousel - Core
8 | */
9 | .owl-carousel {
10 | display: none;
11 | width: 100%;
12 | -webkit-tap-highlight-color: transparent;
13 | /* position relative and z-index fix webkit rendering fonts issue */
14 | position: relative;
15 | z-index: 1; }
16 | .owl-carousel .owl-stage {
17 | position: relative;
18 | -ms-touch-action: pan-Y;
19 | touch-action: manipulation;
20 | -moz-backface-visibility: hidden;
21 | /* fix firefox animation glitch */ }
22 | .owl-carousel .owl-stage:after {
23 | content: ".";
24 | display: block;
25 | clear: both;
26 | visibility: hidden;
27 | line-height: 0;
28 | height: 0; }
29 | .owl-carousel .owl-stage-outer {
30 | position: relative;
31 | overflow: hidden;
32 | /* fix for flashing background */
33 | -webkit-transform: translate3d(0px, 0px, 0px); }
34 | .owl-carousel .owl-wrapper,
35 | .owl-carousel .owl-item {
36 | -webkit-backface-visibility: hidden;
37 | -moz-backface-visibility: hidden;
38 | -ms-backface-visibility: hidden;
39 | -webkit-transform: translate3d(0, 0, 0);
40 | -moz-transform: translate3d(0, 0, 0);
41 | -ms-transform: translate3d(0, 0, 0); }
42 | .owl-carousel .owl-item {
43 | position: relative;
44 | min-height: 1px;
45 | float: left;
46 | -webkit-backface-visibility: hidden;
47 | -webkit-tap-highlight-color: transparent;
48 | -webkit-touch-callout: none; }
49 | .owl-carousel .owl-item img {
50 | display: block;
51 | width: 100%; }
52 | .owl-carousel .owl-nav.disabled,
53 | .owl-carousel .owl-dots.disabled {
54 | display: none; }
55 | .owl-carousel .owl-nav .owl-prev,
56 | .owl-carousel .owl-nav .owl-next,
57 | .owl-carousel .owl-dot {
58 | cursor: pointer;
59 | -webkit-user-select: none;
60 | -khtml-user-select: none;
61 | -moz-user-select: none;
62 | -ms-user-select: none;
63 | user-select: none; }
64 | .owl-carousel .owl-nav button.owl-prev,
65 | .owl-carousel .owl-nav button.owl-next,
66 | .owl-carousel button.owl-dot {
67 | border: none;
68 | font: inherit; }
69 | .owl-carousel.owl-loaded {
70 | display: block; }
71 | .owl-carousel.owl-loading {
72 | opacity: 0;
73 | display: block; }
74 | .owl-carousel.owl-hidden {
75 | opacity: 0; }
76 | .owl-carousel.owl-refresh .owl-item {
77 | visibility: hidden; }
78 | .owl-carousel.owl-drag .owl-item {
79 | -ms-touch-action: pan-y;
80 | touch-action: pan-y;
81 | -webkit-user-select: none;
82 | -moz-user-select: none;
83 | -ms-user-select: none;
84 | user-select: none; }
85 | .owl-carousel.owl-grab {
86 | cursor: move;
87 | cursor: grab; }
88 | .owl-carousel.owl-rtl {
89 | direction: rtl; }
90 | .owl-carousel.owl-rtl .owl-item {
91 | float: right; }
92 |
93 | /* No Js */
94 | .no-js .owl-carousel {
95 | display: block; }
96 |
97 | /*
98 | * Owl Carousel - Animate Plugin
99 | */
100 | .owl-carousel .animated {
101 | animation-duration: 1000ms;
102 | animation-fill-mode: both; }
103 |
104 | .owl-carousel .owl-animated-in {
105 | z-index: 0; }
106 |
107 | .owl-carousel .owl-animated-out {
108 | z-index: 1; }
109 |
110 | .owl-carousel .fadeOut {
111 | animation-name: fadeOut; }
112 |
113 | @keyframes fadeOut {
114 | 0% {
115 | opacity: 1; }
116 | 100% {
117 | opacity: 0; } }
118 |
119 | /*
120 | * Owl Carousel - Auto Height Plugin
121 | */
122 | .owl-height {
123 | transition: height 500ms ease-in-out; }
124 |
125 | /*
126 | * Owl Carousel - Lazy Load Plugin
127 | */
128 | .owl-carousel .owl-item {
129 | /**
130 | This is introduced due to a bug in IE11 where lazy loading combined with autoheight plugin causes a wrong
131 | calculation of the height of the owl-item that breaks page layouts
132 | */ }
133 | .owl-carousel .owl-item .owl-lazy {
134 | opacity: 0;
135 | transition: opacity 400ms ease; }
136 | .owl-carousel .owl-item .owl-lazy[src^=""], .owl-carousel .owl-item .owl-lazy:not([src]) {
137 | max-height: 0; }
138 | .owl-carousel .owl-item img.owl-lazy {
139 | transform-style: preserve-3d; }
140 |
141 | /*
142 | * Owl Carousel - Video Plugin
143 | */
144 | .owl-carousel .owl-video-wrapper {
145 | position: relative;
146 | height: 100%;
147 | background: #000; }
148 |
149 | .owl-carousel .owl-video-play-icon {
150 | position: absolute;
151 | height: 80px;
152 | width: 80px;
153 | left: 50%;
154 | top: 50%;
155 | margin-left: -40px;
156 | margin-top: -40px;
157 | background: url("owl.video.play.png") no-repeat;
158 | cursor: pointer;
159 | z-index: 1;
160 | -webkit-backface-visibility: hidden;
161 | transition: transform 100ms ease; }
162 |
163 | .owl-carousel .owl-video-play-icon:hover {
164 | -ms-transform: scale(1.3, 1.3);
165 | transform: scale(1.3, 1.3); }
166 |
167 | .owl-carousel .owl-video-playing .owl-video-tn,
168 | .owl-carousel .owl-video-playing .owl-video-play-icon {
169 | display: none; }
170 |
171 | .owl-carousel .owl-video-tn {
172 | opacity: 0;
173 | height: 100%;
174 | background-position: center center;
175 | background-repeat: no-repeat;
176 | background-size: contain;
177 | transition: opacity 400ms ease; }
178 |
179 | .owl-carousel .owl-video-frame {
180 | position: relative;
181 | z-index: 1;
182 | height: 100%;
183 | width: 100%; }
184 |
--------------------------------------------------------------------------------
/views/home.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
17 | LANÇAR TAGS AQUI
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
132 visualizações
35 |
154 pessoas compraram
36 |
37 |
38 |
39 | Adicionar ao carrinho
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | LANÇAR TAGS AQUI
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
132 visualizações
65 |
154 pessoas compraram
66 |
67 |
68 |
69 | Adicionar ao carrinho
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | LANÇAR TAGS AQUI
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
132 visualizações
95 |
154 pessoas compraram
96 |
97 |
98 |
99 | Adicionar ao carrinho
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | LANÇAR TAGS AQUI
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
132 visualizações
125 |
154 pessoas compraram
126 |
127 |
128 |
129 | Adicionar ao carrinho
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/views/pages/produtos/product-datail.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 |
102 |
103 |
104 |
105 |
106 |
107 |
Detail overview
108 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
109 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
110 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
111 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
112 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
113 | proident, sunt in culpa qui officia ididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
114 | quis nostrud exercitation ullamco laboris nisi deserunt mollit anim id est laborum.
115 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
116 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
117 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
118 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
119 | cillum dolore eu fugiat nulla pariatur. Excepteurididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
120 | quis nostrud exercitation ullamco laboris nisi sint occaecat cupidatat non
121 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
122 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
123 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
124 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
125 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
126 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
127 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
128 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
129 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
130 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
131 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
132 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
133 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
134 |
135 |
136 |
137 |
138 |
139 |
--------------------------------------------------------------------------------
/public/plugins/prism/prism.js:
--------------------------------------------------------------------------------
1 | /* PrismJS 1.11.0
2 | http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */
3 | var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(\w+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,disableWorkerMessageHandler:_self.Prism&&_self.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof r?new r(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(w instanceof s)){h.lastIndex=0;var _=h.exec(w),P=1;if(!_&&m&&b!=t.length-1){if(h.lastIndex=k,_=h.exec(e),!_)break;for(var A=_.index+(d?_[1].length:0),j=_.index+_[0].length,x=b,O=k,N=t.length;N>x&&(j>O||!t[x].type&&!t[x-1].greedy);++x)O+=t[x].length,A>=O&&(++b,k=O);if(t[b]instanceof s||t[x-1].greedy)continue;P=x-b,w=e.slice(k,O),_.index-=k}if(_){d&&(p=_[1].length);var A=_.index+p,_=_[0].slice(p),j=A+_.length,S=w.slice(0,A),C=w.slice(j),M=[b,P];S&&(++b,k+=S.length,M.push(S));var E=new s(g,f?n.tokenize(_,f):_,y,_,m);if(M.push(E),C&&M.push(C),Array.prototype.splice.apply(t,M),1!=P&&n.matchGrammar(e,t,r,b,k,!0,g),i)break}else if(i)break}}}}},tokenize:function(e,t){var r=[e],a=t.rest;if(a){for(var l in a)t[l]=a[l];delete t.rest}return n.matchGrammar(e,r,t,0,0,!1),r},hooks:{all:{},add:function(e,t){var r=n.hooks.all;r[e]=r[e]||[],r[e].push(t)},run:function(e,t){var r=n.hooks.all[e];if(r&&r.length)for(var a,l=0;a=r[l++];)a(t)}}},r=n.Token=function(e,t,n,r,a){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length,this.greedy=!!a};if(r.stringify=function(e,t,a){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return r.stringify(n,t,e)}).join("");var l={type:e.type,content:r.stringify(e.content,t,a),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:a};if(e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o=Object.keys(l.attributes).map(function(e){return e+'="'+(l.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+l.tag+' class="'+l.classes.join(" ")+'"'+(o?" "+o:"")+">"+l.content+""+l.tag+">"},!_self.document)return _self.addEventListener?(n.disableWorkerMessageHandler||_self.addEventListener("message",function(e){var t=JSON.parse(e.data),r=t.language,a=t.code,l=t.immediateClose;_self.postMessage(n.highlight(a,n.languages[r],r)),l&&_self.close()},!1),_self.Prism):_self.Prism;var a=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return a&&(n.filename=a.src,n.manual||a.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
4 | Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/(^|[^\\])["']/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/?[\da-z]{1,8};/i},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Prism.languages.xml=Prism.languages.markup,Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup;
5 | Prism.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^{}\s][^{};]*?(?=\s*\{)/,string:{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},Prism.languages.css.atrule.inside.rest=Prism.util.clone(Prism.languages.css),Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/(