first commit

This commit is contained in:
Caroline Moran 2022-08-11 09:06:07 -04:00
commit f2a03c53ae
335 changed files with 32042 additions and 0 deletions

6
.dockerignore Normal file
View File

@ -0,0 +1,6 @@
node_modules
Dockerfile
.dockerignore
.git
.gitignore
.yarnrc

12
.editorconfig Normal file
View File

@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
* text=auto eol=lf

79
.gitignore vendored Normal file
View File

@ -0,0 +1,79 @@
*node_modules
node_modules
# para arquivos sass e scss
storefront/styles/css
**/*.sass-cache/
**/*.css.map
# Para arquivos de desenvolvimnto
public/
src\arquivos\sass\lib\_sprite.scss
# gulp
dist/
.temp/
# node
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.vscode/*
!.vscode/extensions.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.scannerwork

10
.gitpod.yml Normal file
View File

@ -0,0 +1,10 @@
# This configuration file was automatically generated by Gitpod.
# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
# and commit this file to your remote git repository to share the goodness with others.
tasks:
- init: yarn install
vscode:
extensions:
- dbaeumer.vscode-eslint

1
.husky/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_

4
.husky/commit-msg Normal file
View File

@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
yarn commitlint --edit $1

8
.husky/common.sh Normal file
View File

@ -0,0 +1,8 @@
command_exists () {
command -v "$1" >/dev/null 2>&1
}
# Workaround for Windows 10, Git Bash and Yarn
if command_exists winpty && test -t 1; then
exec < /dev/tty
fi

4
.husky/pre-commit Normal file
View File

@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
yarn lerna run --concurrency 3 --stream lint --since HEAD --exclude-dependents

9
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"recommendations": [
"sonarsource.sonarlint-vscode",
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"esbenp.prettier-vscode",
"eamodio.gitlens"
]
}

18
Dockerfile Normal file
View File

@ -0,0 +1,18 @@
FROM node:14
WORKDIR /app
RUN npm i -g vtex concurrently gulp
RUN yarn
COPY . .
RUN mkdir /root/.vtex
RUN chmod o+rx /root
RUN chown -R node /root/.vtex
RUN ln -s /root/.vtex /home/node/
CMD ["yarn", "vlink"]

14
README.md Normal file
View File

@ -0,0 +1,14 @@
# {NOME DA LOJA}
## Instalação e desenvolvimento
[Voce pode encontrar a base o desenvolvimento de cada projeto aqui](https://gitlab.com/agenciam3/pattern/documentacao/-/blob/master/vtex/IO/implementa%C3%A7%C3%A3o-io.md)
## Custom - Apps
## Especificações de produto
## Estruturas customizadas do Master Data
NODEJS >= 12

19
bitbucket-pipelines.yml Normal file
View File

@ -0,0 +1,19 @@
image: maven:3.3.9
clone:
depth: full
pipelines:
pull-requests:
"**":
- step:
name: SonarQube analysis
script:
- pipe: sonarsource/sonarqube-scan:1.0.0
variables:
SONAR_HOST_URL: ${SONAR_HOST_URL} # Get the value from the repository/workspace variable.
SONAR_TOKEN: ${SONAR_TOKEN} # Get the value from the repository/workspace variable. You shouldn't set secret in clear text here.
definitions:
caches:
sonar: ~/.sonar

22
checkout/.eslintrc.js Normal file
View File

@ -0,0 +1,22 @@
module.exports = {
env: {
browser: true,
commonjs: true,
es6: false,
jquery: true,
},
globals: {
Modulo: true,
},
extends: ["eslint:recommended", "plugin:prettier/recommended"],
plugins: ["prettier"],
parserOptions: {
ecmaVersion: 10,
sourceType: "module",
},
rules: {
"prettier/prettier": "error",
"linebreak-style": ["warn", "unix"],
"no-undef": "off",
},
};

View File

@ -0,0 +1,6 @@
{
"semi": true,
"singleQuote": false,
"tabWidth": 4,
"useTabs": false
}

140
checkout/gulpfile.js Normal file
View File

@ -0,0 +1,140 @@
const gulp = require("gulp"),
gulpif = require("gulp-if"),
del = require("del"),
connect = require("gulp-connect"),
sourcemaps = require("gulp-sourcemaps"),
autoprefixer = require("gulp-autoprefixer"),
rename = require("gulp-rename"),
sass = require("gulp-sass")(require("sass"));
/**
___ _ _ _ _
/ __| |_ ___ __| |_____ _ _| |_ ___ ___| |_ _ _ _ __
| (__| ' \/ -_) _| / / _ \ || | _| (_-</ -_) _| || | '_ \
\___|_||_\___\__|_\_\___/\_,_|\__| /__/\___|\__|\_,_| .__/
|_|
*/
const webpack = require("webpack");
const pacote = require("../package.json");
const isProduction = process.env.NODE_ENV === "production";
const paths = {
styles: {
src: "src/arquivos/sass/*.{scss,css,sass}",
lib: "src/arquivos/sass/lib",
watch: "src/arquivos/sass/**/*.scss",
},
scripts: {
watch: "src/arquivos/js/**/*.js",
},
img: {
src: "src/arquivos/img/*.{png,gif,jpg}",
watch: "src/arquivos/img/**/*.{png,gif,jpg}",
},
fonts: {
src: "src/arquivos/fonts/**.*",
},
output: "dist",
outputStatic: "dist/arquivos",
tmp: ".temp",
};
function clean() {
return del([paths.output, paths.tmp]);
}
function styles() {
return gulp
.src(paths.styles.src)
.pipe(gulpif(!isProduction, sourcemaps.init()))
.pipe(
sass({
outputStyle: "compressed",
}).on("error", sass.logError)
)
.pipe(
autoprefixer({
cascade: false,
})
)
.pipe(
rename({
prefix: pacote.name + "--",
extname: ".css",
})
)
.pipe(gulpif(!isProduction, sourcemaps.write()))
.pipe(gulp.dest(paths.outputStatic))
.pipe(connect.reload());
}
function scripts() {
let webpackConfig = require("./webpack.dev.js");
if (process.env.NODE_ENV === "production") {
webpackConfig = require("./webpack.prod.js");
}
return new Promise((resolve) =>
webpack(webpackConfig, (err, stats) => {
if (err) console.log("Webpack", err);
console.log(
stats.toString({
all: false,
modules: false,
maxModules: 0,
errors: true,
warnings: true,
moduleTrace: true,
errorDetails: true,
colors: true,
chunks: true,
})
);
resolve();
connect.reload();
})
);
}
function customFonts() {
return gulp
.src(paths.fonts.src)
.pipe(
rename((path) => ({
dirname: "",
basename: path.basename,
extname: path.extname + ".css",
}))
)
.pipe(gulp.dest(paths.outputStatic))
.pipe(connect.reload());
}
function watch() {
devServer();
gulp.watch(paths.scripts.watch, { ignoreInitial: false }, scripts);
gulp.watch(paths.styles.watch, { ignoreInitial: false }, styles);
gulp.watch(paths.fonts.src, { ignoreInitial: false }, customFonts);
}
function devServer() {
connect.server({
root: paths.output,
livereload: true,
port: 3000,
});
}
const build = gulp.series(clean, gulp.parallel(scripts, styles, customFonts));
exports.build = build;
exports.clean = clean;
exports.scripts = scripts;
exports.styles = styles;
exports.devServer = devServer;
exports.watch = gulp.series(build, watch);

56
checkout/package.json Normal file
View File

@ -0,0 +1,56 @@
{
"name": "checkout",
"version": "1.0.0",
"main": "index.js",
"license": "UNLICENSED",
"scripts": {
"dev": "cross-env NODE_ENV=development gulp watch",
"prod": "cross-env NODE_ENV=production gulp build",
"lint": "eslint ./src --fix"
},
"dependencies": {
"@agenciam3/pkg": "^1.1.13",
"@babel/plugin-transform-async-to-generator": "^7.14.5",
"cookie": "^0.4.1",
"del": "^6.0.0",
"glob": "^7.1.7",
"gulp": "^4.0.2",
"gulp-autoprefixer": "^8.0.0",
"gulp-concat": "^2.6.1",
"gulp-connect": "^5.7.0",
"gulp-if": "^3.0.0",
"gulp-rename": "^2.0.0",
"gulp-sass": "^5.0.0",
"gulp-sourcemaps": "^3.0.0",
"jquery": "^3.6.0",
"sass": "^1.38.1",
"terser-webpack-plugin": "^5.1.4"
},
"devDependencies": {
"@babel/core": "^7.15.0",
"@babel/preset-env": "^7.15.0",
"@babel/preset-react": "^7.14.5",
"babel-loader": "^8.2.2",
"cross-env": "^7.0.3",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.1",
"lint-staged": "^11.1.2",
"prettier": "^2.3.2",
"webpack": "^5.51.1",
"webpack-merge": "^5.8.0"
},
"babel": {
"presets": [
"@babel/env",
"@babel/react"
]
},
"browserslist": [
"defaults"
],
"lint-staged": {
"src/**/*": [
"yarn lint"
]
}
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1018 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,14 @@
import CheckoutUI from "./components/CheckoutUI";
import { Container } from "@agenciam3/pkg";
import Exemple from "./components/Exemple";
import ExempleEvent from "./components/ExempleEvent";
// import CatalogService from "./services/CatalogService";
// import CheckoutService from "./services/checkout/CheckoutService";
const m3Checkout = new Container({
appName: "m3-checkout",
// services: [CatalogService, CheckoutService],
components: [CheckoutUI, Exemple, ExempleEvent],
});
m3Checkout.start();

View File

@ -0,0 +1,69 @@
import { isSmallerThen768 } from "../helpers/MediasMatch";
import { alterarTamanhoImagemSrcVtex } from "../helpers/vtexUtils";
import waitForEl from "../helpers/waitForEl";
export default class CheckoutUI {
constructor() {
this.init();
if (isSmallerThen768) {
this.selectors();
this.events();
this.setFooterDropdown();
}
}
selectors() {
this.title = $(".footerCheckout__title");
this.contents = $(".footerCheckout__content");
}
events() {
this.title.click(this.toggleFooterDropdown.bind(this));
}
setFooterDropdown() {
for (let i = 0; i < this.title.length; i++) {
this.title[i].classList.add("dropdown__title");
this.contents[i].classList.add("dropdown__content--closed");
}
}
toggleFooterDropdown(event) {
event.target.classList.toggle("closed");
event.target.nextElementSibling.classList.toggle(
"dropdown__content--closed"
);
}
init() {
this.configThumb();
waitForEl(".product-image img", this.resizeImages.bind(this));
$(window).on("orderFormUpdated.vtex", this.resizeImages.bind(this));
}
configThumb() {
if (isSmallerThen768) {
this.width = 73;
this.height = 96;
} else {
this.width = 63;
this.height = 83;
}
}
resizeImages() {
$(".product-image img").each((i, el) => {
const $el = $(el);
$el.attr(
"src",
alterarTamanhoImagemSrcVtex(
$el.attr("src"),
this.width,
this.height
)
);
});
}
}

View File

@ -0,0 +1,18 @@
import waitForEl from "../helpers/waitForEl";
export default class Exemple {
constructor() {
this.init();
}
async init() {
await this.selectors();
console.log(this.item);
}
async selectors() {
this.item = await waitForEl(
".summary-cart-template-holder .cart-items"
);
}
}

View File

@ -0,0 +1,12 @@
export default class ExempleEvent {
constructor() {
this.eventos();
}
eventos() {
$(window).on("orderFormUpdated.vtex", this.onUpdate.bind(this));
}
onUpdate(orderForm) {
console.log(orderForm);
}
}

View File

@ -0,0 +1,34 @@
/**
* Helper de para ultização de eventos sobre a navegação por hash
*/
export default class HashRouter {
constructor(routes) {
this.routes = routes;
window.addEventListener("hashchange", this.hashChange.bind(this));
this.init();
}
hashChange(e) {
const from = new URL(e.oldURL).hash || "/";
const to = new URL(e.newURL).hash || "/";
this.routes.forEach((route) => {
if (route.path === to) {
route.onEnter && route.onEnter();
} else if (route.path === from) {
route.onLeave && route.onLeave();
}
});
}
init() {
const actualHash = window.location.hash || "/";
this.routes.forEach((route) => {
if (route.path === actualHash) {
route.onEnter && route.onEnter();
}
});
}
}

View File

@ -0,0 +1 @@
export const isSmallerThen768 = window.matchMedia("(max-width:768px)").matches;

View File

@ -0,0 +1,75 @@
/* eslint-disable no-useless-escape */
import cookie from "cookie";
class Cookie {
get(sKey) {
if (!sKey) {
return null;
}
const cookies = cookie.parse(document.cookie);
return cookies[sKey] || null;
}
set(sKey, sValue, vEnd, sPath, sDomain, bSecure) {
if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) {
return false;
}
var sExpires = "";
if (vEnd) {
switch (vEnd.constructor) {
case Number:
sExpires =
vEnd === Infinity
? "; expires=Fri, 31 Dec 9999 23:59:59 GMT"
: "; max-age=" + vEnd;
break;
case String:
sExpires = "; expires=" + vEnd;
break;
case Date:
sExpires = "; expires=" + vEnd.toUTCString();
break;
}
}
document.cookie =
encodeURIComponent(sKey) +
"=" +
encodeURIComponent(sValue) +
sExpires +
(sDomain ? "; domain=" + sDomain : "") +
(sPath ? "; path=" + sPath : "") +
(bSecure ? "; secure" : "");
return true;
}
delete(sKey, sPath, sDomain) {
if (!this.hasItem(sKey)) {
return false;
}
document.cookie =
encodeURIComponent(sKey) +
"=; expires=Thu, 01 Jan 1970 00:00:00 GMT" +
(sDomain ? "; domain=" + sDomain : "") +
(sPath ? "; path=" + sPath : "");
return true;
}
has(sKey) {
if (!sKey) {
return false;
}
return new RegExp(
"(?:^|;\\s*)" +
encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") +
"\\s*\\="
).test(document.cookie);
}
keys() {
return cookie.parse(document.cookie);
}
}
export default new Cookie();

View File

@ -0,0 +1,28 @@
/**
* Função para verificar se estamos em uma das paginas
* que são passadas por argumento
* @param {array} [varname] um array de strings
* @return {Boolean} [description]
*/
function isPage() {
const identificacaoMetaPage = $('meta[name="page"]').prop("content") || "";
const classTagBody = $("body").attr("class") || "";
const pageDataLayer =
typeof dataLayer !== "undefined"
? window.dataLayer[0].pageCategory
: "";
for (const i in arguments) {
// resultado-busca na tag body
if (
identificacaoMetaPage.search(arguments[i]) >= 0 ||
pageDataLayer === arguments[i] ||
classTagBody.search(arguments[i]) >= 0
)
return true;
}
return false;
}
export default isPage;

View File

@ -0,0 +1,74 @@
/**
* Altera as dimenções especificadas na url da img
* @param {string} src url da imagem na VTEX
* @param {int} width
* @param {int} height
* @return {string} url da imagem com o tamanho alterado
*/
export function alterarTamanhoImagemSrcVtex(src, width, height) {
if (typeof src == "undefined") {
console.warn("Parametro 'src' não recebido.");
return;
}
width = typeof width == "undefined" ? 1 : width;
height = typeof height == "undefined" ? width : height;
src = src.replace(
/\/(\d+)(-(\d+-\d+)|(_\d+))\//g,
"/$1-" + width + "-" + height + "/"
);
return src;
}
/**
* Obtem Preco
* caso o preco recebido seja um Float ou int,
* 'Ex.': 10.2 ->'10,20'
* Recebendo uma string o valor sera retornado como um float
* 'Ex.': 'R$1.234,30' -> 1234.3
* @param {FloatZstring} price preço
* @return {[type]} [description]
*/
export function getPrice(price) {
if (!price) {
return 0;
}
if (isNaN(price)) {
return parseFloat(
price.replace("R$", "").replace(".", "").replace(",", ".")
);
} else {
price = price || 0;
price = price.toLocaleString("pt-BR", {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
return price;
}
}
export function formatCurrency() {
return Number(value).toLocaleString("pt-BR", {
style: "currency",
currency: "BRL",
});
}
export function getSellerChannel() {
var name = "VTEXSC=sc=";
var ca = document.cookie.split(";");
let res = "1";
ca.forEach((c) => {
let value = String(c);
while (value.charAt(0) == " ") value = value.substring(1);
if (value.indexOf(name) == 0) {
res = value.substring(name.length, value.length);
}
});
return res;
}

View File

@ -0,0 +1,22 @@
/**
* Espera um elemento exitir no dom e executa o callback
*
* @param {string} selector seletor do elemento que dejesa esperar pela criação
* @param {function} callback Função a ser executada quando tal elemento existir
*/
export default function waitForEl(selector) {
return new Promise((resolve) => {
function waitForElCb(s) {
const el = jQuery(s);
if (el.length) {
resolve(el);
} else {
setTimeout(function () {
waitForElCb(selector);
}, 100);
}
}
waitForElCb(selector);
});
}

View File

@ -0,0 +1,25 @@
var Evento = function () {
var _this = this;
_this.handlers = [];
_this.subscribe = function (fn) {
this.handlers.push(fn);
}.bind(_this);
_this.unsubscribe = function (fn) {
this.handlers = this.handlers.filter(function (item) {
if (item !== fn) {
return item;
}
});
}.bind(_this);
_this.fire = function (dados, thisObj) {
var scope = thisObj || window;
this.handlers.forEach(function (item) {
item.call(scope, dados);
});
}.bind(_this);
};
export default Evento;

View File

@ -0,0 +1,105 @@
import Evento from "./Evento";
var RestricaoDeConculsao = function (funcaoDeAvaliacao, mensagemDeErro) {
var _this = this,
_regraAtiva = true,
_mensagemDeErro;
var eventos = {
tentativaDeFinalizacao: new Evento(),
aplicavel: new Evento(),
naoAplicavel: new Evento(),
};
_this.on = function (evento, fn) {
if (Reflect.has(eventos, evento)) {
eventos[evento].subscribe(fn);
}
};
_this.off = function (evento, fn) {
if (Reflect.has(eventos, evento)) {
eventos[evento].unsubscribe(fn);
}
};
_this.mensagemDeErro = function (
mensagemDeErro = "Forneca as informações para finalizar a compra"
) {
if (mensagemDeErro) _mensagemDeErro = mensagemDeErro;
return _mensagemDeErro;
};
_this.inicializar = function configurarEventos() {
$(window).on("orderFormUpdated.vtex", atualizacaoDoPedido);
window.vtexjs.checkout.getOrderForm();
};
function feedback(tipo, titulo, detalhe) {
var message = {
content: {
title: titulo,
detail: detalhe,
},
type: tipo,
};
if ("undefined" != typeof $) {
$(window).trigger("addMessage", message);
} else {
console.warn("Erro ao acionar front-messages-ui");
}
}
function clickBtnDesabilitado(event) {
event.preventDefault();
feedback("warning", "Erro ", _mensagemDeErro);
eventos.tentativaDeFinalizacao.fire();
}
function aplicavel(alternativa) {
// se a regra estiver desativada não sera aplicada
alternativa = alternativa && _regraAtiva;
var evento = alternativa ? "aplicavel" : "naoAplicavel";
eventos[evento].fire();
ativacao(alternativa);
}
function ativacao(alternativa) {
var $btnContainer = $(".payment-submit-wrap,.payment-submit-hide");
var btns = $btnContainer.find("button");
btns.each(function (i, el) {
$(el).toggleClass("btn-warning", alternativa);
});
if (!alternativa) {
$btnContainer.off("click", clickBtnDesabilitado);
} else {
$btnContainer.on("click", clickBtnDesabilitado);
}
}
_this.ativar = function () {
_regraAtiva = true;
ativacao(_regraAtiva);
};
_this.desativar = function () {
_regraAtiva = false;
ativacao(_regraAtiva);
};
function atualizacaoDoPedido(event, orderform) {
var ehAplicavel = funcaoDeAvaliacao.call(funcaoDeAvaliacao, orderform);
if (typeof ehAplicavel === "boolean") {
aplicavel(ehAplicavel);
} else {
aplicavel(false);
console.error(
"função de avaliação retornando resultado indefinido.\n",
ehAplicavel
);
}
}
_this.mensagemDeErro(mensagemDeErro);
_this.inicializar();
};
export default RestricaoDeConculsao;

View File

@ -0,0 +1,17 @@
export default class CatalogService {
async getSkusData(skus) {
const skusPromises = skus.map(this.getSkuData);
const responses = await Promise.all(skusPromises);
return Promise.all(responses.map((r) => r.json()));
}
getSkuData(sku) {
const urlSku = "/produto/sku/" + sku;
return fetch(urlSku, {
method: "GET",
});
}
}

View File

@ -0,0 +1,29 @@
export default class CartItem {
constructor({
productID,
skuID,
url,
imageUrl,
name,
priceOf,
price,
maxInstallmentAmount,
maxInstallmentValue,
qtd,
id,
availableQtd,
}) {
this.id = id;
this.productID = productID;
this.skuID = skuID;
this.url = url;
this.imageUrl = imageUrl;
this.name = name;
this.priceOf = priceOf;
this.price = price;
this.maxInstallmentAmount = maxInstallmentAmount;
this.maxInstallmentValue = maxInstallmentValue;
this.qtd = qtd;
this.availableQtd = availableQtd;
}
}

View File

@ -0,0 +1,97 @@
import { getSalesChannel } from "Helpers/utils";
import { PubSub } from "@agenciam3/pkg/dist/lib/index";
import CartItem from "./CartItem";
export default class CheckoutService {
constructor() {
this.eventsName = {
CHECKOUT_UPDATED: "CHECKOUT_UPDATED",
ORDERFORM_UPDATED: "ORDERFORM_UPDATED",
};
this.events = new PubSub();
if (window.vtexjs) {
this.checkout = window.vtexjs.checkout;
this.orderform = window.vtexjs.checkout.orderForm;
this.events.subscribe(
this.eventsName.ORDERFORM_UPDATED,
this._orderFormUpdated.bind(this)
);
}
}
_orderFormUpdated(evt, orderForm) {
const cartItems = this._mapOrderFormToCartItems(orderForm);
this.events.publish(this.eventsName.CHECKOUT_UPDATED, cartItems);
}
async addItemsToCart(items) {
try {
return await this.checkout.addToCart(
items,
null,
getSalesChannel()
);
} catch (err) {
console.log(err);
}
}
async rmAllItems() {
try {
return await this.checkout.removeAllItems();
} catch (err) {
console.log(err);
}
}
async updateCartItemsQtd(items, qtd) {
try {
const orderForm = await this.checkout.getOrderForm();
let itemIndex;
for (let i = 0; i < orderForm.items.length; i++) {
if (orderForm.items[i].uniqueId == items.id) {
itemIndex = i;
}
}
const updateItem = {
index: itemIndex,
quantity: qtd,
};
return await window.vtexjs.checkout.updateItems(
[updateItem],
null,
false
);
} catch (err) {
console.log(err);
}
}
async getCartItems() {
try {
const orderform = await this.checkout.getOrderForm();
return this._mapOrderFormToCartItems(orderform);
} catch (err) {
return [];
}
}
_mapOrderFormToCartItems(orderform) {
if (orderform.items.length === 0) return [];
return orderform.items.map(
(item) =>
new CartItem({
id: item.uniqueId,
imageUrl: item.imageUrl,
skuID: item.id,
productID: item.productId,
qtd: item.quantity,
price: item.price,
priceOf: item.listPrice,
name: item.name,
url: item.detailUrl,
})
);
}
}

View File

@ -0,0 +1,5 @@
@import "./utils/all";
@import "./partials/header";
@import "./partials/footer";

View File

@ -0,0 +1,289 @@
.checkout-container {
.client-pre-email {
border-color: $color-gray4;
font-family: $font-family;
padding-top: 8px;
.link-cart {
a {
color: $color-black;
font-size: 14px;
&:hover {
color: lighen($color-black, 10);
}
}
}
.pre-email {
flex-direction: column;
display: flex;
align-items: center;
justify-content: center;
h3 {
margin-bottom: 16px;
span {
color: #303030;
font-size: 24px;
}
small {
color: $color-gray4;
}
}
}
.client-email {
margin: 0 0 16px;
input {
box-shadow: none;
color: $color-black;
font-family: $font-family;
padding: 0 16px;
border: 2px solid $color-gray3;
box-sizing: border-box;
border-radius: 5px;
@media (max-width: 490px) {
width: auto;
}
}
button {
background-color: $color-black;
border-radius: 5px;
border: none;
font-family: $font-family;
height: 54px;
right: 0;
top: 0;
@media (max-width: 490px) {
height: 48px;
margin: 0;
position: absolute;
}
}
span.help.error {
color: red;
}
}
.emailInfo {
padding: 16px;
background-color: $color-white;
border: 1px solid $color-gray4;
border-radius: 0;
h3 {
color: #303030;
margin: 0 0 8px 0;
}
ul {
margin: 0;
li {
span {
color: $color-black;
}
i::before {
color: $color-black;
font-size: 1rem;
opacity: 1;
}
}
}
i::before {
color: $color-black;
font-size: 6rem;
opacity: 0.5;
}
}
}
.shipping-data,
.payment-data,
.client-profile-data {
.accordion-group {
border-radius: 0;
border: 1px solid $color-gray4;
font-family: $font-family;
padding: 16px;
.accordion-heading {
span {
color: #303030;
margin-bottom: 8px;
padding: 0;
i::before {
fill: #303030;
}
}
a {
align-items: center;
background-color: #303030;
border-radius: 8px;
border: none;
color: $color-white;
display: flex;
justify-content: center;
padding: 6px 5px 6px 8px;
}
}
.accordion-inner {
padding: 0;
/* General configurations */
.client-notice {
color: $color-black;
}
p {
label {
color: $color-black;
font-weight: 500;
}
select,
input {
border-radius: 0;
border: 1px solid $color-gray4;
box-shadow: none;
}
.help.error {
color: red;
}
}
.box-client-info-pj {
.link a#is-corporate-client,
.link a#not-corporate-client {
color: $color-black;
font-weight: 500;
text-decoration: underline;
}
}
.state-inscription-box span {
font-weight: 500;
}
button.submit {
border: none;
border-radius: 5px;
background: $color-black;
margin-top: 8px;
outline: none;
transition: all 0.2s linear;
&:hover {
background: lighten($color-black, 5);
}
&:active {
background: darken($color-black, 5);
}
}
/* Shipping configurations */
.ship-postalCode small a {
color: #303030;
font-weight: 500;
text-decoration: underline;
}
.vtex-omnishipping-1-x-deliveryGroup {
p {
color: #303030;
font-size: 14px;
font-weight: 500;
}
.shp-lean {
border: 1px solid $color-gray4;
border-radius: 0;
label {
background-color: $color-white;
box-shadow: none;
color: #303030;
padding: 8px 12px;
svg path {
fill: #d8c8ac;
}
}
}
}
.delivery-address-title {
color: #303030;
font-size: 14px;
font-weight: 500;
}
.shp-summary-group-info {
border-color: $color-gray4;
}
.address-summary {
background: none;
border-color: $color-gray4;
border-radius: 0;
color: #303030;
padding: 12px;
@include mq(md, max) {
background-position: 8px 9px;
}
a {
color: #303030;
font-weight: 500;
text-decoration: underline;
}
}
.shp-summary-group-price,
.shp-summary-package {
color: $color-gray4;
}
.shp-summary-group-price {
padding-right: 16px;
}
.shp-summary-package {
padding-left: 16px;
}
.vtex-omnishipping-1-x-summaryChange {
border-color: #303030;
color: #303030;
}
.vtex-omnishipping-1-x-deliveryChannelsToggle {
background-color: #d8c8ac;
border: 1px solid #d8c8ac;
}
.vtex-omnishipping-1-x-deliveryOptionActive {
text-shadow: 1.3px 1px lighten($color-black, 50);
}
}
}
}
}

View File

@ -0,0 +1,814 @@
.container {
@include mq(md, max) {
width: 100%;
}
}
.cart-template {
font-family: $font-family;
@include mq(md, max) {
padding: 0 0;
}
.item-unit-label {
display: none;
}
.cart {
border: 3px solid $color-gray3;
box-sizing: border-box;
border-radius: 5px;
padding: 16px;
@include mq(md, max) {
margin: 0px 0 25px 0;
border-left: none;
border-right: none;
border-radius: 0;
}
}
.cart-fixed {
font-family: $font-family;
h2 {
background: $color-white;
border: none;
color: #303030;
font-size: 14px;
font-weight: 500;
}
.item-unavailable {
padding: 0;
&-message {
padding: 8px;
}
}
.cart {
border: 1px solid $color-gray4;
ul li {
border-top: none;
margin-top: 0;
padding-top: 0;
&:not(:first-child) {
margin-top: 8px;
padding-top: 8px;
border-top: 1px solid #e5e5e5;
}
.shipping-date,
.price {
color: #7d7d7d;
}
}
}
.summary-template-holder {
border-top: none;
background: $color-white;
}
#go-to-cart-button a {
color: #303030;
text-decoration: underline;
}
.summary-totalizers {
td.info {
width: 100%;
}
}
#payment-data-submit {
background: $color-black;
border: none;
border-radius: 0;
color: $color-white;
outline: none;
transition: all 0.2s linear;
&:hover {
background: lighten($color-black, 5);
}
&:active {
background: darken($color-black, 5);
}
}
}
.lookatme {
background-color: $color-white;
}
.cart-items {
.product-item {
padding: 16px 0;
}
th {
color: $color-black;
padding: 0 0 16px;
font-style: normal;
font-weight: bold;
font-size: 14px;
line-height: 16px;
@include mq(md, max) {
&.quantity-price,
&.shipping-date {
display: none;
}
}
}
.product-image {
height: auto;
padding: 0;
width: 60px;
@include mq(sm, max) {
width: 72px;
}
img {
height: 60px;
max-width: 100%;
width: auto;
@include mq(sm, max) {
height: 72px;
width: auto;
}
}
}
.product-name {
padding-right: 0;
@include mq(lg, max) {
width: 250px;
}
a {
color: $color-blue;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 14px;
transition: ease-in 0.22s all;
&:hover {
color: darken($color-blue, 10);
text-decoration: none;
}
@media (max-width: 490px) {
margin-left: 23px;
}
}
.brand,
.seller {
display: none !important;
}
}
td.shipping-date {
color: $color-gray2;
font-size: 12px;
line-height: 14px;
@include mq(md, max) {
display: none;
}
}
.product-price {
min-width: 100px;
@include mq(md, max) {
min-width: 78px;
}
@media (max-width: 490px) {
position: absolute;
bottom: 0;
right: 0;
}
span.list-price {
color: $color-gray2;
font-size: 12px;
line-height: 14px;
text-decoration-line: line-through;
@include mq(sm, max) {
font-size: 12px;
line-height: 14px;
}
.old-product-price-label {
text-transform: lowercase;
}
}
}
td.quantity {
align-items: center;
border: 1px solid $color-gray3;
border-radius: 0;
box-sizing: border-box;
display: flex;
justify-content: center;
margin: 6px auto 0;
max-height: 38px;
max-width: 118px;
padding: 0;
width: max-content !important;
@media (max-width: 490px) {
margin-left: 84px !important;
}
input {
background-color: $color-white;
border: 1px solid $color-gray3;
border-radius: 0;
border-width: 0 1px;
display: block;
max-height: 38px;
margin: 0 !important;
padding: 8px 0;
width: 38px;
color: $color-gray2;
box-shadow: none;
@include mq(lg, max) {
width: 24px !important;
}
}
.icon-plus-sign,
.icon-minus-sign {
&::before {
color: $color-black;
display: block;
font-weight: 500;
padding: 1px 12px;
}
}
.icon-minus-sign {
&:before {
content: "-";
font-size: 16px;
}
}
.icon-plus-sign {
&:before {
content: "+";
font-size: 14px;
}
}
.item-quantity-change {
@media (max-width: 979px) and (min-width: 768px) {
position: inherit;
bottom: inherit;
left: inherit;
height: inherit;
width: inherit;
top: inherit;
}
@media (max-width: 490px) {
padding: 0;
}
}
}
.quantity-price,
.best-price {
.icon-question-sign {
display: none;
}
span {
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 16px;
color: $color-black;
}
}
.quantity-price {
@include mq(md, max) {
display: none;
}
}
.item-remove {
@media (max-width: 490px) {
top: 0;
}
.icon::before {
color: $color-gray4;
font-size: 15px;
@include mq(md, max) {
font-size: 18px;
}
}
}
.item-unavailable-message {
background-color: #d8c8ac;
color: $color-white;
.icon-warning-sign {
color: #bb4f4f;
}
.top-arrow {
border-bottom-color: #d8c8ac;
}
}
}
.summary {
.cart-more-options {
margin: 0;
width: max-content;
.srp-container {
padding: 0 0 0 10px;
@include mq(md, max) {
padding: 0 16px;
}
.srp-main-title {
margin: 32px 0 12px;
font-style: normal;
font-weight: normal;
font-size: 24px;
line-height: 28px;
color: $color-gray2;
@include mq(md, max) {
margin-top: 0;
}
}
.srp-description {
color: $color-gray2;
font-size: 12px;
line-height: 18px;
margin: 0 0 12px;
}
button.shp-open-options {
background-color: $color-gray5;
border: none;
border-radius: 5px;
color: $color-gray2;
font-size: 16px;
letter-spacing: 0.05em;
line-height: 19px;
font-weight: 500;
outline: none;
padding: 12px 40px;
transition: all 0.2s linear;
&:hover {
background-color: lighten($color-gray5, 5);
}
&:active {
background-color: darken($color-gray5, 5);
}
}
}
.srp-data {
width: 280px;
@include mq(cstm, max) {
width: calc(100vw - 32px);
}
@include mq(md, max) {
margin-bottom: 40px;
}
.srp-pickup-my-location__button {
background-color: $color-black;
border: none;
border-radius: 5px;
color: $color-white;
outline: none;
width: 100%;
font-style: normal;
font-weight: 500;
font-size: 14px;
line-height: 16px;
letter-spacing: 0.05em;
&:hover {
background-color: lighten($color-black, 5);
}
&:active {
background-color: darken($color-black, 5);
}
}
}
.srp-toggle {
margin: 0 0 34px;
&__wrapper {
background-color: $color-white;
border-radius: 100px;
width: 100%;
font-family: $font-family;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 16px;
text-transform: uppercase;
}
&__current {
border: 1px solid $color-blue;
border-radius: 100px;
}
.blue {
color: $color-blue;
}
label {
width: 50%;
&:active {
background-color: #f0f0f0;
}
}
}
.srp-postal-code {
.ship-postalCode {
label {
font-family: $font-family;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 14px;
color: $color-black;
margin-bottom: 12px;
}
input {
border: 1px solid $color-gray3;
border-radius: 5px;
box-shadow: none;
color: $color-gray3;
font-size: 12px;
height: 36px;
padding: 12px 8px;
width: 172px;
}
& ~ button {
background-color: $color-black;
border: none;
border-radius: 5px;
color: $color-white;
font-size: 12px;
height: 36px;
letter-spacing: 1px;
outline: none;
position: absolute;
right: -150px;
top: 36px;
transition: all 0.2s linear;
width: 96px;
text-transform: uppercase;
&:hover {
background-color: lighten($color-black, 5);
}
&:active {
background-color: darken($color-black, 5);
}
}
small a {
font-family: $font-family;
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 12px;
color: $color-blue;
margin-top: 7px;
}
span.help.error {
color: red;
font-size: 12px;
position: absolute;
left: 0;
width: 100%;
top: 17px;
}
}
}
.srp-result {
strong,
.srp-items {
color: #303030;
font-weight: 400;
font-size: 14px;
}
#deliver-at-text a {
color: #303030;
font-size: 16px;
font-weight: 500;
&:hover {
text-decoration: underline;
}
}
.srp-shipping-current-single {
border: 1px solid $color-gray4;
border-radius: 0;
color: #303030;
margin: 16px 0 0;
padding: 4px 12px;
svg path {
fill: #d8c8ac;
}
}
.srp-delivery-select {
border: 1px solid $color-gray4;
}
.srp-delivery-select-container {
border: 1px solid $color-gray4;
border-radius: 0;
.srp-shipping-current-many {
&__name {
color: #303030;
}
&__sla {
color: #7d7d7d;
}
&__price {
color: #7d7d7d;
font-weight: 500;
}
&__arrow svg {
fill: $color-gray4;
}
}
}
}
}
&-totalizers {
padding: 0;
width: 346px;
.coupon-data {
#cart-link-coupon-add {
text-decoration: none;
&:hover {
text-decoration: underline;
cursor: pointer;
}
}
span {
font-family: $font-family;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 14px;
color: $color-blue;
text-decoration: none;
}
}
@include mq(md, max) {
padding: 0 16px;
width: 100%;
}
.coupon-column {
.coupon {
margin: 0;
}
.link-coupon-add {
color: #303030;
font-size: 12px;
text-decoration: underline;
}
.coupon-label label {
margin-bottom: 12px;
font-family: $font-family;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 14px;
color: $color-gray2;
cursor: none;
}
.coupon-fields {
margin-bottom: 32px;
@include mq(sm, max) {
span {
display: flex;
flex-direction: row;
justify-content: space-between;
i {
position: absolute;
right: 91px;
opacity: 1;
}
}
}
input {
border: 2px solid $color-gray3;
border-radius: 5px;
box-shadow: none;
color: $color-gray4;
font-size: 12px;
height: 34px;
padding: 0 12px;
max-width: 160px;
@include mq(sm, max) {
max-width: 100%;
width: 100%;
}
}
button {
background: $color-black;
border: none;
border-radius: 5px;
color: $color-white;
font-size: 12px;
height: 36px;
letter-spacing: 1px;
margin-left: 6px;
outline: none;
transition: all 0.2s linear;
width: 94px;
text-transform: uppercase;
@include mq(md, max) {
width: 138px;
}
&:hover {
background-color: lighten($color-black, 5);
}
&:active {
background-color: darken($color-black, 5);
}
}
}
}
.accordion-group {
tr {
border-color: #e5e5e5;
td {
&.empty {
display: none;
}
&.info,
&.monetary {
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 16px;
color: $color-black;
padding: 12px 0;
}
&.info {
text-align: left;
}
&.monetary {
text-align: right;
}
}
}
tfoot {
td.info,
td.monetary {
font-style: normal;
font-weight: normal;
font-size: 18px;
line-height: 21px;
color: $color-black;
}
}
}
}
}
.cart-links-bottom {
display: flex;
flex-direction: column;
width: 343px;
@include mq(md, max) {
padding: 0 16px;
width: calc(100% - 32px);
float: none;
margin-bottom: 50px;
}
@include mq(md, min) {
margin: 0;
padding-bottom: 50px;
}
.link-choose-more-products-wrapper {
display: block;
text-align: center;
margin-bottom: 16px;
@include mq(md, max) {
margin-bottom: 0px;
}
a {
font-family: $font-family;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 14px;
color: $color-blue;
}
}
.btn-place-order-wrapper {
a {
background: $color-green;
border: none;
border-radius: 5px;
display: block;
font-size: 0;
transition: ease-in 0.22s all;
padding: 12px 19px;
&:hover {
background-color: darken($color-green, 5);
}
&:after {
content: "finalizar compra";
font-family: $font-family;
font-weight: 500;
font-size: 13px;
letter-spacing: 0.05em;
color: $color-white;
text-transform: uppercase;
vertical-align: middle;
line-height: 19px;
text-shadow: none;
}
}
}
}
}
footer {
// display: none;
}

View File

@ -0,0 +1,3 @@
body .container-main.container-order-form{
padding: 0 16px!important;
}

View File

@ -0,0 +1,38 @@
.empty-cart {
font-family: $font-family;
&-content {
color: $color-black;
text-align: center;
@include mq(md, max) {
padding: 0 16px;
}
}
&-title {
font-size: 20px;
}
&-links {
.link-choose-products {
background: $color-black;
border: none;
border-radius: 5px;
transition: ease-in 0.22s all;
outline: none;
font-family: $font-family;
font-style: normal;
font-weight: 500;
font-size: 14px;
line-height: 16px;
text-align: center;
letter-spacing: 0.05em;
color: $color-white;
text-transform: uppercase;
&:hover {
background: lighten($color-black, 5);
}
}
}
}

View File

@ -0,0 +1,122 @@
@import "./checkout-vazio";
@import "./checkout-carrinho";
@import "./checkout-pagamento";
@import "./checkout-autenticacao";
html {
height: 100%;
min-height: 100%;
}
footer {
margin-top: auto;
}
body {
display: flex;
flex-direction: column;
min-height: 100%;
padding-top: 0;
@include mq(md, max) {
padding-left: 0;
}
&.body-cart {
font-family: $font-family;
}
&.body-cart,
&.body-order-form {
@include mq(xl, min) {
padding-top: 0;
}
@include mq(lg, max) {
padding-bottom: 0 !important;
}
@include mq(md, max) {
padding-right: 0;
padding-left: 0;
}
}
.container-cart {
@include mq(xl, min) {
width: 1024px;
}
}
}
.btn-success {
background: $color-black;
text-shadow: none;
&:hover {
background: lighten($color-black, 15%);
}
}
.emailInfo h3 {
color: $color-black !important;
}
#cart-title,
#orderform-title {
color: $color-gray2;
font-family: $font-family;
font-weight: 500;
font-size: 36px;
line-height: 42px;
margin: 40px 0 30px;
letter-spacing: 0.1em;
text-transform: uppercase;
@include mq(md, max) {
margin-left: 30px;
}
}
.dropdown {
&__content {
&--closed {
display: none;
}
}
&__title {
cursor: pointer;
user-select: none;
&::before,
&::after {
content: "";
background: $color-gray2;
display: block;
float: right;
height: 2px;
width: 8px;
margin-top: 8px;
}
&::before {
transform: rotate(0deg);
transition: 0.3s;
}
&::after {
transform: rotate(90deg);
transition: 0.3s;
margin-right: -8px;
}
&.closed::before {
transform: rotate(180deg);
}
&.closed::after {
transform: rotate(0);
}
}
}

View File

@ -0,0 +1 @@
/* _breadcrumb.scss */

View File

@ -0,0 +1 @@
/* _flags.scss */

View File

@ -0,0 +1,178 @@
/* _footer.scss */
.footerCheckout {
border-top: none;
color: $color-gray2;
width: 100%;
&__wrapper {
display: flex;
flex-direction: column;
}
&__top {
align-items: flex-start;
background-color: $color-gray3;
display: flex;
justify-content: space-evenly;
padding: 24px 0;
@include mq(md, max) {
flex-direction: column;
padding: 32px 24px;
}
}
&__doubts,
&__informations {
@include mq(md, max) {
width: 100%;
}
}
&__content {
@include mq(md, max) {
margin-bottom: 32px;
}
}
&__title,
&__subtitle,
&__item,
&__link {
font-size: 12px;
margin-bottom: 12px;
}
&__title {
color: $color-gray2;
font-style: normal;
font-weight: 500;
font-size: 14px;
line-height: 16px;
@include mq(md, max) {
margin-bottom: 24px;
}
}
&__subtitle {
font-weight: 500;
}
&__link a {
color: $color-gray2;
&:hover {
color: darken($color-gray2, 10);
}
}
&__socialMedia {
display: flex;
.footerCheckout__link {
transition: all 0.2s linear;
&:not(:last-child) {
margin-right: 8px;
}
&:hover {
opacity: 0.75;
}
}
}
&__bottom {
align-items: center;
display: flex;
background-color: $color-white;
justify-content: space-between;
padding: 16px 32px;
@include mq(md, max) {
align-items: flex-start;
flex-direction: column;
padding: 16px;
}
@media (max-width: 375px) {
align-items: flex-start;
flex-direction: column;
padding: 16px;
}
&__wrapper {
display: flex;
justify-content: space-between;
max-width: 62%;
width: 100%;
@include mq(md, max) {
max-width: 100%;
flex-direction: column-reverse;
}
}
}
&__address {
color: $color-gray2;
font-family: $font-family;
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 12px;
text-transform: capitalize;
max-width: 40%;
@include mq(md, max) {
margin-bottom: 24px;
max-width: 100%;
}
}
&__stamps {
align-items: center;
display: flex;
justify-self: center;
@include mq(md, max) {
align-self: center;
margin-bottom: 12px;
}
&__divider {
background-color: $color-gray4;
display: inline-block;
height: 24px;
margin: 0 8px;
width: 1px;
}
}
&__developedBy ul {
align-items: center;
display: flex;
list-style-type: none;
margin: 0;
li:last-child {
margin-left: 16px;
}
a {
align-items: center;
color: $color-gray2;
display: flex;
font-family: $font-family;
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 12px;
text-decoration: none;
span {
margin-right: 8px;
}
}
}
}

View File

@ -0,0 +1,38 @@
/* _header.scss */
.headerCheckout {
&__wrapper {
align-items: center;
display: flex;
justify-content: space-between;
padding: 12px 0;
@include mq(md, max) {
padding: 18px 8px;
}
}
&__logo {
img {
height: 52px;
width: auto;
}
}
&__safeBuy {
span {
align-items: center;
display: flex;
text-transform: uppercase;
font-family: $font-family;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 14px;
color: $color-gray;
}
i {
margin-right: 8px;
}
}
}

View File

@ -0,0 +1 @@
/* _mais-categorias.scss */

View File

@ -0,0 +1 @@
/* _menu.scss */

View File

@ -0,0 +1 @@
/* _prateleira.scss */

View File

@ -0,0 +1,57 @@
@keyframes notificacao{
0% {
transform:rotate(0deg);
}
50% {
transform:rotate(3deg) translateX(-3px);
}
100% {
transform:rotate(-3deg) translateX(3px);
}
}
@keyframes addcart{
0% {
margin-left:0px;
}
50% {
margin-left:-2px;
}
100% {
margin-left:2px;
}
}
@keyframes spin {
from { transform:rotate(0deg); }
to { transform:rotate(360deg); }
}
@keyframes fadeIn {
from { opacity:0; }
to { opacity:1; }
}
@keyframes sk-scaleout {
0% { transform: scale(0) }
100% {
transform: scale(1.0);
opacity: 0;
}
}
@keyframes cascadeInSimple {
0% {
opacity:0;
transform: translateX(-100%)
}
100% {
opacity:1;
transform: translateX(0)
}
}

View File

@ -0,0 +1,222 @@
/**
* @reference (https://github.com/engageinteractive/core/blob/master/src/scss/utility/_mixins.scss)
*/
@mixin push--auto {
margin: {
left: auto;
right: auto;
}
}
@mixin pseudo($display: block, $pos: absolute, $content: ''){
content: $content;
display: $display;
position: $pos;
}
@mixin position($top: false,$right: false, $bottom:false, $left: false){
@if( $top ){
top:$top;
}
@if( $right ){
right:$right;
}
@if( $left ){
left:$left;
}
@if( $bottom ){
bottom:$bottom;
}
}
@mixin responsive-ratio($x,$y, $pseudo: false) {
$padding: unquote( ( $y / $x ) * 100 + '%' );
@if $pseudo {
&:before {
@include pseudo($pos: relative);
width: 100%;
padding-top: $padding;
}
} @else {
padding-top: $padding;
}
}
@mixin css-triangle($color, $direction, $size: 6px, $position: absolute, $round: false){
@include pseudo($pos: $position);
width: 0;
height: 0;
@if $round {
border-radius: 3px;
}
@if $direction == down {
border-left: $size solid transparent;
border-right: $size solid transparent;
border-top: $size solid $color;
margin-top: 0 - round( $size / 2.5 );
} @else if $direction == up {
border-left: $size solid transparent;
border-right: $size solid transparent;
border-bottom: $size solid $color;
margin-bottom: 0 - round( $size / 2.5 );
} @else if $direction == right {
border-top: $size solid transparent;
border-bottom: $size solid transparent;
border-left: $size solid $color;
margin-right: -$size;
} @else if $direction == left {
border-top: $size solid transparent;
border-bottom: $size solid transparent;
border-right: $size solid $color;
margin-left: -$size;
}
}
@mixin input-placeholder {
&.placeholder { @content; }
&:-moz-placeholder { @content; }
&::-moz-placeholder { @content; }
&:-ms-input-placeholder { @content; }
&::-webkit-input-placeholder { @content; }
}
@mixin hardware($backface: true, $perspective: 1000) {
@if $backface {
backface-visibility: hidden;
}
perspective: $perspective;
}
@mixin truncate($truncation-boundary) {
max-width: $truncation-boundary;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
@mixin appearance($val: none) {
-webkit-appearance: $val;
-moz-appearance: $val;
appearance: $val;
}
@mixin separador($cor,$p-right: 5px) {
position: relative;
padding-right: $p-right;
display: inline-block;
&:after{
content:' ';
display: block;
width: 1px;
height: 100%;
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%);
background-color: $cor;
}
&:last-child:after{
display: none;
}
}
@mixin mq($width, $type: min) {
@if map_has_key($grid-breakpoints, $width) {
$width: map_get($grid-breakpoints, $width);
@if $type == max {
$width: $width - 1px;
}
@media only screen and (#{$type}-width: $width) {
@content;
}
}
}
@mixin mq_range($min, $max) {
@if (map_has_key($grid-breakpoints, $min) and map_has_key($grid-breakpoints, $max)) {
$width_max: map_get($grid-breakpoints, $max);
$width_min: map_get($grid-breakpoints, $min);
$width_max: $width_max - 1px;
@media only screen and (min-width: $width_min) and (max-width:$width_max) {
@content;
}
}
}
@mixin z-index($nome:'',$soma:0){
@if map_has_key($z-index, $nome) {
z-index: (map_get($z-index,$nome )+$soma) ;
}
}
@mixin scrollbar($width:8px,$bg-color:#eee, $trak-color:#aaa,$trak-color-hover:#999,$border-radius:0 ){
&::-webkit-scrollbar {
width: $width;
}
&::-webkit-scrollbar-track {
background-color: $bg-color;
border-radius: $border-radius;
}
&::-webkit-scrollbar-thumb {
background-color: $trak-color;
border-radius: $border-radius;
&:hover {
background: $trak-color-hover;
}
}
}
@function map-get-next($map, $key, $fallback: false, $return: value) {
// Check if map is valid
@if type-of($map) == map {
// Check if key exists in map
@if map-has-key($map, $key) {
// Init index counter variable
$i: 0;
// Init key index
$key-index: false;
// Traverse map for key
@each $map-key, $map-value in $map {
// Update index
$i: $i + 1;
// If map key found, set key index
@if $map-key == $key {
$key-index: $i;
}
// If next index return next value or key based on $return
@if $i == $key-index + 1 {
@if $return == key {
@return $map-key;
} @else {
@return $map-value;
}
}
// If last entry return false
@if $i == length($map) {
@return $fallback;
}
}
@warn 'No next map item for key #{$key}';
@return $fallback;
}
@warn 'No valid key #{$key} in map';
@return $fallback;
}
@warn 'No valid map';
@return $fallback;
}

View File

@ -0,0 +1,91 @@
// Mixins de definição
@mixin visibility($parent, $display:block) {
@if $display==none {
$display: block;
}
#{$parent} {
display: $display !important;
}
}
@mixin visibility-table($parent) {
table#{$parent} {
display: table !important;
}
tr#{$parent} {
display: table-row !important;
}
th#{$parent},
td#{$parent} {
display: table-cell !important;
}
}
// [converter] $parent hack
@mixin invisibility($parent) {
#{$parent} {
display: none !important;
}
}
@each $slug,$width in $grid-breakpoints {
$class: unquote('.visible-'+$slug);
$classOnly: unquote('.visible-only-'+$slug);
@include invisibility($class);
@include invisibility($classOnly);
}
@each $slug,$width in $grid-breakpoints {
$class: unquote('.visible-'+$slug);
$value: map-get-next($grid-breakpoints,$slug);
$media: '(max-width: '+ (($value)-1) +')';
@if($value == false){
$media: '(min-width: '+ $width +')';
}
@media only screen and #{$media} {
@include visibility($class);
@include visibility($class+'-inline-block',inline-block);
@include visibility($class+'-inline',inline);
@include visibility-table($class);
}
}
@each $slug,$width in $grid-breakpoints {
$class: unquote('.visible-only-'+$slug);
$value: map-get-next($grid-breakpoints,$slug);
$media: '(min-width: '+ $width +') and (max-width: '+ $value +')';
@if($value == false){
$media: '(min-width: '+ (($width)+1) +')';
}
@media only screen and #{$media} {
@include visibility($class);
@include visibility($class+'-inline-block',inline-block);
@include visibility($class+'-inline',inline);
@include visibility-table($class);
}
}
@each $slug,$width in $grid-breakpoints {
$class: unquote('.invisible-'+$slug);
$value: map-get-next($grid-breakpoints,$slug);
$media: '(max-width: '+ (($value)-1) +')';
@if($value == false){
$media: '(min-width: '+ $width +')';
}
@media only screen and #{$media} {
@include invisibility($class);
}
}
@each $slug,$width in $grid-breakpoints {
$class: unquote('.invisible-only-'+$slug);
$value: map-get-next($grid-breakpoints,$slug);
$media: '(min-width: '+ $width +') and (max-width: '+ $value +')';
@if($value == false){
$media: '(min-width: '+$width +')';
}
@media only screen and #{$media} {
@include invisibility($class);
}
}

View File

@ -0,0 +1,36 @@
/* fonts */
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap");
$font-family: "Roboto", sans-serif;
/* Colors */
$color-black: #292929;
$color-white: #fff;
$color-gray: #6c6c6c;
$color-gray2: #7d7d7d;
$color-gray3: #f0f0f0;
$color-gray4: #8d8d8d;
$color-gray5: #e5e5e5;
$color-blue: #4267b2;
$color-green: #4caf50;
/* Grid breakpoints */
$grid-breakpoints: (
xs: 0,
cstm: 400,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
$z-index: (
level1: 5,
level2: 10,
level3: 15,
level4: 20,
level5: 25
) !default;

View File

@ -0,0 +1,5 @@
@import "variaveis";
@import "mixin";
@import "utils";
@import "animacao";

View File

@ -0,0 +1,49 @@
.sprite{
display: inline-block;
vertical-align: middle;
}
.no-buttom {
border: none;
margin: 0;
padding: 0;
width: auto;
overflow: visible;
background: transparent;
outline: none;
text-align: inherit;
/* inherit font & color from ancestor */
color: inherit;
font: inherit;
/* Normalize `line-height`. Cannot be changed from `normal` in Firefox 4+. */
line-height: normal;
/* Corrects font smoothing for webkit */
-webkit-font-smoothing: inherit;
-moz-osx-font-smoothing: inherit;
/* Corrects inability to style clickable `input` types in iOS */
appearance: none;
&::-moz-focus-inner {
border: 0;
padding: 0;
}
}
.itens-inline{
>*{ display: inline-block;}
}
%notificacao{
padding: 7.5px 10px ;
min-height: 1em;
border-radius: 3px;
border-right: solid 5px;
display: block;
}

View File

@ -0,0 +1,116 @@
<footer>
<div class="footerCheckout">
<div class="footerCheckout__top">
<div class="footerCheckout__doubts">
<div class="footerCheckout__title">
Dúvidas
</div>
<div class="footerCheckout__content">
<div class="footerCheckout__link">
<a href="/sobre">Sobre</a>
</div>
<div class="footerCheckout__link">
<a href="/pagamento">Formas de Pagamento</a>
</div>
<div class="footerCheckout__link">
<a href="/entrega">Entrega</a>
</div>
<div class="footerCheckout__link">
<a href="/troca-e-devolucao">Trocas e Devoluções</a>
</div>
<div class="footerCheckout__link">
<a href="/privacidade">Segurança e Privacidade</a>
</div>
</div>
</div>
<div class="footerCheckout__informations">
<div class="footerCheckout__title">
Fale Conosco
</div>
<div class="footerCheckout__content">
<div class="footerCheckout__link">
<a href="mailto:sac@sualoja.com.br">sac@sualoja.com.br</a>
</div>
<div class="footerCheckout__item">
Sac: (00) 0000-0000
</div>
<div class="footerCheckout__subtitle">
Funcionamento:
</div>
<div class="footerCheckout__item">
Segunda à Sexta - 08h às 18h.
</div>
</div>
</div>
<div class="footerCheckout__socialMedia">
<div class="footerCheckout__link">
<a href="https://www.facebook.com/digitalm3">
@TODO: fb icon
</a>
</div>
<div class="footerCheckout__link">
<a href="https://www.instagram.com/agenciam3/">
@TODO: instagram ico
</a>
</div>
<div class="footerCheckout__link">
<a href="https://twitter.com/twitter">
@TODO: twitter icon
</a>
</div>
<div class="footerCheckout__link">
<a href="https://www.youtube.com/">
@TODO: youtube icon
</a>
</div>
</div>
</div>
<div class="footerCheckout__bottom">
<div class="footerCheckout__bottom__wrapper">
<div class="footerCheckout__address">
<span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
</div>
<div class="footerCheckout__stamps">
@TODO: creditcard icons
<span class="footerCheckout__stamps__divider"></span>
@TODO: vtex pci icon
</div>
</div>
<div class="footerCheckout__developedBy">
<ul>
<li>
<a href="https://vtex.com/br-pt/">
<span>Powered By</span>
@TODO: vtex icon
</a>
</li>
<li>
<a href="https://agenciam3.com/">
<span>Developed By</span>
@TODO: m3 icon
</a>
</li>
</ul>
</div>
</div>
</div>
</footer>

View File

@ -0,0 +1,15 @@
<header class="headerCheckout">
<div class="container">
<div class="headerCheckout__wrapper" >
<div class="headerCheckout__logo">
<a href="/">
<img src="/arquivos/logo-checkout.png" alt="agenciam3"/>
</a>
</div>
<div class="headerCheckout__safeBuy">
<span><Compra segura</span>
</div>
</div>
</div>
</header>

View File

@ -0,0 +1,30 @@
const webpack = require("webpack");
const path = require("path");
var shopName = require("../package.json").name;
/**
* Configuração do webpack
*/
module.exports = {
entry: {
checkout: "./src/arquivos/js/checkout.js",
},
output: {
path: path.resolve(__dirname, "./dist/arquivos"),
filename: shopName + "--[name]-bundle.js",
},
resolve: {
alias: {
Helpers: path.resolve(__dirname, "..", "src/arquivos/js/helpers"),
Lib: path.resolve(__dirname, "..", "src/arquivos/js/lib"),
Config: path.resolve(__dirname, "..", "src/arquivos/js/config"),
App: path.resolve(__dirname, "..", "src/arquivos/js/app"),
},
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
}),
],
};

30
checkout/webpack.dev.js Normal file
View File

@ -0,0 +1,30 @@
const webpack = require("webpack");
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
const path = require("path");
module.exports = merge(common, {
devtool: "inline-source-map",
mode: "development",
externals: {
vtexjs: "vtexjs",
jquery: "jQuery",
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
include: path.resolve(__dirname, "..", "src/arquivos/js"),
use: {
loader: "babel-loader",
options: {
presets: [["@babel/preset-env"], "@babel/react"],
plugins: ["@babel/plugin-transform-async-to-generator"],
cacheDirectory: true,
},
},
},
],
},
});

47
checkout/webpack.prod.js Normal file
View File

@ -0,0 +1,47 @@
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
const TerserPlugin = require("terser-webpack-plugin");
module.exports = merge(common, {
externals: {
jquery: "jQuery",
vtexjs: "vtexjs",
},
mode: "production",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules\/(?!(@agenciam3\/pkg)\/).*/,
use: {
loader: "babel-loader",
options: {
presets: [["@babel/preset-env"], "@babel/react"],
plugins: ["@babel/plugin-transform-async-to-generator"],
cacheDirectory: true,
},
},
},
],
},
optimization: {
usedExports: true,
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: true,
terserOptions: {
keep_classnames: true,
keep_fnames: true,
compress: {
pure_funcs: [
"console.table",
"console.debug",
"console.log",
],
},
},
}),
],
},
});

4
commitlint.config.js Normal file
View File

@ -0,0 +1,4 @@
module.exports = {
extends: ["@commitlint/config-conventional"],
ignores: [(message) => message.includes("Release")],
};

3
custom/.eslintignore Normal file
View File

@ -0,0 +1,3 @@
node_modules/
coverage/
*.snap.ts

35
custom/.eslintrc.js Normal file
View File

@ -0,0 +1,35 @@
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
],
settings: {
react: {
pragma: "React",
version: "detect",
},
},
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
sourceType: "module",
},
plugins: ["react", "@typescript-eslint"],
rules: {
indent: ["error", 4],
"linebreak-style": ["error", "unix"],
quotes: ["error", "double"],
semi: ["error", "always"],
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
},
};

6
custom/.vtexignore Normal file
View File

@ -0,0 +1,6 @@
react/**/__tests__/**
react/**/__mocks__/**
react/**/__snapshots__/**
react/**/*.test.js
react/**/*.test.ts
react/**/*.test.tsx

0
custom/CHANGELOG.md Normal file
View File

9
custom/README.md Normal file
View File

@ -0,0 +1,9 @@
# M3 Custom Template
**Esse projeto possui a pasta <span style="color:red;">node</span>, delete ela para componentes simples.**
## Uso no store fronte
Documentar aqui um exemplo de implementação

22
custom/manifest.json Normal file
View File

@ -0,0 +1,22 @@
{
"vendor": "agenciamagma",
"name": "m3-custom",
"version": "0.1.6",
"title": "m3-custom",
"description": "m3-custom component",
"defaultLocale": "pt-BR",
"builders": {
"messages": "1.x",
"store": "0.x",
"react": "3.x"
},
"dependencies": {
"vtex.styleguide": "9.x",
"vtex.css-handles": "0.x",
"vtex.native-types": "0.x",
"vtex.store-graphql": "2.x",
"vtex.search-graphql": "0.x",
"vtex.checkout-graphql": "0.x"
},
"$schema": "https://raw.githubusercontent.com/vtex/node-vtex-api/master/gen/manifest.schema"
}

View File

@ -0,0 +1,4 @@
{
"editor.countdown.title": "Countdown",
"editor.countdown.description": "Countdown component"
}

4
custom/messages/en.json Normal file
View File

@ -0,0 +1,4 @@
{
"editor.countdown.title": "Countdown",
"editor.countdown.description": "Countdown component"
}

4
custom/messages/es.json Normal file
View File

@ -0,0 +1,4 @@
{
"editor.countdown.title": "Cuenta regresiva",
"editor.countdown.description": "Cuenta regresiva component"
}

4
custom/messages/pt.json Normal file
View File

@ -0,0 +1,4 @@
{
"editor.countdown.title": "Contagem regressiva",
"editor.countdown.description": "Componente de contagem regressiva"
}

27
custom/package.json Normal file
View File

@ -0,0 +1,27 @@
{
"name": "custom",
"license": "UNLICENSED",
"version": "1.0.0",
"scripts": {
"lint": "eslint --ext js,jsx,ts,tsx . --fix",
"format": "prettier --write \"**/*.{ts,js,json}\"",
"install:all": "concurrently \"cd react && yarn install\""
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0",
"@vtex/prettier-config": "0.1.4",
"eslint": "7.12.1",
"eslint-config-vtex": "12.3.2",
"eslint-config-vtex-react": "^6.2.1",
"eslint-plugin-react": "^7.23.1",
"husky": "^5.2.0",
"lint-staged": "10.1.1",
"prettier": "2.0.2",
"typescript": "3.8.3"
},
"dependencies": {
"husky": "^5.2.0",
"react": "^17.0.2"
}
}

View File

@ -0,0 +1,6 @@
{
"semi": true,
"singleQuote": false,
"tabWidth": 4,
"useTabs": false
}

3
custom/react/B2bForm.tsx Normal file
View File

@ -0,0 +1,3 @@
import { B2bForm } from "./components/B2bForm/B2bForm";
export default B2bForm;

View File

@ -0,0 +1,3 @@
import { DynamicMenu } from "./components/Menu/DynamicMenu";
export default DynamicMenu;

3
custom/react/Exemple.tsx Normal file
View File

@ -0,0 +1,3 @@
import { Exemple } from "./components/Exemple/Exemple";
export default Exemple;

View File

@ -0,0 +1,32 @@
import ResponsiveRender from "./components/UI/ResponsiveRender/ResponsiveRender";
export default ResponsiveRender;
/*
props: {
type: "min" | "max", "range"
width: "phone" | "tablet" | "desktop" | number(in pixels)
},
children: []
--- Storefront Exemples ---
"m3-responsive-render#titulo-desktop": {
"props": {
"type": "min",
"width": "desktop"
},
"children":["rich-text#titulo"]
}
- Range -
"m3-responsive-render#titulo-desktop": {
"props": {
"type": "range",
"width": "tablet, desktop"
},
"children":["rich-text#titulo-tablet"]
}
*/

View File

@ -0,0 +1,6 @@
.container {
margin: 0 auto;
max-width: 900px;
padding: 16px;
}

View File

@ -0,0 +1,83 @@
import React, { useState } from "react";
import { Formik, FormikHelpers } from "formik";
import styles from "./B2bForm.css";
import { registerSchema } from "./B2bFormRegisterSchema";
import saveData from "./B2bFormSaveData";
import FormStep from "./steps/FormStep";
import SuccessStep from "./steps/SuccessStep";
import ErrorStep from "./steps/ErrorStep";
export interface FormFields {
corporateDocument: string;
document: string;
postalCode: string;
street: string;
complement: string;
number: string;
neighborhood: string;
city: string;
state: string;
corporateName: string;
stateRegistration: string;
tradeName: string;
businessPhone: string;
phone: string;
firstName: string;
lastName: string;
email: string;
}
const initialValues: FormFields = {
corporateDocument: "",
document: "",
postalCode: "",
street: "",
complement: "",
number: "",
neighborhood: "",
city: "",
state: "",
corporateName: "",
stateRegistration: "",
tradeName: "",
businessPhone: "",
phone: "",
firstName: "",
lastName: "",
email: "",
};
export const B2bForm: StorefrontFunctionComponent = () => {
const [step, setStep] = useState<"form" | "success" | "error">("form");
const onSubmit = async (values: FormFields, { setSubmitting }: FormikHelpers<FormFields>) => {
try {
await saveData(values);
setSubmitting(false);
setStep("success");
} catch (error) {
setSubmitting(false);
setStep("error");
}
};
return (
<div className={styles.container}>
<Formik
initialValues={initialValues}
validationSchema={registerSchema}
onSubmit={onSubmit}
>
{() => (
<>
{step === "form" && (<FormStep></FormStep>)}
{step === "success" && (<SuccessStep></SuccessStep>)}
{step === "error" && (<ErrorStep></ErrorStep>)}
</>
)}
</Formik>
</div >
);
};

Some files were not shown because too many files have changed in this diff Show More