diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..f3dbc7f7 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +node_modules/ +coverage/ +*.snap.ts \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..9713dfdd --- /dev/null +++ b/.eslintrc @@ -0,0 +1,7 @@ +{ + "extends": "vtex", + "root": true, + "env": { + "node": true + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..9aa6e7fe --- /dev/null +++ b/.gitignore @@ -0,0 +1,87 @@ +*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 ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.vscode/ + +# 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 + +styles/css/*.css + +styles/css +**/*.sass-cache/ +**/*.css.map +styles/css/*.css +styles/css/vtex.flex-layout.css + +styles/css/vtex.flex-layout.css diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..320bc0c1 --- /dev/null +++ b/.prettierrc @@ -0,0 +1 @@ +"@vtex/prettier-config" \ No newline at end of file diff --git a/assets/fonts/MonumentExtended-Regular.otf b/assets/fonts/MonumentExtended-Regular.otf new file mode 100644 index 00000000..0673962f Binary files /dev/null and b/assets/fonts/MonumentExtended-Regular.otf differ diff --git a/assets/fonts/MonumentExtended-Ultrabold.otf b/assets/fonts/MonumentExtended-Ultrabold.otf new file mode 100644 index 00000000..fd41187a Binary files /dev/null and b/assets/fonts/MonumentExtended-Ultrabold.otf differ diff --git a/assets/fonts/NeoSansPro-Regular.otf b/assets/fonts/NeoSansPro-Regular.otf new file mode 100644 index 00000000..c1c338ac Binary files /dev/null and b/assets/fonts/NeoSansPro-Regular.otf differ diff --git a/assets/fonts/NeoSansStd-Regular.ttf b/assets/fonts/NeoSansStd-Regular.ttf new file mode 100644 index 00000000..a2485248 Binary files /dev/null and b/assets/fonts/NeoSansStd-Regular.ttf differ diff --git a/assets/fonts/Oxygen-Regular.ttf b/assets/fonts/Oxygen-Regular.ttf new file mode 100644 index 00000000..416f8e64 Binary files /dev/null and b/assets/fonts/Oxygen-Regular.ttf differ diff --git a/assets/fonts/Roboto-Regular.ttf b/assets/fonts/Roboto-Regular.ttf new file mode 100644 index 00000000..2b6392ff Binary files /dev/null and b/assets/fonts/Roboto-Regular.ttf differ diff --git a/assets/fonts/neo-sans-std-medium.OTF b/assets/fonts/neo-sans-std-medium.OTF new file mode 100644 index 00000000..2f528df2 Binary files /dev/null and b/assets/fonts/neo-sans-std-medium.OTF differ diff --git a/assets/fonts/neo-sans-std.otf b/assets/fonts/neo-sans-std.otf new file mode 100644 index 00000000..496752f6 Binary files /dev/null and b/assets/fonts/neo-sans-std.otf differ diff --git a/assets/imgs/main-banner-home-mobile.png b/assets/imgs/main-banner-home-mobile.png new file mode 100644 index 00000000..333c8b42 Binary files /dev/null and b/assets/imgs/main-banner-home-mobile.png differ diff --git a/assets/imgs/main-banner-home.png b/assets/imgs/main-banner-home.png new file mode 100644 index 00000000..d308722a Binary files /dev/null and b/assets/imgs/main-banner-home.png differ diff --git a/assets/svgs/american-express-icon.svg b/assets/svgs/american-express-icon.svg new file mode 100644 index 00000000..a8eb12f6 --- /dev/null +++ b/assets/svgs/american-express-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/svgs/arrow-down.svg b/assets/svgs/arrow-down.svg new file mode 100644 index 00000000..f4155bb8 --- /dev/null +++ b/assets/svgs/arrow-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svgs/boleto-icon.svg b/assets/svgs/boleto-icon.svg new file mode 100644 index 00000000..563caf41 --- /dev/null +++ b/assets/svgs/boleto-icon.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/boss-button.svg b/assets/svgs/boss-button.svg new file mode 100644 index 00000000..68b0aa68 --- /dev/null +++ b/assets/svgs/boss-button.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/svgs/discount.svg b/assets/svgs/discount.svg new file mode 100644 index 00000000..4d79d1e8 --- /dev/null +++ b/assets/svgs/discount.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/svgs/elo-icon.svg b/assets/svgs/elo-icon.svg new file mode 100644 index 00000000..b4bf0edc --- /dev/null +++ b/assets/svgs/elo-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/svgs/empty-cart.svg b/assets/svgs/empty-cart.svg new file mode 100644 index 00000000..8c9a4ca0 --- /dev/null +++ b/assets/svgs/empty-cart.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svgs/facebook-footer-icon.svg b/assets/svgs/facebook-footer-icon.svg new file mode 100644 index 00000000..c3fdf34b --- /dev/null +++ b/assets/svgs/facebook-footer-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svgs/garantia.svg b/assets/svgs/garantia.svg new file mode 100644 index 00000000..4dca2173 --- /dev/null +++ b/assets/svgs/garantia.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/instagram-footer-icon.svg b/assets/svgs/instagram-footer-icon.svg new file mode 100644 index 00000000..94b2c455 --- /dev/null +++ b/assets/svgs/instagram-footer-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svgs/login-icon.svg b/assets/svgs/login-icon.svg new file mode 100644 index 00000000..fc0b5fad --- /dev/null +++ b/assets/svgs/login-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/svgs/logo-b8.svg b/assets/svgs/logo-b8.svg new file mode 100644 index 00000000..fd94f955 --- /dev/null +++ b/assets/svgs/logo-b8.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svgs/logo-vtex-light.svg b/assets/svgs/logo-vtex-light.svg new file mode 100644 index 00000000..f555e1a8 --- /dev/null +++ b/assets/svgs/logo-vtex-light.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/svgs/mastercard-icon.svg b/assets/svgs/mastercard-icon.svg new file mode 100644 index 00000000..1ee68f5a --- /dev/null +++ b/assets/svgs/mastercard-icon.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/assets/svgs/minicart-icon.svg b/assets/svgs/minicart-icon.svg new file mode 100644 index 00000000..bc5d3271 --- /dev/null +++ b/assets/svgs/minicart-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svgs/new-cart-icon.svg b/assets/svgs/new-cart-icon.svg new file mode 100644 index 00000000..a53c19f3 --- /dev/null +++ b/assets/svgs/new-cart-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svgs/paga-leve-icon.svg b/assets/svgs/paga-leve-icon.svg new file mode 100644 index 00000000..e7aca4e2 --- /dev/null +++ b/assets/svgs/paga-leve-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/svgs/piano.svg b/assets/svgs/piano.svg new file mode 100644 index 00000000..9aa9702f --- /dev/null +++ b/assets/svgs/piano.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svgs/pix-icon.svg b/assets/svgs/pix-icon.svg new file mode 100644 index 00000000..d2b7479f --- /dev/null +++ b/assets/svgs/pix-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/svgs/price-tag.svg b/assets/svgs/price-tag.svg new file mode 100644 index 00000000..b7283bf8 --- /dev/null +++ b/assets/svgs/price-tag.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/svgs/quality.svg b/assets/svgs/quality.svg new file mode 100644 index 00000000..0e673a45 --- /dev/null +++ b/assets/svgs/quality.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svgs/roland-button.svg b/assets/svgs/roland-button.svg new file mode 100644 index 00000000..de356c6c --- /dev/null +++ b/assets/svgs/roland-button.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svgs/roland-inactive.svg b/assets/svgs/roland-inactive.svg new file mode 100644 index 00000000..7a7ac459 --- /dev/null +++ b/assets/svgs/roland-inactive.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svgs/roland-logo.svg b/assets/svgs/roland-logo.svg new file mode 100644 index 00000000..1b816adc --- /dev/null +++ b/assets/svgs/roland-logo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/svgs/seal-icon.svg b/assets/svgs/seal-icon.svg new file mode 100644 index 00000000..128a4749 --- /dev/null +++ b/assets/svgs/seal-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/svgs/search-icon.svg b/assets/svgs/search-icon.svg new file mode 100644 index 00000000..098b74e6 --- /dev/null +++ b/assets/svgs/search-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svgs/shipping.svg b/assets/svgs/shipping.svg new file mode 100644 index 00000000..1562f866 --- /dev/null +++ b/assets/svgs/shipping.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/svgs/success-icon-newsletter.svg b/assets/svgs/success-icon-newsletter.svg new file mode 100644 index 00000000..090ba9e2 --- /dev/null +++ b/assets/svgs/success-icon-newsletter.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/svgs/truck.svg b/assets/svgs/truck.svg new file mode 100644 index 00000000..7847d21e --- /dev/null +++ b/assets/svgs/truck.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/svgs/visa-icon.svg b/assets/svgs/visa-icon.svg new file mode 100644 index 00000000..177f5bd3 --- /dev/null +++ b/assets/svgs/visa-icon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/svgs/wishlist-icon.svg b/assets/svgs/wishlist-icon.svg new file mode 100644 index 00000000..f210b306 --- /dev/null +++ b/assets/svgs/wishlist-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svgs/youtube-footer-icon.svg b/assets/svgs/youtube-footer-icon.svg new file mode 100644 index 00000000..2f2ae8cf --- /dev/null +++ b/assets/svgs/youtube-footer-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/checkout-ui-settings/.editorconfig b/checkout-ui-settings/.editorconfig new file mode 100644 index 00000000..458bc5a6 --- /dev/null +++ b/checkout-ui-settings/.editorconfig @@ -0,0 +1,13 @@ +# editorconfig.org +root = true + +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +charset = utf-8 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/checkout-ui-settings/.eslintignore b/checkout-ui-settings/.eslintignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/checkout-ui-settings/.eslintignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/checkout-ui-settings/.eslintrc b/checkout-ui-settings/.eslintrc new file mode 100644 index 00000000..4e8cf65a --- /dev/null +++ b/checkout-ui-settings/.eslintrc @@ -0,0 +1,30 @@ +{ + "extends": "vtex", + "root": true, + "env": { + "node": true, + "es6": true, + "jest": true + }, + "globals": { + "metrics": true + }, + "rules": { + "no-console": "off", + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/explicit-member-accessibility": "off", + "@typescript-eslint/camelcase": ["warn", { "properties": "never" }], + "require-atomic-updates": "off" + }, + "overrides": [ + { + "files": ["node/build/react/**/*"], + "globals": { + "window": true, + "__RUNTIME__": true + } + } + ] +} diff --git a/checkout-ui-settings/.gitignore b/checkout-ui-settings/.gitignore new file mode 100644 index 00000000..8d2e82af --- /dev/null +++ b/checkout-ui-settings/.gitignore @@ -0,0 +1,56 @@ +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# 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 + +# 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 + +# webpack +.happypack/ +webpack_cache/ + +# Optional REPL history +.node_repl_history + +# Generate directory +render_build +accounts + +.vscode + +lib + +entrypoints.json +jsconfig.json +.DS_Store + +# Typescript builds +dist diff --git a/checkout-ui-settings/.prettierignore b/checkout-ui-settings/.prettierignore new file mode 100644 index 00000000..254b102c --- /dev/null +++ b/checkout-ui-settings/.prettierignore @@ -0,0 +1,2 @@ +CHANGELOG.md +node/__mocks__/fixtures/** \ No newline at end of file diff --git a/checkout-ui-settings/.prettierrc b/checkout-ui-settings/.prettierrc new file mode 100644 index 00000000..6aca66fa --- /dev/null +++ b/checkout-ui-settings/.prettierrc @@ -0,0 +1,6 @@ +{ + "semi": false, + "singleQuote": true, + "trailingComma": "es5", + "printWidth": 120 +} diff --git a/checkout-ui-settings/.vtexignore b/checkout-ui-settings/.vtexignore new file mode 100644 index 00000000..04834def --- /dev/null +++ b/checkout-ui-settings/.vtexignore @@ -0,0 +1,13 @@ +.DS_Store +.git/ +.happypack/ +.vscode/ +node_modules/ +service/node_modules/ +render_build/ +src/ +.editorconfig +.eslintrc +.gitignore +gulpfile.js +tsconfig.json diff --git a/checkout-ui-settings/CHANGELOG.md b/checkout-ui-settings/CHANGELOG.md new file mode 100644 index 00000000..ffcc3264 --- /dev/null +++ b/checkout-ui-settings/CHANGELOG.md @@ -0,0 +1,24 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.1.0] - 2020-04-29 +### Added +- `checkout-instore-custom.css` and `checkout-instore-custom.js` to template. + +## [0.0.3] - 2020-04-01 +### Fixed +- Folder name in `README.md` from `checkout-custom` to `checkout-ui-custom`. + +## [0.0.2] - 2020-03-23 + +### Changed +- Use default settings for template. + +### Added +- Initial version of the project created. diff --git a/checkout-ui-settings/checkout-ui-custom/checkout-confirmation-custom.css b/checkout-ui-settings/checkout-ui-custom/checkout-confirmation-custom.css new file mode 100644 index 00000000..d7008c8f --- /dev/null +++ b/checkout-ui-settings/checkout-ui-custom/checkout-confirmation-custom.css @@ -0,0 +1 @@ +/* /files/checkout-confirmation-custom.css */ diff --git a/checkout-ui-settings/checkout-ui-custom/checkout-confirmation-custom.js b/checkout-ui-settings/checkout-ui-custom/checkout-confirmation-custom.js new file mode 100644 index 00000000..425a0e2d --- /dev/null +++ b/checkout-ui-settings/checkout-ui-custom/checkout-confirmation-custom.js @@ -0,0 +1,2 @@ +// WARNING: THE USAGE OF CUSTOM SCRIPTS IS NOT SUPPORTED. VTEX IS NOT LIABLE FOR ANY DAMAGES THIS MAY CAUSE. +// THIS MAY BREAK YOUR STORE AND STOP SALES. IN CASE OF ERRORS, PLEASE DELETE THE CONTENT OF THIS SCRIPT. diff --git a/checkout-ui-settings/checkout-ui-custom/checkout-instore-custom.css b/checkout-ui-settings/checkout-ui-custom/checkout-instore-custom.css new file mode 100644 index 00000000..e089acdf --- /dev/null +++ b/checkout-ui-settings/checkout-ui-custom/checkout-instore-custom.css @@ -0,0 +1 @@ +/* /files/checkout-instore-custom.css */ diff --git a/checkout-ui-settings/checkout-ui-custom/checkout-instore-custom.js b/checkout-ui-settings/checkout-ui-custom/checkout-instore-custom.js new file mode 100644 index 00000000..614f3968 --- /dev/null +++ b/checkout-ui-settings/checkout-ui-custom/checkout-instore-custom.js @@ -0,0 +1 @@ +/* /files/checkout-instore-custom.js */ diff --git a/checkout-ui-settings/checkout-ui-custom/checkout5-custom.css b/checkout-ui-settings/checkout-ui-custom/checkout5-custom.css new file mode 100644 index 00000000..a3f88f82 --- /dev/null +++ b/checkout-ui-settings/checkout-ui-custom/checkout5-custom.css @@ -0,0 +1,7 @@ +/* /files/checkout5-custom.css */ + +/* Displays the option to enter a foreign document */ +.document-box { display: block; } + +/* Displays the option to enter an international phone */ +.phone-box { display: block; } diff --git a/checkout-ui-settings/checkout-ui-custom/checkout5-custom.js b/checkout-ui-settings/checkout-ui-custom/checkout5-custom.js new file mode 100644 index 00000000..907a76ae --- /dev/null +++ b/checkout-ui-settings/checkout-ui-custom/checkout5-custom.js @@ -0,0 +1 @@ +// WARNING: THE USAGE OF CUSTOM SCRIPTS IS NOT SUPPORTED. VTEX IS NOT LIABLE FOR ANY DAMAGES THIS MAY CAUSE. THIS MAY BREAK YOUR STORE AND STOP SALES. IN CASE OF ERRORS, PLEASE DELETE THE CONTENT OF THIS SCRIPT. diff --git a/checkout-ui-settings/checkout-ui-custom/checkout6-custom.css b/checkout-ui-settings/checkout-ui-custom/checkout6-custom.css new file mode 100644 index 00000000..38d8f6dd --- /dev/null +++ b/checkout-ui-settings/checkout-ui-custom/checkout6-custom.css @@ -0,0 +1,4488 @@ +@import url(https://p.typekit.net/p.css?s=1&k=jla5wuv&ht=tk&f=139.140.175.176&a=16702154&app=typekit&e=css); + +@font-face { + font-family: "Proxima Nova"; + src: url("https://use.typekit.net/af/2555e1/00000000000000007735e603/30/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3") format("woff2"), url("https://use.typekit.net/af/2555e1/00000000000000007735e603/30/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3") format("woff"), url("https://use.typekit.net/af/2555e1/00000000000000007735e603/30/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3") format("opentype"); + font-display: auto; + font-style: normal; + font-weight: 700; + font-stretch: normal +} + +@font-face { + font-family: "Proxima Nova"; + src: url("https://use.typekit.net/af/4de20a/00000000000000007735e604/30/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=i7&v=3") format("woff2"), url("https://use.typekit.net/af/4de20a/00000000000000007735e604/30/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=i7&v=3") format("woff"), url("https://use.typekit.net/af/4de20a/00000000000000007735e604/30/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=i7&v=3") format("opentype"); + font-display: auto; + font-style: italic; + font-weight: 700; + font-stretch: normal +} + +@font-face { + font-family: "Proxima Nova"; + src: url("https://use.typekit.net/af/efe4a5/00000000000000007735e609/30/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3") format("woff2"), url("https://use.typekit.net/af/efe4a5/00000000000000007735e609/30/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3") format("woff"), url("https://use.typekit.net/af/efe4a5/00000000000000007735e609/30/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3") format("opentype"); + font-display: auto; + font-style: normal; + font-weight: 400; + font-stretch: normal +} + +@font-face { + font-family: "Proxima Nova"; + src: url("https://use.typekit.net/af/3322cc/00000000000000007735e616/30/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=i4&v=3") format("woff2"), url("https://use.typekit.net/af/3322cc/00000000000000007735e616/30/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=i4&v=3") format("woff"), url("https://use.typekit.net/af/3322cc/00000000000000007735e616/30/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=i4&v=3") format("opentype"); + font-display: auto; + font-style: italic; + font-weight: 400; + font-stretch: normal +} + +.vcustom--vtex-omnishipping-1-x-address input, +#app-container input[type=text], +#app-container input[type=tel], +#app-container input[type=email], +#app-container select, +.orderform-template .summary-note .note-textarea, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-addressFormPart1.vtex-omnishipping-1-x-geolocation input, +.orderform-template-holder #client-profile-data form.client-pre-email input[type=text]:not(.pac-target-input), +.orderform-template-holder #client-profile-data form.client-pre-email input[type=tel]:not(.pac-target-input), +.orderform-template-holder #client-profile-data form.client-pre-email input[type=email]:not(.pac-target-input), +.orderform-template-holder #client-profile-data form.client-pre-email select:not(.pac-target-input), +.orderform-template-holder #client-profile-data .step.client-profile-data input[type=text]:not(.pac-target-input), +.orderform-template-holder #client-profile-data .step.client-profile-data input[type=tel]:not(.pac-target-input), +.orderform-template-holder #client-profile-data .step.client-profile-data input[type=email]:not(.pac-target-input), +.orderform-template-holder #client-profile-data .step.client-profile-data select:not(.pac-target-input), +.orderform-template-holder #shipping-data input[type=text]:not(.pac-target-input), +.orderform-template-holder #shipping-data input[type=tel]:not(.pac-target-input), +.orderform-template-holder #shipping-data input[type=email]:not(.pac-target-input), +.orderform-template-holder #shipping-data select:not(.pac-target-input), +.orderform-template-holder #payment-data input[type=text]:not(.pac-target-input), +.orderform-template-holder #payment-data input[type=tel]:not(.pac-target-input), +.orderform-template-holder #payment-data input[type=email]:not(.pac-target-input), +.orderform-template-holder #payment-data select:not(.pac-target-input), +.cart-more-options .srp-container .vtex-shipping-preview-0-x-addressFormPart1.vtex-shipping-preview-0-x-geolocation input, +.cart-more-options .srp-container select, +.cart-more-options .srp-container input[type=text]:not(.pac-target-input), +.summary-template-holder .summary-coupon fieldset.coupon-fieldset input[type=text], +.summary-template-holder .summary-coupon fieldset.coupon-fieldset button[type=submit], +.table.cart-items td.quantity input, +.table.cart-items tbody tr td .product-service select, +.table.cart-items tr.item-attachments-content input, +.table.cart-items tr.item-attachments-content select, +#vtexIdContainer input { + padding: 0px 16px !important; + border-radius: 2px !important; + border: 1px solid #d4d4d8 !important; + font-family: "Proxima Nova", sans-serif !important; +} + +.vcustom--vtex-omnishipping-1-x-address input::placeholder, +#app-container input[type=text]::placeholder, +#app-container input[type=tel]::placeholder, +#app-container input[type=email]::placeholder, +#app-container select::placeholder, +.orderform-template .summary-note .note-textarea::placeholder, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-addressFormPart1.vtex-omnishipping-1-x-geolocation input::placeholder, +.orderform-template-holder #client-profile-data form.client-pre-email input[type=text]:not(.pac-target-input)::placeholder, +.orderform-template-holder #client-profile-data form.client-pre-email input[type=tel]:not(.pac-target-input)::placeholder, +.orderform-template-holder #client-profile-data form.client-pre-email input[type=email]:not(.pac-target-input)::placeholder, +.orderform-template-holder #client-profile-data form.client-pre-email select:not(.pac-target-input)::placeholder, +.orderform-template-holder #client-profile-data .step.client-profile-data input[type=text]:not(.pac-target-input)::placeholder, +.orderform-template-holder #client-profile-data .step.client-profile-data input[type=tel]:not(.pac-target-input)::placeholder, +.orderform-template-holder #client-profile-data .step.client-profile-data input[type=email]:not(.pac-target-input)::placeholder, +.orderform-template-holder #client-profile-data .step.client-profile-data select:not(.pac-target-input)::placeholder, +.orderform-template-holder #shipping-data input[type=text]:not(.pac-target-input)::placeholder, +.orderform-template-holder #shipping-data input[type=tel]:not(.pac-target-input)::placeholder, +.orderform-template-holder #shipping-data input[type=email]:not(.pac-target-input)::placeholder, +.orderform-template-holder #shipping-data select:not(.pac-target-input)::placeholder, +.orderform-template-holder #payment-data input[type=text]:not(.pac-target-input)::placeholder, +.orderform-template-holder #payment-data input[type=tel]:not(.pac-target-input)::placeholder, +.orderform-template-holder #payment-data input[type=email]:not(.pac-target-input)::placeholder, +.orderform-template-holder #payment-data select:not(.pac-target-input)::placeholder, +.cart-more-options .srp-container .vtex-shipping-preview-0-x-addressFormPart1.vtex-shipping-preview-0-x-geolocation input::placeholder, +.cart-more-options .srp-container select::placeholder, +.cart-more-options .srp-container input[type=text]:not(.pac-target-input)::placeholder, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset input[type=text]::placeholder, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset button[type=submit]::placeholder, +.table.cart-items td.quantity input::placeholder, +.table.cart-items tbody tr td .product-service select::placeholder, +.table.cart-items tr.item-attachments-content input::placeholder, +.table.cart-items tr.item-attachments-content select::placeholder, +#vtexIdContainer input::placeholder { + color: #71717a; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.14px +} + +.btn, +.orderform-template-holder #payment-data .payment-discounts-list table td.action a, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a { + font-family: "Proxima Nova", sans-serif !important; +} + +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a { + color: #fdf2ec !important; +} + + +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a:hover, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a:focus { + color: #fbe5d8 !important; +} + +.btn-primary { + background: #fdf2ec !important; + color: #f1f7ff !important; +} + +body.shared-cart .pg-cartao-fisico, +body.shared-cart #payment-group-creditDirectSalePaymentGroup, +body.shared-cart #payment-group-debitDirectSalePaymentGroup { + display: none!important; +} + +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active { + background: #fbe5d8 !important; + border: 1px solid #fbe5d8 !important; +} + +.btn-secondary, +.orderform-template-holder #payment-data #btn-add-gift-card, +.orderform-template-holder #payment-data .payment-discounts-list table td.action a, +.cart-more-options .srp-container .vtex-shipping-preview-0-x-pc .btn, +.cart-more-options .srp-container .vtex-shipping-preview-0-x-pc .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .cart-more-options .srp-container .vtex-shipping-preview-0-x-pc a, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset button[type=submit], +.table.cart-items tbody tr td .product-service input[type=submit], +.table.cart-items tbody tr td.product-name .add-service.btn, +.table.cart-items tbody tr td.product-name .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a.add-service, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .table.cart-items tbody tr td.product-name a.add-service, +.table.cart-items tbody tr td.product-name .clone-item.btn, +.table.cart-items tbody tr td.product-name .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a.clone-item, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .table.cart-items tbody tr td.product-name a.clone-item, +.table.cart-items tbody tr td.product-name .add-item-attachment-container a { + background: #fdf2ec !important; + color: #ff5a00 !important; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px +} + +.btn-secondary:hover, +.orderform-template-holder #payment-data #btn-add-gift-card:hover, +.orderform-template-holder #payment-data .payment-discounts-list table td.action a:hover, +.cart-more-options .srp-container .vtex-shipping-preview-0-x-pc .btn:hover, +.cart-more-options .srp-container .vtex-shipping-preview-0-x-pc .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a:hover, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .cart-more-options .srp-container .vtex-shipping-preview-0-x-pc a:hover, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset button[type=submit]:hover, +.table.cart-items tbody tr td .product-service input[type=submit]:hover, +.table.cart-items tbody tr td.product-name .add-service.btn:hover, +.table.cart-items tbody tr td.product-name .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a.add-service:hover, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .table.cart-items tbody tr td.product-name a.add-service:hover, +.table.cart-items tbody tr td.product-name .clone-item.btn:hover, +.table.cart-items tbody tr td.product-name .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a.clone-item:hover, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .table.cart-items tbody tr td.product-name a.clone-item:hover, +.table.cart-items tbody tr td.product-name .add-item-attachment-container a:hover, +.btn-secondary:focus, +.orderform-template-holder #payment-data #btn-add-gift-card:focus, +.orderform-template-holder #payment-data .payment-discounts-list table td.action a:focus, +.cart-more-options .srp-container .vtex-shipping-preview-0-x-pc .btn:focus, +.cart-more-options .srp-container .vtex-shipping-preview-0-x-pc .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a:focus, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .cart-more-options .srp-container .vtex-shipping-preview-0-x-pc a:focus, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset button[type=submit]:focus, +.table.cart-items tbody tr td .product-service input[type=submit]:focus, +.table.cart-items tbody tr td.product-name .add-service.btn:focus, +.table.cart-items tbody tr td.product-name .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a.add-service:focus, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .table.cart-items tbody tr td.product-name a.add-service:focus, +.table.cart-items tbody tr td.product-name .clone-item.btn:focus, +.table.cart-items tbody tr td.product-name .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a.clone-item:focus, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .table.cart-items tbody tr td.product-name a.clone-item:focus, +.table.cart-items tbody tr td.product-name .add-item-attachment-container a:focus, +.btn-secondary:active, +.orderform-template-holder #payment-data #btn-add-gift-card:active, +.orderform-template-holder #payment-data .payment-discounts-list table td.action a:active, +.cart-more-options .srp-container .vtex-shipping-preview-0-x-pc .btn:active, +.cart-more-options .srp-container .vtex-shipping-preview-0-x-pc .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a:active, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .cart-more-options .srp-container .vtex-shipping-preview-0-x-pc a:active, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset button[type=submit]:active, +.table.cart-items tbody tr td .product-service input[type=submit]:active, +.table.cart-items tbody tr td.product-name .add-service.btn:active, +.table.cart-items tbody tr td.product-name .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a.add-service:active, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .table.cart-items tbody tr td.product-name a.add-service:active, +.table.cart-items tbody tr td.product-name .clone-item.btn:active, +.table.cart-items tbody tr td.product-name .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a.clone-item:active, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .table.cart-items tbody tr td.product-name a.clone-item:active, +.table.cart-items tbody tr td.product-name .add-item-attachment-container a:active { + background: #fbe5d8 !important; +} + +.orderform-template .cart-template.mini-cart h2, +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle, +.orderform-template-holder #shipping-data .accordion-toggle, +.orderform-template-holder #payment-data .accordion-toggle, +.client-pre-email h3.client-pre-email-h span:after { + color: var(--text-neutral-bold, #18181B) !important; + font-size: 16px; + font-style: normal; + font-weight: 500 !important; + line-height: 24px; + letter-spacing: -0.16px; +} + +.input-append input, +.input-prepend input { + border-radius: 0 2px 2px 0 !important; +} + +.default-modal { + border-radius: 2px !important; +} + +#vtexIdContainer a { + color: #fdf2ec !important; +} + +body { + font-family: "Proxima Nova", sans-serif !important; + min-height: 100vh !important; + box-sizing: border-box; + padding-bottom: 0!important; +} + +body input[type=checkbox] { + width: 16px; + height: 16px; + accent-color: #ff5a00; + border-radius: 4px; +} + +body .checkbox.newsletter-label input[type=checkbox] { + transform: translateY(-2px); +} + +body input.success:not([invalid=true]) { + background-image: url('data:image/svg+xml,'); + background-position: right 16px center +} + +body a { + color: #ee8146; +} + + +.onda-v1 .br-pill, +.step, +.cart, +.totalizers { + border-radius: 2px !important; +} + +.container-main { + min-height: unset; +} + +.cart-more-options { + display: none +} + +.radio-options-container { + display: flex; + flex-direction: column; + gap: 8px; + border: none +} + +.vtex-omnishipping-1-x-leanShippingOption { + border: 1px solid var(--border-neutral-subtlest, #E4E4E7); + padding: 14px 16px; + max-height: 48px; + box-sizing: border-box +} + +.vtex-omnishipping-1-x-leanShippingOption .vtex-omnishipping-1-x-leanShippingIcon { + border-radius: var(--radius-rounded-full, 9999px); + border: 1px solid var(--border-input-base, #D4D4D8); + background: var(--bg-neutral-subtlest-base, #FFF); + width: 16px; + height: 16px; + margin-right: 8px +} + +.vtex-omnishipping-1-x-leanShippingOption .vtex-omnishipping-1-x-leanShippingTextLabel, +.vtex-omnishipping-1-x-leanShippingOption .radio-option-input { + display: none +} + +.vtex-omnishipping-1-x-leanShippingOption.shp-lean-option-active { + border: 1px solid #EE8146 !important; + background: #FDF2EC !important; +} + +.vtex-omnishipping-1-x-leanShippingOption.shp-lean-option-active .vtex-omnishipping-1-x-optionPrice { + color: #ff5a00 +} + +.vtex-omnishipping-1-x-leanShippingOption.shp-lean-option-active .vtex-omnishipping-1-x-leanShippingIcon::before { + content: url('data:image/svg+xml,'); + width: 16px; + height: 16px +} + +.vtex-omnishipping-1-x-leanShippingOption.shp-lean-option-active .vtex-omnishipping-1-x-leanShippingIcon .vtex-omnishipping-1-x-svg { + display: none +} + +.vtex-omnishipping-1-x-leanShippingOption .vtex-omnishipping-1-x-leanShippingText { + border-right: none +} + +.vtex-omnishipping-1-x-leanShippingOption .vtex-omnishipping-1-x-leanShippingText span { + color: var(--text-neutral-bold, #18181B); + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.vtex-omnishipping-1-x-leanShippingOption .vtex-omnishipping-1-x-optionPrice { + color: var(--text-neutral-bold, #18181B); + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.body-order-form .cart-more-options { + display: none !important +} + +.payment-edit-link { + display: none +} + +.valid-coupon .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-fields::after { + content: "Cupom aplicado com sucesso!"; + color: #065F46; + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; + letter-spacing: -0.12px; + width: 100%; + display: block; + text-align: left; + padding-top: 1rem; +} + +.loading-bg, +.loading-img { + background: rgba(0, 0, 0, 0) +} + +.loading-bg .icon-spinner, +.loading-img .icon-spinner { + width: 48px; + height: 48px; + border-radius: 50%; + position: relative; + animation: rotate 1s linear infinite; + opacity: 1 +} + +.loading-bg .icon-spinner::before, +.loading-img .icon-spinner::before { + content: ""; + box-sizing: border-box; + position: absolute; + inset: 0px; + border-radius: 50%; + border: 5px solid #ff5a00; + animation: prixClipFix 2s linear infinite +} + +/* .v-custom-step-shipping #shipping-data .step .accordion-inner { + width: 48px; + height: 48px; + border-radius: 50%; + position: relative; + animation: rotate 1s linear infinite; + opacity: 1; + align-self: center; + margin: 0 auto +} */ + +/* .v-custom-step-shipping #shipping-data .step .accordion-inner .box-step { + display: none +} */ + +/* .v-custom-step-shipping #shipping-data .step .accordion-inner::before { + content: ""; + box-sizing: border-box; + position: absolute; + inset: 0px; + border-radius: 50%; + border: 5px solid #ff5a00; + animation: prixClipFix 2s linear infinite +} */ + +.container { + max-width: 1248px; + width: 100%; + margin: 0 auto +} + +@media screen and (min-width: 1024px) { + .container { + min-height: calc(100vh - 345px); + max-height: 100%; + } +} + +.checkout-container .orderform-template, +.checkout-container .cart-template { + margin-bottom: 0; +} + +.checkout-container .orderform-template .extensions-checkout-buttons-container, +.checkout-container .cart-template .extensions-checkout-buttons-container { + display: none !important; +} + +.v-custom-assemblies { + border-top: 1px solid #d4d4d8 !important; +} + +@keyframes rotate { + 100% { + transform: rotate(360deg) + } +} + +@keyframes prixClipFix { + 0% { + clip-path: polygon(50% 50%, 0 0, 0 0, 0 0, 0 0, 0 0) + } + + 25% { + clip-path: polygon(50% 50%, 0 0, 100% 0, 100% 0, 100% 0, 100% 0) + } + + 50% { + clip-path: polygon(50% 50%, 0 0, 100% 0, 100% 100%, 100% 100%, 100% 100%) + } + + 75% { + clip-path: polygon(50% 50%, 0 0, 100% 0, 100% 100%, 0 100%, 0 100%) + } + + 100% { + clip-path: polygon(50% 50%, 0 0, 100% 0, 100% 100%, 0 100%, 0 0) + } +} + +.client-pre-email h3.client-pre-email-h span:before, +.client-profile-data .accordion-toggle>span:before, +.shipping-data .accordion-toggle:before, +.payment-data .accordion-toggle>span:not(.payment-edit-link):before { + border-radius: var(--radius-rounded-full, 9999px) !important; + background: var(--bg-accent-brand-primary-subtlest, #FBE5D8) !important; + width: 32px !important; + height: 32px !important; + color: var(--text-accent-brand-subtle, #EE8146) !important; + font-size: 14px !important; + font-style: normal; + font-weight: 500; + line-height: 16px !important; + letter-spacing: -0.14px +} + +body .client-profile-data .accordion-toggle>span:before, +body .payment-data .accordion-toggle>span:not(.payment-edit-link):before, +body .shipping-data .accordion-toggle:before, +body .client-profile-data .accordion-toggle>span:before, +body .client-profile-data .accordion-toggle>span:before, +body .shipping-data .accordion-toggle:before, +body .client-profile-data .accordion-toggle>span:before, +.client-profile-data .accordion-toggle>span:before { + border: none; +} + +.client-pre-email h3.client-pre-email-h span:before, +.client-profile-data .accordion-toggle>span:before, +.shipping-data .accordion-toggle:before, +.payment-data .accordion-toggle>span:not(.payment-edit-link):before { + margin-right: 16px !important; + font-size: 14px; + font-style: normal; + font-weight: 500 !important; + line-height: 20px; + letter-spacing: -0.14px; + display: flex !important; + align-items: center; + justify-content: center; +} + +@media(max-width: 690px) { + body:before { + background: #fdf2ec !important; + } +} + +body.v-custom-step-cart .checkout-steps_item_cart:before { + background: #fdf2ec !important; + border-color: #fdf2ec !important; +} + +body.v-custom-step-email .checkout-steps_item_cart:before, +body.v-custom-step-email .checkout-steps_item_identification:before, +body.v-custom-step-profile .checkout-steps_item_cart:before, +body.v-custom-step-profile .checkout-steps_item_identification:before { + background: #fdf2ec !important; + border-color: #fdf2ec !important; +} + +body.v-custom-step-shipping .checkout-steps_item_cart:before, +body.v-custom-step-shipping .checkout-steps_item_identification:before, +body.v-custom-step-shipping .checkout-steps_item_shipping:before { + background: #fdf2ec !important; + border-color: #fdf2ec !important; +} + +body.v-custom-step-payment .checkout-steps_item_cart:before, +body.v-custom-step-payment .checkout-steps_item_identification:before, +body.v-custom-step-payment .checkout-steps_item_shipping:before, +body.v-custom-step-payment .checkout-steps_item_payment:before { + background: #fdf2ec !important; + border-color: #fdf2ec !important; +} + +.checkout-steps__list { + display: flex; + align-items: center; + list-style: none; + justify-content: center !important; + margin: 0 +} + +.checkout-steps__item { + padding-right: 12px +} + +.checkout-steps__item a { + display: flex; + align-items: center; + gap: 12px; + text-decoration: none +} + +.checkout-steps__item a span { + color: var(--Gray-Scale-Black, #000); + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.checkout-steps__item:first-child .checkout-steps__item-icon::before { + display: none +} + +.checkout-steps__item.completed svg:not(.completed) { + display: none +} + +.checkout-steps__item.completed svg.completed { + display: block +} + +.checkout-steps__item.completed svg.completed path:last-child { + fill: #fdf2ec; + stroke: #ee8146 +} + +.checkout-steps__item.active .checkout-steps__item-icon::before { + background-color: #ee8146 +} + +.checkout-steps__item.active span { + color: #ee8146 +} + +.checkout-steps__item.active svg { + fill: #ee8146 +} + +.checkout-steps__item.active svg path { + stroke: #fff +} + +.checkout-steps__item.active .completed { + display: none +} + +.checkout-steps__item-icon { + display: flex; + align-items: center +} + +.checkout-steps__item-icon .completed { + display: none +} + +.checkout-steps__item-icon::before { + content: ""; + display: block; + width: 32px; + height: 1px; + background-color: #71717a +} + +.checkout-steps.mobile { + display: none !important; +} + +@media screen and (max-width: 924px) { + .checkout-steps { + padding: 8px 16px; + overflow-x: auto; + min-width: unset; + box-sizing: border-box; + } + + .checkout-steps.desktop { + display: none!important; + } + + .checkout-steps.mobile { + display: block!important; + } + + .checkout-steps__list { + justify-content: flex-start!important; + } +} + +body .headerContainer { + display: none +} + +body.v-custom-cart-empty .header.new .header-wrapper { + padding-bottom: 20px +} + +body .header.new { + display: block !important; + border-top: 8px solid #ff5a00; + background-color: #fff +} + +body .header.new .header-wrapper { + max-width: 1248px; + margin: 0 auto; + padding: 12px 0 20px; + display: flex; + align-items: center; + justify-content: space-between +} + +body .header.new .header-wrapper .seal-safe-environment { + display: flex; + align-items: center; + gap: 12px +} + +@media screen and (max-width: 406px) { + body .header.new .header-wrapper .seal-safe-environment { + justify-content: flex-end + } +} + +body .header.new .header-wrapper .seal-safe-environment .safe-environment-icon { + height: 20px +} + +body .header.new .header-wrapper .seal-safe-environment span { + color: #000; + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 24px; + letter-spacing: -0.16px; + white-space: nowrap; +} + +@media screen and (max-width: 1024px) { + body .header.new .header-wrapper .seal-safe-environment span { + white-space: wrap; + } +} + +@media screen and (max-width: 406px) { + body .header.new .header-wrapper .seal-safe-environment span { + width: 45%; + font-size: 12px; + line-height: 16px + } +} + +@media screen and (max-width: 1260px) { + body .header.new .header-wrapper { + padding: 12px 16px 20px 16px + } +} + +@media screen and (max-width: 768px) { + body .header.new .header-wrapper { + padding: 20px 16px; + position: relative + } + .container.container-main.container-order-form { + width: 100%; + } + + body .header.new .header-wrapper .store-logo svg { + width: 116px + } +} + +@media screen and (max-width: 768px) { + body .header.new { + border-top: 0 + } +} + +.footerSection { + display: none +} + +.footer.new { + margin-top: 32px; + display: block !important; + background: #000; + padding: 32px 0 +} + +.footer.new .payment-methods-and-seals { + max-width: 1376px; + margin: 0 auto; + display: flex; + align-items: center; + justify-content: space-between +} + +.footer.new .payment-methods-and-seals .payment-methods, +.footer.new .payment-methods-and-seals .seals { + display: flex; + align-items: center; + gap: 16px +} + +.footer.new .payment-methods-and-seals .payment-methods span, +.footer.new .payment-methods-and-seals .seals span { + color: #fff; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.footer.new .payment-methods-and-seals .payment-methods>div, +.footer.new .payment-methods-and-seals .seals>div { + display: flex; + align-items: center; + gap: 16px; + flex-wrap: wrap +} + +@media screen and (max-width: 1397px) { + .footer.new .payment-methods-and-seals { + padding: 0 24px + } +} + +@media screen and (max-width: 768px) { + .footer.new .payment-methods-and-seals { + flex-direction: column; + align-items: flex-start; + padding-bottom: 24px + } +} + +@media screen and (max-width: 547px) { + .footer.new .payment-methods-and-seals .payment-methods { + flex-direction: column; + align-items: flex-start + } +} + +.footer.new .assignature { + border-top: 1px solid #3f3c3c; + padding-top: 24px +} + +.footer.new .assignature-wrapper { + max-width: 1376px; + margin: 0 auto; + display: flex; + align-items: center; + justify-content: space-between +} + +.footer.new .assignature-wrapper span { + color: #fff; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.footer.new .assignature-wrapper .technology { + display: flex; + align-items: center +} + +.footer.new .assignature-wrapper .technology span { + font-size: 12px; + line-height: 16px; + margin-right: 7px +} + +.footer.new .assignature-wrapper .technology .b8-logo { + margin-right: 24px; + height: 14px +} + +@media screen and (max-width: 768px) { + .footer.new .assignature-wrapper .technology .b8-logo { + height: 24px + } + + .footer.new .assignature-wrapper .technology .b8-logo::before { + content: url('data:image/svg+xml,') + } + + .footer.new .assignature-wrapper .technology .b8-logo svg { + display: none + } +} + +.footer.new .assignature-wrapper .technology .vtex-logo { + height: 20px +} + +@media screen and (max-width: 1397px) { + .footer.new .assignature-wrapper { + padding: 0 32px + } +} + +@media screen and (max-width: 768px) { + .footer.new .assignature-wrapper { + flex-direction: column; + gap: 32px; + align-items: flex-start + } +} + +.cart { + border: 1px solid var(--border-neutral-subtlest, #E4E4E7)!important; + background: #fff; + position: relative; +} + +.custom-cart-template-wrap .cart { + border: none!important; +} + +@media screen and (max-width: 1070px) { + .cart { + border: none!important; + } +} + +.empty-cart-content { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 420px; + padding: 0 !important; +} + +.empty-cart-content .empty-cart-title { + color: #18181b; + text-align: center; + font-size: 32px; + font-style: normal; + font-weight: 400; + line-height: 40px; + letter-spacing: -0.32px; + margin: 0; + margin-bottom: 16px +} + +@media screen and (max-width: 768px) { + .empty-cart-content .empty-cart-title { + font-size: 24px; + line-height: 32px; + letter-spacing: -0.24px + } +} + +.empty-cart-content .empty-cart-message p { + color: #71717a; + text-align: center; + font-size: 18px; + font-style: normal; + font-weight: 400; + line-height: 28px; + letter-spacing: -0.18px; + margin: 0 0 32px 0 +} + +@media screen and (max-width: 768px) { + .empty-cart-content .empty-cart-message p { + font-size: 14px; + line-height: 20px; + letter-spacing: -0.14px; + margin-bottom: 16px; + padding: 0 16px + } +} + +.empty-cart-content .empty-cart-links .link-choose-products { + color: #3f3f46 !important; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px; + border-radius: 2px; + border: 1.25px solid #d4d4d8; + background: #fff; + padding: 12px 20px; + text-transform: lowercase; + margin: 0; + transition: all .2s ease-in-out +} + +.empty-cart-content .empty-cart-links .link-choose-products::first-letter { + text-transform: uppercase +} + +.empty-cart-content .empty-cart-links .link-choose-products::before { + content: "Voltar e " +} + +.empty-cart-content .empty-cart-links .link-choose-products:hover { + border: 1.25px solid #ee8146; + background: #fdf2ec; + color: #ff5a00 +} + +@media screen and (max-width: 768px) { + .empty-cart-content { + min-height: unset; + padding: 68px 0 + } +} + +.cart-template-holder { + width: 100%; +} + +.cart-template-holder:has(> .empty-cart-content[style*="display: flex"]) { + flex: none; +} + +.table.cart-items thead tr { + padding: 16px 24px 0!important; + display:flex; + align-items: center!important; +} + +.table.cart-items thead tr th { + padding: 0; + overflow: hidden; + color: var(--text-neutral-subtlest, #71717A); + text-overflow: ellipsis; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; + letter-spacing: -0.12px; +} + +.table.cart-items thead tr th.product { + width: 52.60% !important; +} + +.table.cart-items thead tr th.quantity { + min-width: 62px; + margin-right: 12.47%; +} + +.table.cart-items thead tr th.product-price { + /* width: 211px !important; */ + text-align: left; +} + +@media screen and (max-width: 1070px) { + .table.cart-items thead { + display: none + } +} + +.table.cart-items tbody tr { + border-bottom: 1px solid #e4e4e7; + border-top: none ; +} + +@media screen and (min-width: 1070px) { + .table.cart-items tbody tr:last-child { + border-bottom: none + } +} + +.table.cart-items tbody tr.product-item { + margin: 0; + padding: 0 +} + +.table.cart-items tbody tr.product-item.hide-pix-price .new-product-price { + display: none +} + +.table.cart-items tbody tr.product-item.hide-pix-price .new-product-real-price::before { + content: ''!important; +} + +.table.cart-items tbody tr .v-custom-product-item-wrap { + width:100%; + display: flex; + align-items: center; + position:relative; + padding: 24px; + gap: 7.26%; + box-sizing: border-box; +} + +@media screen and (max-width: 1125px) { + .table.cart-items tbody tr .v-custom-product-item-wrap { + gap: 0; + justify-content: space-between; + } +} + +@media screen and (max-width: 1024px) { + .table.cart-items tbody tr .v-custom-product-item-wrap { + flex-wrap: wrap; + } +} + +@media screen and (max-width: 738px) { + .table.cart-items tbody tr .v-custom-product-item-wrap { + justify-content: flex-start; + padding: 16px 20px; + } + + + .table.cart-items tbody tr .v-custom-product-item-wrap .product-image { + background: none; + grid-area: product-image; + position: unset; + } + + .table.cart-items tbody tr .v-custom-product-item-wrap .product-name { + width: calc(100% - 88px); + grid-area: product-name; + padding: 0px!important; + max-width: 100%; + margin-left: 0!important; + display: flex; + margin-bottom: 12px ; + } + + .table.cart-items tbody tr .v-custom-product-item-wrap .product-name a { + max-width: 100%; + padding-right: 0; + max-height: 32px; + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; /* 133.333% */ + letter-spacing: -0.12px; + } + + .table.cart-items tbody tr .v-custom-product-item-wrap .seller { + display: none; + } + + .table.cart-items tbody tr .v-custom-product-item-wrap .quantity { + grid-area: quantity; + margin-left: 89px !important; + width: fit-content; + } + + .table.cart-items tbody tr .v-custom-product-item-wrap .product-price { + padding: 0; + margin: 0; + padding-left: 10px; + grid-area: price; + } +} + +@media screen and (max-width: 490px) { + .table.cart-items tbody tr .v-custom-product-item-wrap .product-price { + width: 35%!important; + text-align: left; + white-space: wrap; + } + + .table.cart-items tbody tr .v-custom-product-item-wrap .product-image { + position: relative; + } + + .table.cart-items tbody tr .v-custom-product-item-wrap .quantity { + padding: 0 4px !important; + } + + .table.cart-items td.quantity input { + width: 14px !important; + } + +} + + +.table.cart-items tbody tr td.product-name .seller { + display: none !important; +} + +.table.cart-items tbody tr td.product-price, +.table.cart-items tbody tr td.quantity-price { + width: unset !important; +} + +.table.cart-items tbody tr td.product-price { + margin: 0; + padding: 0; +} + +@media screen and (max-width: 812px) { + .table.cart-items tbody tr td.product-price { + margin-left: 10px; + } +} + +.table.cart-items tbody tr td.item-remove .icon-spinner { + width: 20px; + height: 20px; + border-radius: 50%; + position: relative; + animation: rotate 1s linear infinite; + opacity: 1 +} + +.table.cart-items tbody tr td.item-remove .icon-spinner::before { + content: ""; + box-sizing: border-box; + position: absolute; + inset: 0px; + border-radius: 50%; + border: 2px solid #ff5a00; + animation: prixClipFix 2s linear infinite +} + +@media screen and (max-width: 1125px) { + .table.cart-items tbody tr td.item-remove { + margin-left: 0 + } +} + +@media screen and (max-width: 782px) { + .table.cart-items tbody tr td.item-remove { + position: absolute; + right: 16px !important; + top: 16px !important + } +} + +.table.cart-items tbody tr td.product-image { + background-image: none; +} + + + +.table.cart-items tbody tr td.product-price .list-price { + text-align: left; + color: #71717A; + font-family: "Proxima Nova"; + font-size: 0.75rem; + font-style: normal; + font-weight: 400; + line-height: 1rem; + letter-spacing: -0.0075rem; +} + +.table.cart-items tbody tr td.product-price .best-price { + display: flex !important; + flex-direction: column; + color: #18181b; + font-family: "Proxima Nova"; + font-size: 12px; + font-style: normal; + line-height: 16px; + align-items: flex-start; + letter-spacing: -0.12px +} + +.table.cart-items tbody tr td.product-price .best-price .new-product-real-price { + order: 2; + font-weight: 700; + display: block +} + +.table.cart-items tbody tr td.product-price .best-price .new-product-real-price::before { + content: "ou "; + font-weight: 400 +} + +.table.cart-items tbody tr td.product-price .best-price .new-product-real-price::after { + content: " no cart\E3o"; + font-weight: 400 +} + +.table.cart-items tbody tr td.product-price .best-price .new-product-price { + order: 1; + font-weight: 700 +} + +.table.cart-items tbody tr td.product-price .best-price .new-product-price::after { + content: " no pix" +} + +.table.cart-items tbody tr td.product-price .best-price .price-details { + display: none +} + +.table.cart-items tbody tr td .field-help { + background: #fdf2ec !important; + border-color: #fdf2ec !important; +} + +.table.cart-items tbody tr td i.icon-question-sign { + color: #fdf2ec !important; +} + +.table.cart-items tbody tr .v-custom-assemblies { + clear: both +} + +.table.cart-items tbody tr.v-custom-indexed-item .v-custom-product-item-wrap, +.table.cart-items tbody tr.v-custom-indexed-item .v-custom-trservice-wrap, +.table.cart-items tbody tr.item-service .v-custom-product-item-wrap, +.table.cart-items tbody tr.item-service .v-custom-trservice-wrap { + border: 1px dashed #d4d4d8 !important; + border-radius: 2px !important; +} + +@media screen and (min-width: 1070px) { + .table.cart-items tbody tr:last-child { + border-bottom: none + } +} + +@media screen and (max-width: 1070px) { + .table.cart-items tbody { + gap: 16px; + display: flex !important; + flex-direction: column; + background-color: #f4f4f5; + padding: 0 !important; + margin: 0 !important + } + + .table.cart-items tbody tr { + border-radius: 2px; + border: 1px solid var(--Neutral-light, #CFD1D2)!important; + background: var(--Neutral-white, #FFF); + box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.00); + } +} + +.table.cart-items td.product-image { + padding: 0 +} + +.table.cart-items td.product-image a { + overflow: hidden; + border-radius: 2px !important; +} + +.table.cart-items td.product-image a { + margin-right: 24px!important; +} + +.table.cart-items td.product-image a, +.table.cart-items td.product-image img { + width: 64px !important; +} + +.table.cart-items td.product-name { + margin-left: -7.26%; + display: flex; + flex-direction: column; + padding: 0; + max-width: 312px; + width: 100%; +} + + +.table.cart-items td.product-name>a { + order: 2; + color: #18181b !important; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.14px; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box !important; + line-height: 16px; + max-height: 40px; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + max-width: 312px +} + +.table.cart-items td.product-name a.sku-button.sku-selector-button { + display: none !important; +} + +.table.cart-items td.product-name>a:hover { + text-decoration: none; + color: #18181b !important; + font-weight: 400 !important; +} + +.table.cart-items td.product-name .brand { + order: 1; + margin-bottom: 4px; + display: block +} + +.table.cart-items td.product-name .brand .brand-name { + display: block; + color: #ff5a00; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 20px; + letter-spacing: -0.14px +} + +.table.cart-items td.quantity { + padding: 0px 14px !important; + height: 36px; + justify-content: space-between; + border-radius: 2px; + border: 1px solid #d4d4d8; + background: #fff; + max-width: 111px; + width: 100%; + margin: 0; + box-sizing: border-box; +} + +.full-cart .table.cart-items td.quantity input { + width: 30px; + height: 100% !important; + padding: 0 !important; + box-shadow: none; + color: #18181b; + text-align: center; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + border: none !important; +} + +.table.cart-items td.quantity input:focus { + border: none; + box-shadow: none +} + +.table.cart-items td.quantity .item-quantity-change i:before { + position: relative; + top: 5px +} + +.table.cart-items td.quantity .item-quantity-change.item-quantity-change-decrement i:before { + content: url('data:image/svg+xml,') !important; +} + +.table.cart-items td.quantity .item-quantity-change.item-quantity-change-increment i:before { + content: url('data:image/svg+xml,') !important; +} + +.table.cart-items td.quantity .item-multiplier-label, +.table.cart-items td.quantity .item-unit-label { + display: none +} + +.table.cart-items i.icon.icon-remove.item-remove-ico:before { + content: url('data:image/svg+xml,') !important; + width: 16px !important; + height: 16px !important; +} + +.summary-template-holder .summary-coupon fieldset.coupon-fieldset::after { + margin-top: 8px; + display: block; + text-align: left +} + +.summary-template-holder .summary-coupon fieldset.coupon-fieldset p { + margin: 0; + color: #676767 !important; + width: 100% +} + +.orderform-template .cart-template.mini-cart .summary-template-holder .summary-coupon p.coupon-fields { + padding-top: 16px !important; +} + +.summary-template-holder .summary-coupon fieldset.coupon-fieldset p .info { + border-radius: 2px; + border: 1px solid #D4D4D8; + background: #FFF; + width: 100%; + padding: 12px 16px !important; + box-sizing: border-box; + max-height: 2.5rem; +} + +.summary-template-holder .summary-coupon fieldset.coupon-fieldset p .info span[data-bind="text: value"] { + color: var(--text-neutral-bold, #18181B); + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.summary-template-holder .summary-coupon fieldset.coupon-fieldset>div { + flex-direction: column; + align-items: flex-start !important; +} + +.summary-template-holder .summary-coupon p.coupon-fields span.info>span { + color: #18181B !important; +} + +.summary-template-holder .summary-coupon p.coupon-fields span input { + margin-right: 12px !important; +} + +.summary-template-holder .summary-coupon p.coupon-fields .delete { + width: auto +} + +.cart-links-bottom { + float: none; + display: flex; + flex-direction: column-reverse; + align-items: center; + justify-content: center; + gap: 8px; + margin: 0; + padding: 0 0 24px; + border: 1px solid #e4e4e7; + background: #fff; + border-top: 0 +} + +.summary-template-holder .cart-links-bottom::before, +.summary-template-holder .cart-links-bottom::after { + display: none +} + +.summary-template-holder .cart-links-bottom .link-choose-more-products-wrapper { + width: 100%; + display: block !important; + +} + +.summary-template-holder .cart-links-bottom .btn-place-order-wrapper { + width: 100% +} + +.summary-template-holder .cart-links-bottom { + flex-direction: column-reverse !important; +} + +.cart-links-bottom a { + width: 100%; + padding: 12px 20px; + font-size: 16px; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px; + display: flex; + align-items: center; + justify-content: center; + box-sizing: border-box; + position: relative +} + +.summary-template-holder .cart-links-bottom a.link-choose-more-products { + border-radius: 2px; + border: 1.25px solid #d4d4d8; + padding: 12px 18px; + background: #fff; + color: #3f3f46; + margin: 0; + font-size: 0; + transition: all .2s ease-in-out +} + +.summary-template-holder .cart-links-bottom a.link-choose-more-products:hover { + border-radius: 2px; + border: 1.25px solid #ee8146; + background: #fdf2ec; + color: #ff5a00 +} + +.summary-template-holder .cart-links-bottom a.link-choose-more-products::before { + content: "Voltar e continuar comprando"; + font-size: 16px +} + +@media screen and (max-width: 1024px) { + .summary-template-holder .cart-links-bottom { + position: inherit !important; + margin: 0; + } +} + +.cart-links-bottom a#cart-to-orderform { + border-radius: 2px; + background: #2b2b3a; + color: #fff; + border: none; + text-align: center; + width: 100%; + font-size: 0; + transition: all .2s ease-in-out +} + +.cart-links-bottom a#cart-to-orderform:hover { + background: #424250; + color: #fff; +} + +.cart-links-bottom a#cart-to-orderform:hover::before { + color: #fff; + +} + +.cart-links-bottom a#cart-to-orderform::before { + content: "Finalizar compra"; + font-size: 16px +} + +.cart-links-bottom a#cart-to-orderform::after { + content: url('data:image/svg+xml,'); + position: absolute; + right: 20px; + top: 14px +} + +.summary-template-holder tbody { + border: none !important; +} + +.summary-template-holder tbody.totalizers-list { + padding-bottom: 0; +} + +.summary-template-holder tbody td { + display: inline-block; + text-align: left !important; + width: auto +} + +.summary-template-holder tbody td.info { + color: #71717a; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + padding: 0 +} + +.summary-template-holder tbody .srp-summary-result { + order: 0; +} + +.summary-template-holder tbody .Discounts { + order: 1; +} + +.summary-template-holder tbody .srp-summary-result td.info { + font-size: 0 !important; +} + +.summary-template-holder tbody .srp-summary-result td.info::after { + content: 'Frete'; + font-size: 14px !important; +} + +.summary-template-holder .accordion-inner { + margin: 0 !important; +} + +.summary-template-holder tbody td.monetary { + color: #000; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 20px; + letter-spacing: -0.14px +} + +.summary-template-holder tfoot tr td.info { + color: #71717A; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + padding: 0 !important; +} + +.summary-template-holder tfoot tr td.monetary { + color: #000 !important; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 20px; + letter-spacing: -0.14px; + padding: 0 !important +} + +#shipping-preview-container.srp-container .srp-main-title { + color: #18181b; + text-align: left; + font-style: normal; + font-weight: 500; + font-size: 14px; + line-height: 20px; + letter-spacing: -0.14px; + display: flex; + align-items: center; + gap: 8px +} + +#shipping-preview-container.srp-container .srp-main-title::before { + content: url('data:image/svg+xml,'); + width: 20px; + height: 20px; + display: block +} + +#shipping-preview-container.srp-container .srp-description, +#shipping-preview-container.srp-container .srp-toggle { + display: none +} + +#shipping-preview-container.srp-container .srp-data #cart-shipping-calculate { + border-radius: 0 2px 2px 0 !important; + background: #2B2B3A !important; + border: 1px solid #D4D4D8; + border-left: 0; + color: #FFF !important; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + transition: all .2s ease-in-out; + text-transform: uppercase; + margin: 0; + max-width: 111px; + width: 100%; + position: relative; + top: 1px +} + +#shipping-preview-container.srp-container .srp-data #cart-shipping-calculate:hover { + background: var(--bg-brand-secondary-bold-hover, #424250) +} + +#shipping-preview-container.srp-container .srp-data #shipping-calculate-link { + border-radius: 2px; + background: #fdf2ec; + color: #ff5a00 !important; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px; + width: 100%; + transition: all .2s ease-in-out; + text-transform: capitalize; + border: none +} + +.cart-more-options .srp-container .srp-delivery-info .srp-delivery-select-container.b--light-gray { + border: none !important; +} + +#shipping-preview-container.srp-container .srp-delivery-info .srp-delivery-current-many, +#shipping-preview-container.srp-container .srp-delivery-info .srp-delivery-select, +.cart-template.full-cart .cart-more-options { + display: none !important; +} + +.srp-delivery-current-many__arrow { + filter: brightness(0); +} + +.cart-more-options .srp-container .srp-data #shipping-calculate-link::after { + content: " Frete" +} + +.cart-more-options .srp-container .srp-data #shipping-calculate-link:hover { + background: #fbe5d8 +} + +.cart-more-options .srp-container .srp-toggle__wrapper label { + border-radius: 2px !important; +} + +.cart-more-options .srp-container .srp-delivery-info { + padding: 0; + margin: 0 +} + +.cart-more-options .srp-container .srp-delivery-info .srp-shipping-current-single { + padding: 12px; + border: 1px solid var(--border-selected-base, #EE8146); + background: var(--bg-selected-subtle-base, #FDF2EC); + border-radius: 0; +} + +.cart-more-options .srp-container .srp-delivery-info .srp-shipping-current-single .srp-shipping-current-single__wrapper { + margin: 0; +} + +.cart-more-options .srp-container button.shp-open-options { + border-color: #fbe5d8 !important; +} + +/* ah */ + +.cart-more-options .srp-container .onda-v1 .b--blue { + border-color: #fdf2ec !important; +} + +.cart-more-options .srp-container .onda-v1 .bg-blue { + background: #fdf2ec !important; +} + +.cart-more-options .srp-container .vtex-shipping-preview-0-x-pc .btn, +.cart-more-options .srp-container .vtex-shipping-preview-0-x-pc .orderform-template-holder #payment-data .payment-discounts-list table td.action a, +.orderform-template-holder #payment-data .payment-discounts-list table td.action .cart-more-options .srp-container .vtex-shipping-preview-0-x-pc a, +.cart-more-options .srp-container .vtex-shipping-preview-0-x-pc .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data a, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .cart-more-options .srp-container .vtex-shipping-preview-0-x-pc a { + border-radius: 2px !important; +} + +.cart-more-options .srp-container .vtex-shipping-preview-0-x-postalCodeForgotten { + padding-bottom: 17px +} + +.cart-more-options .srp-container .ship-postalCode label { + color: var(--text-neutral-subtle, #3F3F46); + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + margin-bottom: 4px +} + +.cart-more-options .srp-container .ship-postalCode input#ship-postalCode { + border-radius: 2px 0 0 2px; + border: 1px solid var(--border-input-base, #D4D4D8); + background: var(--bg-neutral-subtlest-base, #FFF); + border-right: 0 +} + +.cart-more-options .srp-container .ship-postalCode small { + position: relative; + top: 11px +} + +.cart-more-options .srp-container .ship-postalCode small a { + color: #FF5A00 !important; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.cart-more-options .srp-container .ship-postalCode small a:hover { + text-decoration: none +} + +.cart-more-options #shipping-preview-container { + margin: 0 !important; + width: 100%; + display: block !important; +} + +.cart-more-options #shipping-preview-container .srp-delivery-header .srp-items, +.cart-more-options #shipping-preview-container .srp-delivery-header #deliver-at-text a { + color: #18181B !important; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.cart-more-options #shipping-preview-container .srp-delivery-header #deliver-at-text a:hover { + color: #18181B !important; + text-decoration: none; +} + +.cart-more-options #shipping-preview-container .srp-delivery-header .srp-items strong, +.cart-more-options #shipping-preview-container .srp-delivery-header #deliver-at-text a strong { + font-weight: 500 +} + +.cart-select-gift-placeholder .label-vertical-group:hover .icon-check-empty, +.cart-select-gift-placeholder .icon-check-sign { + color: #fdf2ec !important; +} + +.cart-more-options .cart-select-gift-placeholder { + display: none !important; +} + +.summary-template-holder { + max-width: 294px; + width: 100% !important; +} + +@media screen and (max-width: 1070px) { + .cart-template-holder { + max-width: 100%; + border: none + } + .summary-template-holder { + max-width: 100%; + background: rgba(0, 0, 0, 0); + margin-top: 0 !important; + } + + .cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers { + gap: 16px; + } +} + +@media screen and (min-width: 64rem) { + .cart-template.full-cart.active { + gap: 24px; + } +} + +.cart-template.full-cart.active .summary-coupon-wrap { + display: none +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers { + margin: 0; + display: flex; + flex-direction: column; + gap: 12px; + padding: 0; +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .summary-coupon-wrap, +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .cart-more-options { + padding: 20px 24px; + border: 1px solid #e4e4e7; + background: #fff +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .summary-coupon-wrap { + order: 1; + display: block !important; + box-sizing: border-box; +} + + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .summary-coupon-wrap .coupon-label { + display: flex; + align-items: center; + gap: 8px; + justify-content: flex-start; + margin-bottom: 16px; + height: 20px +} + +.coupon-form .coupon-fieldset .coupon-label, +.coupon-form .coupon-fieldset .coupon-label label { + cursor: pointer !important; +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .summary-coupon-wrap .coupon-label::before { + content: url('data:image/svg+xml,'); + height: 14px +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .summary-coupon-wrap .coupon-label label { + color: #18181b; + font-size: 0px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + height: 20px +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .summary-coupon-wrap .coupon-label label::before { + content: "Adicionar cupom de desconto"; + font-size: 14px +} + +.orderform-template .cart-template.mini-cart .summary-template-holder input[type=text]#cart-coupon { + max-height: inherit !important; +} + +.orderform-template .cart-template.mini-cart .summary-template-holder input[type=text]#cart-coupon:focus { + border: 1.5px solid #EE8146 !important; +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .summary-coupon-wrap #cart-coupon-add { + border: none !important; + font-size: 0; + padding: 10px 13.5px; + min-width: 43px; + height: 40px; + border-radius: 0.125rem !important; + background: #E4E4E7 !important; + color: #71717A !important; + box-shadow: none; + transition: all 0.3s ease-in-out; +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .summary-coupon-wrap #cart-coupon-add:hover { + background: #fdf2ec !important; + color: #ff5a00 !important; +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .summary-coupon-wrap #cart-coupon-add::before { + content: "ok"; + font-size: 14px +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .cart-more-options { + order: 2 +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .cart-more-options .cart-select-gift-placeholder { + margin: 0 +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .cart-more-options .shipping-bar-wrapper { + display: flex !important; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + border-top: 1px solid #e4e4e7; + padding-top: 20px; + margin-top: 20px +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .cart-more-options .shipping-bar-wrapper .shipping-bar-text p, +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .cart-more-options .shipping-bar-wrapper .shipping-bar-text span { + color: #3f3f46; + text-align: center; + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; + letter-spacing: -0.12px +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .cart-more-options .shipping-bar-wrapper .shipping-bar-text p strong, +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .cart-more-options .shipping-bar-wrapper .shipping-bar-text span strong { + font-weight: 500; + color: #ff5a00 +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .cart-more-options .shipping-bar-wrapper .shipping-bar { + width: 100%; + height: 2px; + background: #a1a1aa; + margin-top: 16px +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .cart-more-options .shipping-bar-wrapper .shipping-bar .shipping-bar-progress { + height: 2px; + background-color: #ee8146; + position: relative; + display: flex; + align-items: center +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers .cart-more-options .shipping-bar-wrapper .shipping-bar .shipping-bar-progress::after { + content: ""; + display: block; + width: 12px; + height: 12px; + border-radius: 50%; + background-color: #ee8146; + position: absolute; + right: 0 +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers div[data-bind="template: { name: 'totalizers-template', afterRender: vtex.i18n.translateHtml }"] { + order: 3; + border: 1px solid #e4e4e7; + border-bottom: none; + background: #fff; + padding: 24px 24px 16px; +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers div[data-bind="template: { name: 'totalizers-template', afterRender: vtex.i18n.translateHtml }"] .accordion-heading { + display: block +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers div[data-bind="template: { name: 'totalizers-template', afterRender: vtex.i18n.translateHtml }"] .accordion-heading span { + color: #000; + font-size: 0; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + padding: 0 +} + +.cart-template.full-cart.active .totalizers.summary-totalizers.cart-totalizers div[data-bind="template: { name: 'totalizers-template', afterRender: vtex.i18n.translateHtml }"] .accordion-heading span::before { + content: "Resumo"; + font-size: 14px; + font-weight: 600; +} + +@media screen and (max-width: 1300px) { + .cart-template.full-cart.active { + padding: 0 16px + } +} + +@media screen and (max-width: 1070px) { + .cart-template.full-cart.active { + flex-direction: column!important; + } +} + +.client-pre-email a#orderform-to-cart { + color: #fdf2ec !important; +} + +.client-pre-email .emailInfo .icon-ok, +.client-pre-email .emailInfo h3 { + color: #fdf2ec +} + +.vcustom--vtex-omnishipping-1-x-address label, +.orderform-template-holder .step .input.text label { + color: #3f3f46 !important; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + margin: 0 0 8px !important; +} + + +svg.pickup-marker-blue, +svg.pickup-marker-blue path, +svg.pkpmodal-pickup-point-marker-image, +svg.pkpmodal-pickup-point-marker-image path, +svg.vtex-omnishipping-1-x-svg, +svg.vtex-omnishipping-1-x-svg path, +svg.pkpmodal-pickup-point-best-marker-image path:not([fill=white]) { + fill: #fdf2ec !important; +} + +.orderform-template-holder #shipping-data.postal-code-error .accordion-inner, +.orderform-template-holder #shipping-data.visible .accordion-inner { + width: 100%; + height: 100%; + border-radius: unset; + animation: unset +} + +.orderform-template-holder #shipping-data.postal-code-error .accordion-inner .box-step, +.orderform-template-holder #shipping-data.visible .accordion-inner .box-step { + display: flex +} + +.orderform-template-holder #shipping-data.postal-code-error .accordion-inner::before, +.orderform-template-holder #shipping-data.visible .accordion-inner::before { + display: none +} + +.orderform-template-holder #shipping-data.postal-code-error { + display: block +} + +.orderform-template-holder #shipping-data.postal-code-error .vtex-omnishipping-1-x-addressForm, +.orderform-template-holder #shipping-data.postal-code-error .vtex-omnishipping-1-x-deliveryGroup, +.orderform-template-holder #shipping-data.postal-code-error .vtex-omnishipping-1-x-submitPaymentButton { + display: none !important +} + +.orderform-template-holder #shipping-data.postal-code-error #ship-postalCode { + border-color: red !important; + background-image: url('data:image/svg+xml,') !important; + background-repeat: no-repeat; + background-position: right 16px center +} + +.postal-code-error .ship-postalCode small { + display: flex; + flex-direction: column; + position: relative +} + +.postal-code-error .ship-postalCode small::after { + content: "CEP inválido"; + color: #dd4b39; + font-size: 12px; + position: absolute; + top: 21px; + left: 0; +} + +.help.error { + display: none; +} + + +.orderform-template-holder #client-profile-data { + width: 100% +} + +.orderform-template-holder #client-profile-data form.client-pre-email, +.orderform-template-holder #client-profile-data .step.client-profile-data, +.orderform-template-holder #shipping-data, +.orderform-template-holder #payment-data { + width: 100% !important; + padding: 0; + margin: 0; + box-sizing: border-box; + background: #fff; + border-radius: 2px; + margin-bottom: 20px !important; + z-index: initial; + border: 1px solid var(--border-neutral-subtlest, #E4E4E7); + background: #fff; + padding: 24px; +} + +@media screen and (max-width: 64rem) { + + .orderform-template-holder #payment-data { + padding-bottom: 0 !important; + } +} + + +.orderform-template-holder #client-profile-data form.client-pre-email .link-box-edit, +.orderform-template-holder #client-profile-data .step.client-profile-data .link-box-edit, +.orderform-template-holder #shipping-data .link-box-edit, +.orderform-template-holder #payment-data .link-box-edit { + top: 1.25rem !important; +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle, +.orderform-template-holder #shipping-data .accordion-toggle, +.orderform-template-holder #payment-data .accordion-toggle { + display: flex; + padding: 0!important; +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle span[data-i18n="clientProfileData.identification"], +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle span[data-i18n="paymentData.payment"], +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle.collapsed:not(.accordion-toggle-active), +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle span[data-i18n="clientProfileData.identification"], +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle span[data-i18n="paymentData.payment"], +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle.collapsed:not(.accordion-toggle-active), +.orderform-template-holder #shipping-data .accordion-toggle, +.orderform-template-holder #shipping-data .accordion-toggle.collapsed:not(.accordion-toggle-active), +.orderform-template-holder #payment-data .accordion-toggle span[data-i18n="clientProfileData.identification"], +.orderform-template-holder #payment-data .accordion-toggle span[data-i18n="paymentData.payment"], +.orderform-template-holder #payment-data .accordion-toggle.collapsed:not(.accordion-toggle-active) { + color: #18181b; + font-family: "Proxima Nova"; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px; + vertical-align: middle; + display: flex; + align-items: center; + padding-bottom: 24px!important; + width: 100%; + position: relative; + top: 5px; +} + + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle #edit-shipping-data, +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle #edit-profile-data, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle #edit-shipping-data, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle #edit-profile-data, +.orderform-template-holder #shipping-data .accordion-toggle #edit-shipping-data, +.orderform-template-holder #shipping-data .accordion-toggle #edit-profile-data, +.orderform-template-holder #payment-data .accordion-toggle #edit-shipping-data, +.orderform-template-holder #payment-data .accordion-toggle #edit-profile-data { + border-radius: var(--radius-rounded-sm, 2px); + border: 1.25px solid var(--border-neutral-subtle, #D4D4D8); + background: var(--Gray-Scale-White, #FFF); + padding: 10px 16px; + color: var(--text-neutral-subtle, #3F3F46) !important; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 17px; + letter-spacing: -0.14px; + max-height: 40px +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle #edit-shipping-data i, +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle #edit-profile-data i, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle #edit-shipping-data i, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle #edit-profile-data i, +.orderform-template-holder #shipping-data .accordion-toggle #edit-shipping-data i, +.orderform-template-holder #shipping-data .accordion-toggle #edit-profile-data i, +.orderform-template-holder #payment-data .accordion-toggle #edit-shipping-data i, +.orderform-template-holder #payment-data .accordion-toggle #edit-profile-data i { + display: none +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle #edit-shipping-data:hover, +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle #edit-profile-data:hover, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle #edit-shipping-data:hover, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle #edit-profile-data:hover, +.orderform-template-holder #shipping-data .accordion-toggle #edit-shipping-data:hover, +.orderform-template-holder #shipping-data .accordion-toggle #edit-profile-data:hover, +.orderform-template-holder #payment-data .accordion-toggle #edit-shipping-data:hover, +.orderform-template-holder #payment-data .accordion-toggle #edit-profile-data:hover { + border: 1.25px solid var(--border-brand-primary-base, #EE8146); + background: var(--bg-brand-primary-subtlest-hover, #FDF2EC); + color: #ff5a00 !important; +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle #edit-shipping-data::before, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle #edit-shipping-data::before, +.orderform-template-holder #shipping-data .accordion-toggle #edit-shipping-data::before, +.orderform-template-holder #payment-data .accordion-toggle #edit-shipping-data::before { + content: "Alterar op\E7\E3o de entrega" +} + +@media screen and (max-width: 768px) { + + .orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle #edit-shipping-data::before, + .orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle #edit-shipping-data::before, + .orderform-template-holder #shipping-data .accordion-toggle #edit-shipping-data::before, + .orderform-template-holder #payment-data .accordion-toggle #edit-shipping-data::before { + content: "Alterar" + } +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle #edit-profile-data::before, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle #edit-profile-data::before, +.orderform-template-holder #shipping-data .accordion-toggle #edit-profile-data::before, +.orderform-template-holder #payment-data .accordion-toggle #edit-profile-data::before { + content: "Editar" +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle.collapsed:not(.accordion-toggle-active), +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle.collapsed:not(.accordion-toggle-active), +.orderform-template-holder #shipping-data .accordion-toggle.collapsed:not(.accordion-toggle-active), +.orderform-template-holder #payment-data .accordion-toggle.collapsed:not(.accordion-toggle-active) { + display: flex; + border-bottom: none !important; + padding-bottom: 0 !important +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle.collapsed:not(.accordion-toggle-active)::before, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle.collapsed:not(.accordion-toggle-active)::before, +.orderform-template-holder #shipping-data .accordion-toggle.collapsed:not(.accordion-toggle-active)::before, +.orderform-template-holder #payment-data .accordion-toggle.collapsed:not(.accordion-toggle-active)::before { + background: var(--bg-accent-brand-primary-subtlest, #FBE5D8); + color: #ee8146 +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle.collapsed:not(.accordion-toggle-active)>span, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle.collapsed:not(.accordion-toggle-active)>span, +.orderform-template-holder #shipping-data .accordion-toggle.collapsed:not(.accordion-toggle-active)>span, +.orderform-template-holder #payment-data .accordion-toggle.collapsed:not(.accordion-toggle-active)>span { + width: 100% +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle.collapsed:not(.accordion-toggle-active)>span::before, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle.collapsed:not(.accordion-toggle-active)>span::before, +.orderform-template-holder #shipping-data .accordion-toggle.collapsed:not(.accordion-toggle-active)>span::before, +.orderform-template-holder #payment-data .accordion-toggle.collapsed:not(.accordion-toggle-active)>span::before { + background: var(--bg-accent-brand-primary-subtlest, #FBE5D8) !important; + color: #ee8146 !important; +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle span[data-i18n="clientProfileData.identification"], +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle span[data-i18n="clientProfileData.identification"], +.orderform-template-holder #shipping-data .accordion-toggle span[data-i18n="clientProfileData.identification"], +.orderform-template-holder #payment-data .accordion-toggle span[data-i18n="clientProfileData.identification"] { + font-size: 0 +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle span[data-i18n="clientProfileData.identification"]::after, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle span[data-i18n="clientProfileData.identification"]::after, +.orderform-template-holder #shipping-data .accordion-toggle span[data-i18n="clientProfileData.identification"]::after, +.orderform-template-holder #payment-data .accordion-toggle span[data-i18n="clientProfileData.identification"]::after { + content: "Informações da conta"; + font-size: 16px +} + +.orderform-template-holder #payment-data p.link.link-gift-card, +.orderform-template-holder #payment-data .payment-group-item { + border-radius: 2px !important; + border: 1px solid #d4d4d8 !important; +} + +.orderform-template-holder #payment-data p.link.link-gift-card h3[data-i18n="paymentData.paymentMethod"], +.orderform-template-holder #payment-data fieldset.payment-group h3[data-i18n="paymentData.paymentMethod"] { + display: block; + color: var(--text-neutral-bold, #18181B); + text-align: left; + font-style: normal; + font-weight: 500; + font-size: 0; + line-height: 20px; + letter-spacing: -0.14px +} + +.orderform-template-holder #payment-data p.link.link-gift-card h3[data-i18n="paymentData.paymentMethod"]::before, +.orderform-template-holder #payment-data fieldset.payment-group h3[data-i18n="paymentData.paymentMethod"]::before { + content: "Selecione a forma de pagamento"; + margin-bottom: 12px; + font-size: 14px +} + +.orderform-template-holder #payment-data #iframe-placeholder-creditCardPaymentGroup>.payment-group-item-cards { + display: none +} + +#iframe-placeholder-debitCardPaymentGroup.box-payment-option, +#iframe-placeholder-creditCardPaymentGroup.box-payment-option { + padding: 0 !important; +} + +#iframe-placeholder-debitCardPaymentGroup.box-payment-option::before, +#iframe-placeholder-creditCardPaymentGroup.box-payment-option::before { + content: url('https://roland.vtexassets.com/assets/vtex.file-manager-graphql/images/1f25fc32-554f-491a-8b57-96410d9c9a34___2860e25ed89cdd26cda9577bef3cce81.png'); + width: 424px; + max-width: 100%; + overflow-x: auto; + display: block; + padding-bottom: 1.5rem; +} + +.orderform-template-holder #payment-data .payment-group-list-btn { + width: 96%; + display: flex; + margin-bottom: 24px; + flex-wrap: wrap; + gap: 8px; +} + +.orderform-template-holder #payment-data .payment-group-item { + width: fit-content !important; + border-radius: var(--radius-rounded-sm, 2px); + border: 1.25px solid var(--border-neutral-subtle, #D4D4D8); + background: #fff; + padding: 12px 20px; + box-sizing: border-box; + transition: all .2s ease-in-out; + margin: 0 +} + +@media screen and (max-width: 64rem) { + .orderform-template-holder #payment-data .payment-group-item { + width: 100% !important; + } +} + +.orderform-template-holder #payment-data .payment-group-item:hover { + border: 1.25px solid var(--border-brand-primary-base, #EE8146); + background: var(--bg-brand-primary-subtlest-hover, #FDF2EC) +} + +.orderform-template-holder #payment-data .payment-group-item:hover span.payment-group-item-text { + color: #ff5a00 +} + +.orderform-template-holder #payment-data .payment-group-item span.payment-group-item-text { + color: var(--text-neutral-subtle, #3F3F46); + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + background: none; + letter-spacing: -0.16px; + padding: 0 +} + +.orderform-template-holder #payment-data .payment-group-item.active { + background: var(--bg-brand-secondary-bold-base, #2B2B3A); + border: 1.25px solid rgba(0, 0, 0, 0) +} + +.orderform-template-holder #payment-data .payment-group-item.active:hover { + background: var(--bg-brand-secondary-bold-hover, #424250) +} + +.orderform-template-holder #payment-data .payment-group-item.active span.payment-group-item-text { + color: #fff +} + +.orderform-template-holder #payment-data .payment-group-item.active span.payment-group-item-text::after { + color: #fff !important +} + +.orderform-template-holder #payment-data .payment-group-item#payment-group-PagalevePixAVistaTransparentePaymentGroup span::after, +.orderform-template-holder #payment-data .payment-group-item#payment-group-bankInvoicePaymentGroup span::after { + content: " (10% OFF)"; + color: var(--text-brand-primary-base, #FF5A00); + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 24px; + letter-spacing: -0.16px +} + +@media screen and (max-width: 653px) { + .orderform-template-holder #payment-data .payment-group-item { + width: 100% + } +} + +.orderform-template-holder #payment-data #btn-add-gift-card { + border-radius: 2px !important; +} + +.orderform-template-holder #payment-data .steps-view .payment-method .bankInvoicePaymentGroup { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + padding: 64px 0; + margin: 0 +} + +.orderform-template-holder #payment-data .steps-view .payment-method .bankInvoicePaymentGroup::before { + content: url('data:image/svg+xml,') +} + +.orderform-template-holder #payment-data .steps-view .payment-method .bankInvoicePaymentGroup .payment-description { + width: 100%; + margin: 0; + margin-bottom: 8px; + margin-top: 24px; + padding: 0; + font-size: 0; + color: var(--text-neutral-bold, #18181B); + text-align: center; + font-style: normal; + font-weight: 500; + line-height: 28px; + letter-spacing: -0.2px; + max-width: 100% +} + +.orderform-template-holder #payment-data .steps-view .payment-method .bankInvoicePaymentGroup .payment-description::before { + content: "Voc\EA poder\E1 baixar o boleto para pagamento ap\F3s finalizar o pedido."; + font-size: 20px +} + +.orderform-template-holder #payment-data .steps-view .payment-method .bankInvoicePaymentGroup .sight .total::after { + content: " do boleto" +} + +.orderform-template-holder #payment-data .steps-view .payment-method .bankInvoicePaymentGroup .sight span { + color: var(--text-neutral-subtle, #3F3F46); + text-align: center; + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 24px; + letter-spacing: -0.16px +} + +.orderform-template-holder #payment-data .steps-view .payment-method .bankInvoicePaymentGroup .sight span[data-bind="text: window.paymentData.totalToPayIncludingGiftsLabel"] { + color: #18181b +} + +@media screen and (max-width: 768px) { + .orderform-template-holder #payment-data .steps-view .payment-method .bankInvoicePaymentGroup { + padding: 64px 32px; + box-sizing: border-box + } + + .orderform-template-holder #payment-data .steps-view .payment-method .bankInvoicePaymentGroup .sight { + text-align: center; + margin: 0 + } +} + +.orderform-template-holder #payment-data .v-custom-payment-item-wrap { + border-radius: 2px !important; + border: 1px solid #d4d4d8 !important; +} + +.orderform-template-holder #payment-data .v-custom-payment-item-wrap.active, +.orderform-template-holder #payment-data .v-custom-payment-item-wrap:hover { + border-color: #fdf2ec !important; +} + +.orderform-template-holder #payment-data .v-custom-payment-item-wrap .payment-group-item.active { + border-bottom: 1px solid #fdf2ec !important; +} + +.orderform-template-holder #payment-data .v-custom-payment-item-wrap .payment-group-item.active .payment-group-item-text:before { + background: #fdf2ec !important; + border-color: #fdf2ec !important; +} + +.orderform-template-holder #payment-data .v-custom-payment-item-wrap .payment-group-item:hover .payment-group-item-text:before { + border-color: #fdf2ec !important; +} + + +.orderform-template-holder .step .box-info { + display: flex; + flex-direction: column; + margin-top: 24px; +} + +.orderform-template-holder .step .box-info p span { + color: var(--text-neutral-bold, #18181B); + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.14px; + margin-bottom: 4px +} + +.orderform-template-holder .step .box-info .client-profile-email { + order: 2 +} + +.orderform-template-holder .step .box-info .client-profile-summary { + order: 1 +} + +.orderform-template-holder .step .form-step fieldset { + width: 100%; + float: none; + margin: 24px 0; + margin-bottom: 0; +} + +.orderform-template-holder .step .form-step fieldset.PagalevePaymentGroup { + margin-top: 0 +} + +.orderform-template-holder .step .form-step fieldset.PagalevePaymentGroup .pagaleve-container { + max-width: 485px; + margin: 0 auto; +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup { + margin-top: 0 +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container { + border: none; + box-shadow: none; + padding: 32px 0; + padding-bottom: 48px; + box-sizing: border-box +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-logo-container { + flex-grow: unset; + margin: 0; + margin-bottom: 48px +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-logo-container .pagaleve-pix-a-vista-logo { + max-width: 133px; + background-image: url('data:image/svg+xml,'); + background-repeat: no-repeat; + background-size: contain; + height: 48px +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container { + position: relative; + max-width: 440px; + align-self: center; + margin: 0; + width: 100% +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container::after { + content: ""; + width: 100%; + height: 1px; + background-color: #d4d4d8; + display: block +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container p { + font-size: 0; + color: var(--text-neutral-subtle, #3F3F46); + text-align: center; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.14px; + margin: 0; + position: absolute; + display: flex; + flex-direction: column; + align-items: center +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container p::after { + color: var(--text-neutral-subtle, #3F3F46); + text-align: center; + font-family: "Proxima Nova"; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; + letter-spacing: -0.12px; + position: relative; + top: 10px; + max-width: 207px +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container p::before { + border-radius: 16px; + border: 1px solid var(--border-neutral-subtle, #D4D4D8); + background: var(--bg-accent-zinc-subtlest, #F4F4F5); + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: -15px +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container p:first-child { + left: -120px +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container p:first-child::before { + content: "1"; + font-size: 14px +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container p:first-child::after { + content: "Aperte em Finalizar compra para gerar QR Code."; + left: 0 +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container p:last-child { + right: -120px +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container p:last-child::before { + content: "2"; + font-size: 14px +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container p:last-child::after { + right: 0; + content: "Confira os dados e realize o pagamento pelo app do seu banco" +} + +@media screen and (max-width: 780px) { + .orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container { + display: flex; + flex-direction: column; + gap: 100px + } + + .orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container p { + position: relative; + left: 0 !important; + right: 0 !important; + align-self: center + } + + .orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-advisor-container::after { + height: 75px; + width: 1px; + position: absolute; + align-self: center; + top: 62px + } +} + +.orderform-template-holder .step .form-step fieldset.PagalevePixAVistaPaymentGroup .pagaleve-pix-a-vista-container .pagaleve-pix-a-vista-footer-container { + display: none +} + +.orderform-template-holder .step .form-step fieldset p { + position: relative; + max-width: 274px; + margin-right: 32px; + margin-bottom: 16px +} + +@media screen and (max-width: 690px) { + .orderform-template-holder .step .form-step fieldset p { + max-width: 100%; + margin-right: 0 + } +} + +.orderform-template-holder .step .form-step fieldset p.client-notice { + display: none +} + +.orderform-template-holder .step .form-step fieldset p.client-last-name, +.orderform-template-holder .step .form-step fieldset p.client-first-name { + width: 100% !important; +} + +.orderform-template-holder .step .form-step fieldset p.client-last-name label, +.orderform-template-holder .step .form-step fieldset p.client-first-name label { + font-size: 0; +} + +.box-client-info p label:not(.newsletter-label)::after { + content: '*'; +} + +.orderform-template-holder .step .form-step fieldset p.client-last-name label::after { + content: 'Sobrenome*'; + font-size: 0.875rem; +} + +.orderform-template-holder .step .form-step fieldset p.client-first-name label::after { + content: 'Nome*'; + font-size: 0.875rem; +} + + + +.orderform-template-holder .step .form-step fieldset.box-client-info-pj .corporate-hide-link a { + max-width: 263px; + color: #ff5a00 !important; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px; + border-radius: 2px; + background: #fdf2ec; + padding: 12px 20px; + box-sizing: border-box; + transition: all .2s ease-in-out; + cursor: pointer +} + +.orderform-template-holder .step .form-step fieldset.box-client-info-pj .corporate-hide-link a:hover { + text-decoration: none; + background: #fbe5d8 +} + +@media screen and (max-width: 500px) { + .orderform-template-holder .step .form-step fieldset.box-client-info-pj .corporate-hide-link a { + max-width: 100% + } +} + +.orderform-template-holder .step .form-step fieldset.box-client-info-pj .links { + width: fit-content; + margin: 0 +} + +.orderform-template-holder .step .form-step fieldset.box-client-info-pj .links .link { + display: flex +} + +.orderform-template-holder .step .form-step .btn-submit-wrapper { + position: absolute; + right: 0; + bottom: 0; + margin: 0 +} + +.orderform-template-holder .step .form-step .btn-submit-wrapper button { + font-size: 0; + color: #fff; + font-family: "Proxima Nova"; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px; + padding: 12px 20px; + display: flex; + align-items: center; + justify-content: space-between; + border-radius: 2px; + background: #2b2b3a; + border: none; + gap: 8px; + transition: all ease .2s ease-in-out; + margin: 0!important; + max-height: 48px; +} + +.orderform-template-holder .step .form-step .btn-submit-wrapper button:hover { + background-color: #424250 +} + +.orderform-template-holder .step .form-step .btn-submit-wrapper button::before { + content: "Avançar"; + font-size: 16px +} + +.orderform-template-holder .step .form-step .btn-submit-wrapper button::after { + content: url('data:image/svg+xml,'); + width: 20px; + height: 20px; + display: inline-block; + transform: translate(9px, 5px); + +} + +@media screen and (max-width: 786px) { + .orderform-template-holder .step .form-step .btn-submit-wrapper { + position: unset; + margin-top: 10px + } + + .orderform-template-holder .step .form-step .btn-submit-wrapper button { + width: 100%; + justify-content: center + } +} + +.orderform-template-holder .step.client-profile-data .box-client-info .newsletter { + position: absolute; + top: 286px; +} + + + +@media screen and (max-width: 768px) { + .orderform-template-holder .step.client-profile-data .box-client-info .newsletter { + position: unset + } +} + +.orderform-template-holder .step.client-profile-data .box-client-info .row-fluid::before, +.orderform-template-holder .step.client-profile-data .box-client-info .row-fluid::after { + display: none +} + +.orderform-template-holder .step.client-profile-data .client-document, +.orderform-template-holder .step.client-profile-data .client-phone { + width: 100% +} + +.orderform-template-holder .step.shipping-data .box-step { + display: flex; + flex-wrap: wrap; +} + +.orderform-template-holder .step.shipping-data .box-step .vtex-omnishipping-1-x-SummaryItemGroup { + padding: 24px 0; + border-top: 1px solid #e4e4e7 +} + +.orderform-template-holder .step.shipping-data .box-step .vtex-omnishipping-1-x-SummaryItemGroup .vtex-omnishipping-1-x-SummaryItemInfo { + border-right: none +} + +.orderform-template-holder .step.shipping-data .box-step .vtex-omnishipping-1-x-SummaryItemGroup .vtex-omnishipping-1-x-SummaryItemPrice { + display: none +} + +.orderform-template-holder .step.shipping-data .box-step .vtex-omnishipping-1-x-SummaryItemGroup span { + color: var(--text-neutral-bold, #18181B); + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.14px +} + +.orderform-template-holder .step.shipping-data .box-step .vtex-omnishipping-1-x-SummaryItemGroup .address-summary { + display: flex; + flex-wrap: wrap; + gap: 3px +} + +.orderform-template-holder .step.shipping-data .box-step #postalCode-finished-loading { + display: none +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-addressFormPart1 .ship-postalCode { + max-width: 274px; + margin-bottom: 1rem; +} + +@media screen and (max-width: 499px) { + .orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-addressFormPart1 .ship-postalCode { + max-width: 100% !important + } +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-addressFormPart1 .ship-postalCode small { + margin: 0; + margin-top: 12px; + display: block +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-addressFormPart1 .ship-postalCode small a { + color: #FF5A00 !important; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-addressForm .vtex-omnishipping-1-x-shippingSectionTitle { + color: var(--text-neutral-subtle, #3F3F46); + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-addressForm .address-summary span { + color: var(--text-neutral-bold, #18181B); + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.14px +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-deliveryGroup .vtex-omnishipping-1-x-shippingSectionTitle { + color: var(--text-neutral-bold, #18181B); + text-align: left; + font-style: normal; + font-size: 0; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-deliveryGroup .vtex-omnishipping-1-x-shippingSectionTitle::before { + content: "Selecione a forma de entrega"; + font-size: 14px +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-deliveryGroup .vtex-omnishipping-1-x-leanShippingGroupList .vtex-omnishipping-1-x-leanShippingOption, +.vtex-omnishipping-1-x-addressList .vtex-omnishipping-1-x-addressItemOption, +.vtex-omnishipping-1-x-leanShippingOption, +.vtex-omnishipping-1-x-addressList .vtex-omnishipping-1-x-buttonEditAddress, +.vtex-omnishipping-1-x-addressFormPart1 .vtex-omnishipping-1-x-backToAddressList, +.vtex-omnishipping-1-x-addressList .vtex-omnishipping-1-x-buttonCreateAddress{ + border: 1px solid var(--border-neutral-subtlest, #E4E4E7); + padding: 14px 16px; + max-height: 48px; + box-sizing: border-box +} + +.vtex-omnishipping-1-x-addressList .vtex-omnishipping-1-x-addressItemOption { + max-height: 100%; +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-deliveryGroup .vtex-omnishipping-1-x-leanShippingGroupList .vtex-omnishipping-1-x-leanShippingOption .vtex-omnishipping-1-x-leanShippingTextLabel { + display: none +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-deliveryGroup .vtex-omnishipping-1-x-leanShippingGroupList .vtex-omnishipping-1-x-leanShippingOption.shp-lean-option-active, +.vtex-omnishipping-1-x-active { + border: 1px solid #EE8146 !important; + background: #FDF2EC !important; +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-deliveryGroup .vtex-omnishipping-1-x-leanShippingGroupList .vtex-omnishipping-1-x-leanShippingOption.shp-lean-option-active .vtex-omnishipping-1-x-optionPrice { + color: #ff5a00 +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-deliveryGroup .vtex-omnishipping-1-x-leanShippingGroupList .vtex-omnishipping-1-x-leanShippingOption.shp-lean-option-active .vtex-omnishipping-1-x-leanShippingIcon { + margin-right: 8px +} + +#shipping-preview-container.srp-container .srp-delivery-info .srp-shipping-current-single .srp-shipping-current-single__bullet::before, +.vtex-omnishipping-1-x-active .vtex-omnishipping-1-x-addressItemIcon::before, +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-deliveryGroup .vtex-omnishipping-1-x-leanShippingGroupList .vtex-omnishipping-1-x-leanShippingOption.shp-lean-option-active .vtex-omnishipping-1-x-leanShippingIcon::before { + content: url('data:image/svg+xml,'); + width: 16px; + height: 16px; + display: block; +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-deliveryGroup .vtex-omnishipping-1-x-leanShippingGroupList .vtex-omnishipping-1-x-leanShippingOption.shp-lean-option-active .vtex-omnishipping-1-x-leanShippingIcon .vtex-omnishipping-1-x-svg, +#shipping-preview-container.srp-container .srp-delivery-info .srp-shipping-current-single .srp-icon-radio-selected { + display: none +} + +#shipping-preview-container.srp-container .srp-delivery-info .srp-shipping-current-single .srp-shipping-current-single__sla { + color: #18181B !important; + border: none; +} + +#shipping-preview-container.srp-container .srp-delivery-info .srp-shipping-current-single .srp-shipping-current-single__price { + color: #FF5A00 !important +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-deliveryGroup .vtex-omnishipping-1-x-leanShippingGroupList .vtex-omnishipping-1-x-leanShippingOption .vtex-omnishipping-1-x-leanShippingText { + border-right: none +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-deliveryGroup .vtex-omnishipping-1-x-leanShippingGroupList .vtex-omnishipping-1-x-leanShippingOption .vtex-omnishipping-1-x-leanShippingText span, +.vtex-omnishipping-1-x-addressFormPart1 .vtex-omnishipping-1-x-backToAddressList, +.vtex-omnishipping-1-x-buttonEditAddress, +.vtex-omnishipping-1-x-buttonCreateAddress { + color: var(--text-neutral-bold, #18181B)!important; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.vtex-omnishipping-1-x-buttonEditAddress:hover +.vtex-omnishipping-1-x-buttonCreateAddress:hover { + color: var(--text-neutral-bold, #18181B)!important; + +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-deliveryGroup .vtex-omnishipping-1-x-leanShippingGroupList .vtex-omnishipping-1-x-leanShippingOption .vtex-omnishipping-1-x-optionPrice { + color: var(--text-neutral-bold, #18181B); + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-submitPaymentButton { + margin-top: 24px; + display: flex; + justify-content: flex-end; + margin-bottom: 1.5rem; +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-submitPaymentButton #btn-go-to-payment { + display: none !important; +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-submitPaymentButton button:hover { + background-color: #424250 +} + +.orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-submitPaymentButton button::after { + content: url('data:image/svg+xml,'); + width: 20px; + height: 20px; + display: block +} + +@media screen and (max-width: 768px) { + .orderform-template-holder .step.shipping-data .box-step>*.vtex-omnishipping-1-x-submitPaymentButton button { + width: 100%; + justify-content: center; + align-items: center + } +} + +.orderform-template-holder .step.shipping-data .box-step>*.btn-link.vtex-omnishipping-1-x-btnDelivery, +.orderform-template-holder .step.shipping-data .summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .box-step>a.vtex-omnishipping-1-x-btnDelivery, +.summary-template-holder .summary-coupon fieldset.coupon-fieldset .coupon-data .orderform-template-holder .step.shipping-data .box-step>a.vtex-omnishipping-1-x-btnDelivery { + background: #fdf2ec !important; +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address { + margin: 0 +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address>div { + display: flex; + flex-wrap: wrap +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-addressSummaryActive .address-summary { + background: url("data:image/svg+xml;utf8, ") no-repeat !important; + background-position: 11px 18px !important; + border-radius: var(--radius-rounded-sm, 2px); + border: 1px solid var(--border-input-base, #D4D4D8) !important; +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-pickupButton, +.orderform-template-holder .step.shipping-data .vtex-pickup-points-modal-3-x-pickupViewOptionActive, +.orderform-template-holder .step.shipping-data .vtex-pickup-points-modal-3-x-pickupViewOptionActive:hover, +.orderform-template-holder .step.shipping-data .vtex-pickup-points-modal-3-x-pickupViewOptionActive:active, +.orderform-template-holder .step.shipping-data .vtex-pickup-points-modal-3-x-pickupViewOptionActive:focus, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-deliveryChannelsTogglePickup, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-deliveryChannelsOption.vtex-omnishipping-1-x-deliveryOptionActive { + background: #fdf2ec !important; + border-color: #fdf2ec !important; + border-radius: 2px !important; +} + +.orderform-template-holder .step.shipping-data .vtex-pickup-points-modal-3-x-pickupViewOptionInctive { + color: #fdf2ec !important; + border-color: #fdf2ec !important; + border-radius: 2px !important; +} + +.orderform-template-holder .step.shipping-data .shipping-method-toggle { + border-color: #fdf2ec !important; +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-linkEdit { + color: var(--text-link-primary-default-base, #FF5A00); +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-deliveryChannelsWrapper, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-deliveryChannelsToggle { + border-radius: 2px !important; +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-deliveryChannelsWrapper { + border: 1px solid #d4d4d8 !important; +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-summaryChange { + display: none +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-leanShippingGroupList { + margin: 0; + display: flex; + flex-direction: column; + gap: 12px; + border: none; + overflow: unset +} + +.orderform-template-holder .step.shipping-data .vtex-pickup-points-modal-3-x-primary { + background: #fdf2ec !important; + border-color: #fdf2ec !important; +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-pickupPointChange { + border-color: #fdf2ec !important; +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-street, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-complement, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-neighborhood, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-city, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-state, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-receiverName { + width: 100%; + margin-bottom: 16px +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-street input, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-street select, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-complement input, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-complement select, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-neighborhood input, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-neighborhood select, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-city input, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-city select, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-state input, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-state select, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-receiverName input, +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-receiverName select { + max-width: 274px !important +} + +@media screen and (max-width: 499px) { + + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-street input, + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-street select, + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-complement input, + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-complement select, + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-neighborhood input, + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-neighborhood select, + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-city input, + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-city select, + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-state input, + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-state select, + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-receiverName input, + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-receiverName select { + max-width: 100% !important + } +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-complement { + max-width: 274px; + width: 100%; + margin-left: 24px +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-complement label { + font-size: 0; + height: 20px +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-complement label::before { + content: "Complemento"; + font-size: 14px +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-number { + max-width: 128px +} + +@media screen and (max-width: 499px) { + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-complement { + max-width: 43%; + margin-left: 19px + } + + .orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-address p.ship-complement input { + max-width: 120px + } +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-container.shp-pickup-receiver svg.person-blue path { + fill: #fdf2ec !important; +} + +.orderform-template-holder .step.shipping-data .vtex-omnishipping-1-x-container.shp-pickup-receiver .vtex-omnishipping-1-x-btn { + color: #fdf2ec !important; +} + +.orderform-template { + padding: 0 16px !important; + gap: 24px; + margin-top: 32px; +} + +.orderform-template::before, +.orderform-template::after { + display: none +} + +@media screen and (max-width: 960px) { + .orderform-template { + flex-direction: column; + padding: 16px + } +} + +@media screen and (min-width: 1024px) { + .orderform-template .orderform-template-holder { + width: 74.52% !important; + } +} + +@media screen and (max-width: 1024px) { + .orderform-template .orderform-template-holder { + width: 100% !important; + } + +.orderform-template-holder .step.client-profile-data .box-client-info .newsletter { + top: unset; + bottom: 71px; + } + +} + +.orderform-template .orderform-template-holder { + max-width: 930px; + box-sizing: border-box; + padding: 0 !important; +} + +.orderform-template .cart-template.mini-cart { + max-width: 294px; + width: 100% !important; + background: var(--elevation-raised, #FFF); +} + +.orderform-template .cart-template.mini-cart .cart-fixed h2 { + padding: 1rem 0 0 1.5rem !important; + font-size: 0; + line-height: 1.25rem; + letter-spacing: -0.14px; +} + +.orderform-template .cart-template.mini-cart .cart-fixed h2::after { + content: "Resumo"; + font-size: 0.875rem; +} + +@media screen and (max-width: 960px) { + .orderform-template .cart-template.mini-cart { + width: 100%; + max-width: 100%; + position: relative; + top: 0 + } +} + +.orderform-template .cart-template.mini-cart .quantity { + min-width: 24px !important; + height: 24px !important; + border-radius: var(--radius-rounded-full, 9999px); + background: var(--bg-accent-brand-primary-subtlest, #FBE5D8) !important; + color: var(--text-neutral-bold, #18181B) !important; + text-align: center; + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; + letter-spacing: -0.12px; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + border: none; + box-shadow: none +} + +.orderform-template .cart-template.mini-cart .summary-template-holder .summary>.summary-coupon-wrap { + width: 100%; + padding: 20px 24px !important; + border-top: 1px solid var(--border-neutral-subtlest, #E4E4E7) !important; + border-bottom: 1px solid var(--border-neutral-subtlest, #E4E4E7) !important; + border-left: none; + border-right: none; +} + +.orderform-template .cart-template.mini-cart .summary-template-holder .summary>.summary-coupon-wrap .coupon-label { + display: flex; + align-items: center; + gap: 8px; + justify-content: flex-start; + height: 20px +} + +.orderform-template .cart-template.mini-cart .summary-template-holder .summary>.summary-coupon-wrap .coupon-label::before { + content: url('data:image/svg+xml,'); + height: 14px +} + +.orderform-template .cart-template.mini-cart .summary-template-holder .summary>.summary-coupon-wrap .coupon-label label { + color: #18181b; + font-size: 0px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + height: 20px +} + +.orderform-template .cart-template.mini-cart .summary-template-holder .summary>.summary-coupon-wrap .coupon-label label::before { + content: "Adicionar cupom de desconto"; + font-size: 14px +} + +.orderform-template .cart-template.mini-cart .summary-template-holder .summary>.summary-coupon-wrap #cart-coupon-add { + border: none !important; + font-size: 0; + padding: 10px 13.5px; + min-width: 43px; + height: 2.5rem; + background-color: #E4E4E7 !important; + color: #71717A !important; +} + +.orderform-template .cart-template.mini-cart .summary-template-holder .summary>.summary-coupon-wrap #cart-coupon-add::before { + content: "ok"; + font-size: 14px +} + +.orderform-template .cart-template.mini-cart .item { + padding: 12px !important; + border-bottom: 1px solid #e4e4e7 !important; + background: #fff; + display: flex; + max-width: 234px; + box-sizing: border-box +} + +@media screen and (max-width: 960px) { + .orderform-template .cart-template.mini-cart .item { + max-width: 100% + } +} + +.orderform-template .cart-template.mini-cart .item .service-item, +.orderform-template .cart-template.mini-cart .item.v-custom-indexed-item { + border: 1px dashed #d4d4d8 !important; + border-radius: 2px !important; +} + +.orderform-template .cart-template.mini-cart .item .description { + display: flex; + position: absolute; + left: 71px; + top: 46px; + margin: 0 +} + +.orderform-template .cart-template.mini-cart .item .description .shipping-date { + display: none !important; +} + +.orderform-template .cart-template.mini-cart .item .description .price { + overflow: hidden; + color: var(--text-neutral-subtle, #3F3F46); + text-overflow: ellipsis; + white-space: nowrap; + font-size: 12px; + font-style: normal; + font-weight: 600; + line-height: 16px; + letter-spacing: -0.12px +} + +.orderform-template .cart-template.mini-cart .item .price { + white-space: nowrap +} + +.orderform-template .cart-template.mini-cart .item .url { + width: 48px; + height: 48px; + margin-right: 12px +} + +.orderform-template .cart-template.mini-cart .item .product-name { + overflow: hidden; + color: var(--text-neutral-subtlest, #71717A); + text-overflow: ellipsis; + white-space: nowrap; + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; + letter-spacing: -0.12px; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + white-space: unset; + max-height: 32px +} + +.orderform-template .cart-template.mini-cart #go-to-cart-button { + display: none +} + +.orderform-template .cart-template.mini-cart .summary-totalizers tbody { + padding: 16px 24px 0 !important; + display: flex; + flex-direction: column; +} + +.orderform-template .cart-template.mini-cart .summary-totalizers tbody tr { + margin-bottom: 8px +} + +.orderform-template .cart-template.mini-cart .summary-totalizers tbody tr:last-child { + margin-bottom: 0 +} + +.orderform-template .cart-template.mini-cart .summary-totalizers tbody td { + text-align: left !important; + width: auto +} + +.orderform-template .cart-template.mini-cart .summary-totalizers tbody td.info { + color: #71717a; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + padding: 0 +} + +.orderform-template .cart-template.mini-cart .summary-totalizers tbody .Discounts td.info, +.summary-template-holder tbody .Discounts td.info { + font-size: 0; +} + +.orderform-template .cart-template.mini-cart .summary-totalizers tbody .Discounts td.info::after, +.summary-template-holder tbody .Discounts td.info::after { + content: 'Desconto'; + font-size: 14px; +} + +.orderform-template .cart-template.mini-cart .summary-totalizers tbody td.monetary { + text-align: right !important; + margin-left: auto; + float: right; + color: #000; + font-size: 0.875rem; + font-style: normal; + line-height: 1.25rem; + letter-spacing: -0.00875rem; + padding: 0 +} + +.orderform-template .cart-template.mini-cart .summary-totalizers tbody td.empty { + display: none +} + +.orderform-template .cart-template.mini-cart .summary-totalizers tfoot { + padding: 0 24px; + display: block +} + +.orderform-template .cart-template.mini-cart .summary-totalizers tfoot tr td.info { + color: #71717a; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + padding: 0 0 1rem !important; +} + +.orderform-template .cart-template.mini-cart .summary-totalizers tfoot tr td.monetary { + color: #000; + font-size: 0.875rem; + font-style: normal; + font-weight: 600; + line-height: 1.25rem; + letter-spacing: -0.00875rem; + padding: 0 0 1rem !important; +} + + +.orderform-template .cart-template.mini-cart .cart { + margin-bottom: 0; + max-height: 12rem; + padding: 0; +} + +.orderform-template .cart-template.mini-cart .cart .cart-items::-webkit-scrollbar-track { + border-radius: 2px !important; +} + +.orderform-template .cart-template.mini-cart .cart .cart-items::-webkit-scrollbar-thumb { + background: #d4d4d8 !important; +} + +.orderform-template .payment-confirmation-wrap .payment-submit-wrap { + padding: 0 16px; + margin: 0 !important; + position: inherit !important; +} + +.cart-template.mini-cart .payment-confirmation-wrap .payment-submit-wrap { + padding: 0 1.5rem 1.5rem !important; +} + +@media screen and (max-width: 64rem) { + .cart-template.mini-cart .payment-confirmation-wrap .payment-submit-wrap { + max-width: 100%; + width: auto; + padding-bottom: 0 !important; + } +} + +.orderform-template .payment-confirmation-wrap #payment-data-submit { + padding: 12px 20px; + display: flex; + align-items: center; + justify-content: space-between; + border-radius: 2px; + background: #2b2b3a; + border: none; + transition: all ease .2s ease-in-out +} + +.orderform-template .payment-confirmation-wrap #payment-data-submit:hover { + background-color: #424250 +} + +.orderform-template .payment-confirmation-wrap #payment-data-submit .icon-lock { + display: none +} + +.orderform-template .payment-confirmation-wrap #payment-data-submit span { + color: var(--text-inverse-bold, #FFF); + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px +} + +.orderform-template .payment-confirmation-wrap #payment-data-submit::after { + content: url('data:image/svg+xml,'); + width: 20px; + height: 20px; + display: block +} + +.orderform-template .summary-note .note-textarea { + font-family: "Proxima Nova", sans-serif !important; +} + +.orderform-template .custom-cart-template-wrap { + border-radius: 2px !important; + border: 1px solid var(--border-neutral-subtlest, #E4E4E7) !important; + padding: 0; +} + +.orderform-template .custom-cart-template-wrap h2[data-i18n="totalizers.summary"] { + color: #18181b; + font-size: 0; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + margin: 0; + margin-bottom: 12px; + padding: 0 24px !important +} + +.orderform-template .custom-cart-template-wrap .summary-cart-template-holder { + padding: 0 24px; +} + +.orderform-template .custom-cart-template-wrap .summary-cart-template-holder .cart .cart-items::before, +.orderform-template .custom-cart-template-wrap .summary-cart-template-holder .cart .cart-items::after { + display: none +} + +.orderform-template .custom-cart-template-wrap .summary-template-holder { + margin-top: 0 +} + +#app-container .CardForm { + display: flex; + flex-wrap: wrap +} + +#app-container .CardForm p { + margin-bottom: 0 +} + +#app-container .CardForm .PaymentCardFlags { + order: -1; + width: 100% +} + +#app-container .CardForm .PaymentInstallments+div { + order: 2; + max-width: 304px; + width: 100% +} + +#app-container .CardForm>div { + width: 100%; + display: flex; + flex-direction: column +} + +#app-container .CardForm>div .PaymentLabel { + width: 100% +} + +#app-container .CardForm>div:nth-child(1):not(.PaymentLabel) { + width: 100%; + order: 1 +} + +#app-container .CardForm>div.PaymentInstallments { + order: 5; + width: 100% +} + +#app-container .CardForm>div.PaymentInstallments label { + display: block +} + +#app-container .CardForm>div.PaymentInstallments select { + max-width: 100% +} + +#app-container .CardForm>div.BillingAddress { + order: 6; + width: 100% +} + +@media screen and (min-width: 64rem) { + #payment-data .box-step .box-step-content .form-step { + margin-bottom: 2rem; + } +} + +@media screen and (max-width: 64rem) { + #app-container .CardForm>div.BillingAddress { + margin: 0; + } + + .ChangeNumberOfPayments { + margin-top: 2rem; + } + + .BillingAddress .payment-billing-address-postalCode.input-small { + margin-bottom: 0.5rem !important; + } +} + +#app-container .CardForm>div.BillingAddress #address-toggle-0 { + opacity: 0; + margin-left: -1.25rem; +} + +#app-container .CardForm>div.BillingAddress label { + color: var(--text-neutral-bold, #18181B); + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.14px; +} + +#app-container .CardForm>div.BillingAddress label strong { + font-weight: 400 +} + +#app-container .CardForm>div.BillingAddress label::after { + content: "Alterar"; + color: #FF5A00; + font-family: "Proxima Nova"; + font-size: 0.875rem; + font-style: normal; + font-weight: 500; + line-height: 1.25rem; + letter-spacing: -0.00875rem; + padding-left: 1.5rem; +} + +/* #app-container .CardForm>div:nth-child(3):not(.PaymentInstallments) { + order: 2; + max-width: 304px; + width: 100% +} */ + +@media screen and (max-width: 659px) { + #app-container .CardForm>div { + max-width: 100% !important + } +} + +#app-container .CardForm .PaymentCardValue { + order: 4; + display: flex; + flex-direction: column; + margin-left: 32px; +} + +#app-container .CardForm .PaymentCardValue .input-prepend { + max-height: 40px; + margin-bottom: 24px +} + +#app-container .CardForm .PaymentCardValue .input-prepend input { + margin-bottom: 0 +} + +#app-container .CardForm select { + font-size: 16px; + font-weight: 400; + line-height: 24px; + letter-spacing: -0.16px; + height: 48px; + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + background-image: url('data:image/svg+xml,'); + background-repeat: no-repeat; + background-position: right 16px center; + box-shadow: none; +} + +#app-container .CardForm select option { + color: #3F3F46; + font-family: "Proxima Nova"; + font-size: 0.875rem; + font-style: normal; + font-weight: 500; + line-height: 1.25rem; + letter-spacing: -0.00875rem; + padding: 0.625rem 0.75rem !important; + display: flex; + width: 100%; + align-items: center; + justify-content: space-between; + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; +} + +/* #app-container .CardForm select option:hover, +#app-container .CardForm select option:checked { + color: #FF5A00 !important; +} */ + +#app-container .CardForm select option:checked::after { + content: url('data:image/svg+xml,'); + font-size: 14px; +} + +#app-container .CardForm .PaymentCardCVV { + order: 3; + display: flex; + flex-direction: column; + justify-content: flex-end; + padding-bottom: 4px +} + + + +#app-container .CardForm .PaymentCardDueDate { + margin-right: 32px; +} + +#app-container .CardForm .PaymentCardCVV input { + min-width: 17.125rem; +} + +@media screen and (max-width: 48rem) { + + #app-container .CardForm .PaymentCardCVV label, + #app-container .CardForm .PaymentCardCVV input#creditCardpayment-card-0Code, + #app-container .CardForm .PaymentCardCVV input#creditCardpayment-card-1Code { + margin-left: 0 !important; + } +} + + + +@media screen and (max-width: 659px) { + #app-container .CardForm .PaymentCardCVV { + width: 100% + } +} + +#app-container .CardForm .PaymentCardHolderDocument { + order: 4; + width: 100%; + max-width: 274px +} + +#app-container .CardForm .PaymentCardDueDate { + display: flex; + flex-wrap: wrap +} + +#app-container .CardForm .PaymentCardDueDate .FormFieldLabel { + width: 100% +} + +#app-container .CardForm .PaymentCardDueDate .payment-card-lash { + display: none +} + +#app-container .CardForm .PaymentCardDueDate p { + max-width: 128px; + width: 100%; + margin-right: 16px +} + +#app-container .CardForm .PaymentCardDueDate p:last-child { + margin-right: 0 +} + +@media screen and (max-width: 659px) { + #app-container .CardForm .PaymentCardDueDate p { + max-width: 100%; + width: 48.06% + } +} + +@media screen and (max-width: 483px) { + #app-container .CardForm .PaymentCardDueDate p { + width: 47.06% + } +} + +#app-container .ChangeNumberOfPayments a { + color: #FF5A00 !important; + font-size: 0.875rem; + font-style: normal; + font-weight: 500; + line-height: 1.25rem; + letter-spacing: -0.00875rem +} + +.DontKnowPostalCode a { + color: #FF5A00 !important; +} + +#app-container .ChangeNumberOfPayments a:hover { + color: #FF5A00 !important; + text-decoration: underline; +} + +#app-container .PaymentCardFlags { + margin-bottom: 24px +} + +#app-container .PaymentCardFlags .card-flags { + display: none; +} + +#app-container .PaymentCardFlags .card-flag { + width: 40px; + height: 28px; + margin: 0; + box-sizing: border-box; + background-repeat: no-repeat; + transition: all .2s ease-in-out; + opacity: 1; + border: 1px solid rgba(0, 0, 0, 0); + background-position: left; + border-radius: var(--radius-rounded, 4px) +} + +#app-container .PaymentCardFlags .card-flag:hover { + border: 1px solid var(--border-selected-base, #EE8146) +} + +#app-container .PaymentCardFlags .card-flag-label input { + display: none +} + +#app-container .PaymentCardFlags .card-flag-label { + width: auto +} + +#app-container .PaymentCardFlags .card-flag.card-selected { + border: 1px solid var(--border-selected-base, #EE8146) +} + +#app-container .label-vertical-group:hover { + color: #fdf2ec !important; +} + +#app-container .label-vertical-group.active { + color: #fdf2ec !important; +} + +#app-container label.FormFieldLabel { + color: var(--text-neutral-subtle, #3F3F46); + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + margin-bottom: 8px +} + +#app-container input, +#app-container select { + border-radius: var(--radius-rounded-sm, 2px); + border: 1px solid var(--border-input-base, #D4D4D8); + background: var(--bg-neutral-subtlest-base, #FFF); + color: var(--text-neutral-bold, #18181B); + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + margin-bottom: 24px; + padding: 12px 16px +} + +#app-container input { + max-width: 274px +} + +@media screen and (max-width: 659px) { + #app-container input { + max-width: 100% + } +} + +#app-container select { + max-width: 128px +} + +@media screen and (max-width: 659px) { + #app-container select { + max-width: 100% + } +} + +.summary-coupon fieldset.coupon-fieldset .vcustom-showCustomMsgCoupon { + border-radius: 2px !important; +} + +.v-custom-addLabels-active-flag { + display: none !important; + border-radius: 2px !important; + border: 1px solid #d4d4d8 !important; +} + +.v-custom-assemblies { + border-top: 1px solid #d4d4d8 !important; +} + +.pac-container.pac-logo { + border: 1px solid #d4d4d8 !important; + border-radius: 2px !important; +} + +/* Novas estilizações */ +.checkout-container .row-fluid.orderform-template.active { + justify-items: center; +} + + +body .cart-template.full-cart>* { + opacity: initial !important; +} + +.cart-template-holder { + width: 74.52%!important; + max-width: 930px; +} + +@media screen and (max-width: 1070px) { + .cart-template-holder { + width: 100%!important; + max-width: 100%; + } +} + + +.summary-template-holder { + padding: 0 !important; + background: transparent !important; +} + +.cart-template.full-cart.active { + margin-top: 3.5rem; + justify-content: center !important; + flex-wrap: nowrap!important; +} + + +.cart-template-holder { + grid-area: 1 / 1 / 3 / 3; +} + +.summary-template-holder { + grid-area: 1 / 3 / 2 / 4; + position: inherit !important; +} + +@media screen and (min-width: 1024px) { + /* .cart-template.full-cart.active { + margin-top: 5.5rem; + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: repeat(2, 1fr); + column-gap: 1.5rem; + row-gap: 0; + } */ + + .summary-template-holder { + transform: translateY(-20px); + } + + .clearfix.cart-links.cart-links-bottom { + padding-top: 0; + } + +} + +.clearfix.cart-links.cart-links-bottom { + grid-area: 2 / 3 / 3 / 4; + margin: 0 !important +} + +.table.cart-items tbody tr.product-item { + width: 100%; + display: flex; + align-items: center; + position: relative; + box-sizing: border-box; +} + +@media screen and (min-width: 1024px) { + .table.cart-items tbody tr.product-item { + flex-wrap: nowrap; + } +} + +.cart-template-holder .cart::before { + content: 'Carrinho'; + position: absolute; + top: -3rem; + left: 0px; + color: var(--text-neutral-bold, #18181B); + text-align: center; + font-family: "Proxima Nova"; + font-size: 1.5rem; + font-style: normal; + font-weight: 500; + line-height: 2rem; + letter-spacing: -0.015rem; +} + +@media screen and (max-width: 1024px) { + .cart-template-holder .cart { + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px; + padding: 0; + background: transparent; + margin: 0 !important; + } + + .cart-template-holder .cart::before { + content: "Meu carrinho"; + color: var(--text-neutral-bold, #18181B); + text-align: center; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; /* 150% */ + letter-spacing: -0.16px; + } +} + +span.btn-place-order-wrapper, +span.link-choose-more-products-wrapper { + width: 100%; + padding: 0 1.5rem; + box-sizing: border-box; +} + +span.link-choose-more-products-wrapper .link-choose-more-products { + border-radius: var(--radius-rounded-sm, 0.125rem); + border: 1.25px solid var(--border-neutral-subtle, #D4D4D8); + background: #FFF; + color: var(--text-neutral-subtle, #3F3F46) !important; + font-size: 0; + font-style: normal; + font-weight: 500; + line-height: 1.5rem; + letter-spacing: -0.01rem; + transition: all 0.3s ease-in-out; +} + +span.link-choose-more-products-wrapper .link-choose-more-products:hover { + color: #FF5A00 !important; + text-decoration: none !important; + border: 1.25px solid #EE8146; + background: #FDF2EC; + +} + +span.link-choose-more-products-wrapper .link-choose-more-products::before { + content: 'Voltar e continuar comprando'; + font-size: 1rem; +} + +.orderform-template-holder #client-profile-data.client-profile-data form.client-pre-email.client-pre-email { + display: none !important; +} + +.step.client-profile-data.active .accordion-inner .box-step .form-step[style*="display: block"] { + padding: 0 !important; +} + +body .client-profile-data .accordion-toggle>span:before { + content: "1"; +} + +body .shipping-data .accordion-toggle:before { + content: "2"; +} + +body .payment-data .accordion-toggle>span:not(.payment-edit-link):before { + content: "3"; +} + +body .client-profile-data .accordion-toggle>span:before, +body .payment-data .accordion-toggle>span:not(.payment-edit-link):before, +body .shipping-data .accordion-toggle:before, +body .client-profile-data .accordion-toggle>span:before, +body .client-pre-email h3.client-pre-email-h span:before, +body .client-pre-email h3.client-pre-email-h span:before, +body .client-pre-email h3.client-pre-email-h span:before, +body .client-profile-data .accordion-toggle>span:before, +body .shipping-data .accordion-toggle:before, +body .client-pre-email h3.client-pre-email-h span:before, +body .client-profile-data .accordion-toggle>span:before, +body .client-pre-email h3.client-pre-email-h span:before { + background: #EE8146 !important; + color: #FFF !important; +} + +.orderform-template-holder #client-profile-data form.client-pre-email .accordion-toggle.collapsed:not(.accordion-toggle-active)::before, +.orderform-template-holder #client-profile-data .step.client-profile-data .accordion-toggle.collapsed:not(.accordion-toggle-active)::before, +.orderform-template-holder #shipping-data .accordion-toggle.collapsed:not(.accordion-toggle-active)::before, +.orderform-template-holder #payment-data .accordion-toggle.collapsed:not(.accordion-toggle-active)::before { + background: var(--bg-accent-brand-primary-subtlest, #FBE5D8) !important; + color: #EE8146 !important; +} + +.checkout-steps__item-icon svg { + overflow: visible; +} + +.orderform-template .cart-template.mini-cart .summary-template-holder input#cart-coupon[type=text], +.orderform-template .cart-template.mini-cart .summary-template-holder button#cart-coupon-add[type=submit] { + height: 40px !important; + box-shadow: none; +} + +.orderform-template .cart-template.mini-cart .cart .cart-items:not(.v-loaded) { + padding: 0; + max-height: 192px; + overflow: hidden; + overflow-y: scroll !important; +} + +.orderform-template .cart-template.mini-cart .cart::-webkit-scrollbar { + width: 4px; +} + +.orderform-template .cart-template.mini-cart .cart::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0); +} + +.orderform-template .cart-template.mini-cart .cart::-webkit-scrollbar-thumb { + background: #d4d4d8; + border-radius: 9999px; +} + +.orderform-template .cart-template.mini-cart .cart .cart-items:not(.v-loaded) li.item { + border-bottom: 1px solid var(--border-neutral-subtlest, #E4E4E7) !important; +} + +.orderform-template .cart-template.mini-cart .cart .cart-items:not(.v-loaded) li.item>* { + opacity: 1 !important; +} + +.orderform-template .cart-template.mini-cart .cart .cart-items:not(.v-loaded) li.item:after { + display: none !important; +} + +.mini-cart .summary-cart-template-holder { + overflow: hidden !important; +} + +@media screen and (max-width: 1024px) { + .orderform-template .cart-template.mini-cart .summary-template-holder { + padding-bottom: 12px !important; + } + + .orderform-template .cart-template.mini-cart .summary-totalizers { + margin-bottom: 16px !important; + } + + .orderform-template-holder .step .form-step fieldset p { + max-width: 100%; + margin-right: 0; + } + +} + +.btn-go-to-payment-wrapper .custom-button { + display: flex !important; + color: #FFF !important; + padding: 0.75rem 1rem 0.75rem 1.25rem; + justify-content: center; + align-items: center; + gap: 0.5rem; + border-radius: 0.125rem; + background: #2B2B3A; + + font-size: 1rem; + font-weight: 500; + line-height: 1.5rem; + letter-spacing: -0.01rem; + border: none; +} + +@media screen and (min-width: 64rem) { + .btn-go-to-payment-wrapper .custom-button { + background: #000; + transition: all 0.3s ease-in-out; + } + + .btn-go-to-payment-wrapper .custom-button { + background: #2B2B3A; + } +} + +.coupon.summary-coupon.hideElement .coupon-form .coupon-fieldset .coupon-fields, +.coupon.summary-coupon.hideElement .coupon-form .coupon-fieldset .vcustom-showCustomMsgCoupon, +.coupon.summary-coupon.hideElement .coupon-form .coupon-fieldset::after { + display: none !important; +} + +.summary-totalizers tbody { + display: flex; + flex-direction: column; +} + +.summary-totalizers .Items .monetary { + display: flex !important; + flex-direction: column; + justify-content: flex-end; +} + +.summary-totalizers .Items .monetary .subtotalCardValue { + color: #18181B; + font-size: 0.75rem; + font-style: normal; + font-weight: 600; + line-height: 1rem; + letter-spacing: -0.0075rem; + margin: 0 !important; +} + +.summary-totalizers .Items .monetary .valueText { + color: #71717A; + font-family: "Proxima Nova"; + font-size: 0.75rem; + font-style: normal; + font-weight: 500; + line-height: 1rem; + letter-spacing: -0.0075rem; +} + +#client-profile-data .accordion-body { + border-top: 1px solid #E4E4E7 !important; +} + +#shipping-data .accordion-toggle.collapsed.accordion-toggle-active, +#payment-data .accordion-toggle.collapsed.accordion-toggle-active { + margin-top: 1rem; + border-bottom: 1px solid #E4E4E7 !important; +} + +.orderform-template-holder .step.client-profile-data .box-info[data-bind="fadeVisible: visitedAndNotActive"] { + padding-bottom: 1.5rem; +} + +.summary-template-holder .summary-totalizers .cart-more-options { + display: flex !important; +} + +.summary-template-holder .summary-coupon p.coupon-fields::after { + content: 'Use apenas 1 código por pedido'; + width: 100%; + display: block; + text-align: left; + padding-top: 1rem; + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; + color: #71717A; +} + +.SavedCardsList { + display: flex; + flex-direction: column; + gap: 8px; +} + + +.SavedCardsList .SavedCard { + border: 1px solid var(--border-neutral-subtlest, #E4E4E7); + background: #fff; + padding: 12px; + border-radius: 0!important; + box-shadow: none!important; + +} + +.SavedCardsList .SavedCard.active { + border-color:var(--border-selected-base, #EE8146); + background: var(--bg-selected-subtle-base, #FDF2EC)!important; +} + +.SavedCardsList .SavedCard .card-label { + color: var(--text-neutral-bold, #18181B); + font-family: "Proxima Nova"; + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; + letter-spacing: -0.12px; +} + +.UseAnotherCard { + background-color: #fff!important; + border: none!important; + box-shadow: none!important; +} diff --git a/checkout-ui-settings/checkout-ui-custom/checkout6-custom.js b/checkout-ui-settings/checkout-ui-custom/checkout6-custom.js new file mode 100644 index 00000000..88c93b67 --- /dev/null +++ b/checkout-ui-settings/checkout-ui-custom/checkout6-custom.js @@ -0,0 +1,686 @@ +let isPostalCodeBeingValidated = false + +const getVtexAddress = async (postalCode) => { + try { + const response = await fetch(`/api/checkout/pub/postal-code/BRA/${postalCode}`) + + if (!response.ok) throw new Error('Erro ao buscar endereço na VTEX') + + const address = await response.json() + + if (address.city === '') { + throw new Error('Endereço não encontrado') + } + + return address + } catch (error) { + // console.error('Error getting VTEX address', error) + + return null + } +} + +function debounce(func, wait) { + let timeout + return function (...args) { + clearTimeout(timeout) + timeout = setTimeout(() => func.apply(this, args), wait) + } +} + +const getAddressByViaCep = async (postalCode) => { + try { + const response = await fetch(`https://viacep.com.br/ws/${postalCode.replace('-', '')}/json/`) + + if (!response.ok) throw new Error('Erro ao buscar endereço no ViaCep') + + return await response.json() + } catch (error) { + console.error('Error getting ViaCep address', error) + + return { erro: true } + } +} +async function isOnPostalCodeRange(postalCode) { + return await validateRangePostalCode(postalCode) +} + +async function validateRangePostalCode(postalCode) { + try { + const response = await fetch(`/api/dataentities/CR/search?isActive=true&_fields=FinalRange,initialRange`) + + if (!response.ok) throw new Error('Erro ao buscar intervalos de CEP na VTEX') + const addressRanges = await response.json() + + const isWithinRange = addressRanges.some((range) => { + const initialRange = parseInt(range.initialRange, 10) + const finalRange = parseInt(range.FinalRange, 10) + const code = parseInt(postalCode.replace('-', ''), 10) + + return code >= initialRange && code <= finalRange + }) + + return isWithinRange + } catch (error) { + console.error('Error getting VTEX address', error) + + return false + } +} + +function updateBreadcrumb() { + const currentURL = window.location.href + const { orderForm } = vtexjs.checkout + const { items } = orderForm + + if (items.length === 0) { + const stepElement = document.querySelector('.checkout-steps') + + if (stepElement) { + stepElement.style.display = 'none' + } + + return + } + + const updateClasses = (selectors, addClasses = [], removeClasses = []) => { + selectors.forEach((selector) => { + const elements = document.querySelectorAll(selector) + + elements.forEach((element) => { + addClasses.forEach((cls) => element.classList.add(cls)) + removeClasses.forEach((cls) => element.classList.remove(cls)) + }) + }) + } + + const step = currentURL.split('/').pop() + const stepsConfig = { + cart: { + active: ['.checkout-steps__item[step="cart"]'], + inactive: [ + '.checkout-steps__item[step="profile"]', + '.checkout-steps__item[step="shipping"]', + '.checkout-steps__item[step="payment"]', + ], + }, + email: { + active: ['.checkout-steps__item[step="profile"]'], + completed: ['.checkout-steps__item[step="cart"]'], + uncompleted: ['.checkout-steps__item[step="shipping"]', '.checkout-steps__item[step="payment"]'], + inactive: [ + '.checkout-steps__item[step="shipping"]', + '.checkout-steps__item[step="payment"]', + '.checkout-steps__item[step="cart"]', + ], + }, + profile: { + active: ['.checkout-steps__item[step="profile"]'], + completed: ['.checkout-steps__item[step="cart"]'], + uncompleted: ['.checkout-steps__item[step="shipping"]', '.checkout-steps__item[step="payment"]'], + inactive: [ + '.checkout-steps__item[step="shipping"]', + '.checkout-steps__item[step="payment"]', + '.checkout-steps__item[step="cart"]', + ], + }, + shipping: { + active: ['.checkout-steps__item[step="profile"]', '.checkout-steps__item[step="shipping"]'], + completed: ['.checkout-steps__item[step="cart"]', '.checkout-steps__item[step="profile"]'], + inactive: ['.checkout-steps__item[step="payment"]'], + }, + payment: { + active: [ + '.checkout-steps__item[step="profile"]', + '.checkout-steps__item[step="shipping"]', + '.checkout-steps__item[step="payment"]', + ], + completed: [ + '.checkout-steps__item[step="cart"]', + '.checkout-steps__item[step="profile"]', + '.checkout-steps__item[step="shipping"]', + ], + }, + confirmation: { + active: [ + '.checkout-steps__item[step="profile"]', + '.checkout-steps__item[step="shipping"]', + '.checkout-steps__item[step="payment"]', + ], + completed: [ + '.checkout-steps__item[step="cart"]', + '.checkout-steps__item[step="profile"]', + '.checkout-steps__item[step="shipping"]', + '.checkout-steps__item[step="payment"]', + ], + }, + } + + const config = stepsConfig[step] || {} + + updateClasses(config.active || [], ['active'], ['completed']) + updateClasses(config.completed || [], ['completed']) + updateClasses(config.uncompleted || [], [], ['completed']) + updateClasses(config.inactive || [], [], ['active']) +} + +function showDeliveryOptions() { + const { hash } = window.location + if (hash !== '#/cart') return + + const observer = new MutationObserver((mutations, obs) => { + const shippingCalculator = $('.cart-template .cart-template-holder .cart-more-options') + const targetContainer = document.querySelector('.cart-template.full-cart.active .summary-totalizers') + const alreadyAppended = !!targetContainer?.querySelector('.cart-more-options') + + if (shippingCalculator.length && !alreadyAppended) { + setTimeout(() => { + shippingCalculator.appendTo(targetContainer) + buildShippingBar() + buildShippingOptions() + debouncedValidatePostalCode() + }, 1000) + } + }) + + const config = { + childList: true, + subtree: true, + } + + observer.observe(document.body, config) +} + +function buildShippingOptions() { + const observer = new MutationObserver((mutations, obs) => { + const deliverySelect = document.querySelector('.srp-delivery-select') + + if (deliverySelect) { + if (document.querySelector('.radio-options-container')) { + obs.disconnect() + + return + } + + const options = deliverySelect.querySelectorAll('option') + + const radioContainer = document.createElement('div') + + radioContainer.classList.add('radio-options-container') + + function updateSelect(value) { + deliverySelect.querySelector(`option[value="${value}"]`).parentNode.click() + + deliverySelect.value = value + deliverySelect.dispatchEvent(new CustomEvent('change', { bubbles: true })) + } + + function extractText(optionText) { + const parts = optionText.split(' - ') + const text = parts[0] + const price = parts[1] || '' + + return { text, price } + } + + options.forEach((option) => { + const { text, price } = extractText(option.textContent) + + const labelHtml = ` + + ` + + radioContainer.innerHTML += labelHtml + }) + + radioContainer.querySelectorAll('input[type="radio"]').forEach((radio) => { + radio.addEventListener('change', function (evt) { + updateSelect(radio.value) + + document + .querySelectorAll('.vtex-omnishipping-1-x-leanShippingOption') + .forEach((label) => label.classList.remove('shp-lean-option-active')) + + radio.closest('.vtex-omnishipping-1-x-leanShippingOption').classList.add('shp-lean-option-active') + }) + + if (radio.value === deliverySelect.value) { + radio.checked = true + radio.closest('.vtex-omnishipping-1-x-leanShippingOption').classList.add('shp-lean-option-active') + } + }) + + deliverySelect.parentNode.insertBefore(radioContainer, deliverySelect) + + obs.disconnect() + } + }) + + const config = { + childList: true, + subtree: true, + } + + observer.observe(document.body, config) +} + +function updateShippingBar() { + const minValue = 200 + const orderForm = vtexjs.checkout.orderForm + const itemsValue = orderForm.totalizers.find(({ id }) => id === 'Items')?.value || 0 + const differenceToMinValue = (itemsValue - minValue * 100) / 100 + const progressPercentage = Math.min(100, (itemsValue / (minValue * 100)) * 100) + const textWrapperElement = document.querySelector('.shipping-bar-wrapper .shipping-bar-text') + if (!textWrapperElement) return + const textContentElement = textWrapperElement.querySelector('p') + const valueElement = textContentElement?.querySelector('.value') + const fullBarTextElement = textWrapperElement.querySelector('.value-reached') + const progressBarElement = document.querySelector('.shipping-bar-progress') + + if (differenceToMinValue < 0) { + if (valueElement) valueElement.textContent = `R$ ${Math.abs(differenceToMinValue).toFixed(2)}` + if (progressBarElement) progressBarElement.style.width = `${progressPercentage}%` + fullBarTextElement.style.display = 'none' + textContentElement.style.display = 'block' + } else { + fullBarTextElement.style.display = 'block' + textContentElement.style.display = 'none' + if (progressBarElement) progressBarElement.style.width = '100%' + } +} + +function buildShippingBar() { + const { hash } = window.location + + if (hash !== '#/cart') return null + const shippingBarElement = $('.shipping-bar-wrapper') + const alreadyAppended = !!document.querySelector('.cart-more-options .shipping-bar-wrapper') + + if (alreadyAppended) return + + shippingBarElement.appendTo('.cart-template.active .summary-totalizers .cart-more-options') + updateShippingBar() +} + +function configurePostalCodeInput(postalCodeInput) { + postalCodeInput.setAttribute('maxlength', '9') + + const formatPostalCode = () => { + let value = postalCodeInput.value + + value = value.replace(/\D/g, '') + + value = value.slice(0, 8) + + if (value.length > 5) { + value = value.replace(/(\d{5})(\d{1,3})/, '$1-$2') + } + + postalCodeInput.value = value + } + + + postalCodeInput.addEventListener('keyup', formatPostalCode) +} + +function validatePostalCode() { + const { hash } = window.location + + if (hash === '#/shipping' || hash === '#/cart') { + async function handlePostalCodeChange(postalCode) { + if (isPostalCodeBeingValidated) return + isPostalCodeBeingValidated = true + + try { + removeExistingErrors() + await handleVtexAddress(postalCode) + } catch (error) { + console.error('Erro ao validar o código postal:', error) + } finally { + isPostalCodeBeingValidated = false + } + } + + async function initObserver(postalCodeInput) { + const observer = new MutationObserver(async (mutationsList) => { + for (const mutation of mutationsList) { + const formattedValue = postalCodeInput.value.replace(/\D/g, '') + if (mutation.type === 'attributes' && mutation.attributeName === 'value' && formattedValue.length >= 8) { + await handlePostalCodeChange(postalCodeInput.value) + observer.disconnect() + } + } + }) + + observer.observe(postalCodeInput, { + attributes: true, + attributeFilter: ['value'], + }) + } + + function waitForPostalCodeInput() { + const postalCodeInput = document.getElementById('ship-postalCode') + + if (postalCodeInput) { + configurePostalCodeInput(postalCodeInput) + initObserver(postalCodeInput) + } else { + setTimeout(waitForPostalCodeInput, 500) + } + } + + waitForPostalCodeInput() + } +} + +function displayError() { + const { hash } = window.location + removeExistingErrors() + + const shippingContainer = + hash === '#/cart' ? document.querySelector('.cart-template') : document.getElementById('shipping-data') + + if (!shippingContainer) return + + shippingContainer.classList.add('postal-code-error') + shippingContainer.classList.remove('visible') + + if (hash === '#/cart') { + const elementExist = setInterval(() => { + const resetPostalCodeButton = document.querySelector('#deliver-at-text .srp-address-title') + if (resetPostalCodeButton) { + clearInterval(elementExist) + resetPostalCodeButton.click() + } + }, 1000) + } +} + +function removeExistingErrors() { + const errorClass = document.querySelector('.postal-code-error') + if (errorClass) { + errorClass.classList.remove('postal-code-error') + } +} + +// TODO: MELHORAR LÓGICA DESTA FUNÇÃO +async function handleVtexAddress(postalCode) { + const existOnVtex = await getVtexAddress(postalCode) + + if (existOnVtex === null) { + const addressViaCep = await getAddressByViaCep(postalCode) + const isOnRange = await isOnPostalCodeRange(postalCode) + + if (!addressViaCep.erro) { + fillAddressForm(addressViaCep) + showShippingStep() + removeExistingErrors() + } else if (!isOnRange) { + displayError() + } else { + showShippingStep() + removeExistingErrors() + } + } else { + removeExistingErrors() + } +} + +function fillAddressForm(address) { + const { bairro, logradouro, localidade, uf } = address + const streetInput = document.getElementById('ship-street') + const neighborhoodInput = document.getElementById('ship-neighborhood') + const cityInput = document.getElementById('ship-city') + const stateSelect = document.getElementById('ship-state') + + if (streetInput && neighborhoodInput && cityInput && stateSelect) { + streetInput.value = logradouro || '' + neighborhoodInput.value = bairro || '' + cityInput.value = localidade || '' + stateSelect.value = uf || '' + } +} + +function showShippingStep() { + const { hash } = window.location + + const shippingContainer = + hash === '#/cart' ? document.querySelector('.cart-template') : document.getElementById('shipping-data') + + shippingContainer.classList.remove('postal-code-error') + shippingContainer.classList.add('visible') +} + +function handleCouponSuccess() { + if (!window.vtexjs) return + const { vtexjs = {} } = window + const { checkout = {} } = vtexjs + const { orderForm = {} } = checkout + const { marketingData = {} } = orderForm + const { totalizers = [] } = orderForm + const cartTemplateGroup = document.querySelectorAll('.cart-template') + const existDiscount = totalizers.find((item) => item.id.toLowerCase() === 'discounts') + + if (marketingData && marketingData.coupon && existDiscount) { + return cartTemplateGroup.forEach((el) => { + el.classList.add('valid-coupon') + }) + } + + const vtexCustomMsgCouponEl = document.querySelector('.vcustom-showCustomMsgCoupon') + + if (marketingData && marketingData.coupon && vtexCustomMsgCouponEl) { + return cartTemplateGroup.forEach((el) => { + el.classList.add('coupon-not-applicable') + }) + } + + return cartTemplateGroup.forEach((el) => { + el.classList.remove('valid-coupon') + el.classList.remove('coupon-not-applicable') + }) +} + +function settingCupomToggle() { + const couponTitleArray = document.querySelectorAll('.coupon-form .coupon-fieldset .coupon-label') + const couponElementArray = document.querySelectorAll('.coupon.summary-coupon') + + function toggleFieldsDisplay() { + couponElementArray.forEach((field) => { + if (field.classList.contains('hideElement')) { + field.classList.remove('hideElement') + } else { + field.classList.add('hideElement') + } + }) + } + + couponTitleArray.forEach((title) => { + title.addEventListener('click', toggleFieldsDisplay) + }) +} + +function addingPixPriceIntoSummaryTotalizers() { + const priceWithDiscountsElement = document.querySelector('.summary-totalizers tfoot tr td.monetary') + const subtotalElements = document.querySelectorAll('.summary-totalizers .Items .monetary') + + if (priceWithDiscountsElement) { + const pixPriceElement = document.querySelector('.valueOfSubtotal') + + if (pixPriceElement) return + + const { items, totalizers } = vtexjs.checkout.orderForm + const totalWithoudDiscount = totalizers.find((item) => item.id === 'Items').value + const pricePixInfos = items.reduce((acc, item) => acc + item.sellingPrice, 0) + const priceCreditFormatted = (totalWithoudDiscount / 100).toLocaleString('pt-BR', { + style: 'currency', + currency: 'BRL', + }) + const pricePixFormatted = (pricePixInfos / 100).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' }) + + if (totalWithoudDiscount === pricePixInfos) return + + subtotalElements.forEach((element) => { + element.innerHTML = ` + ${pricePixFormatted} + no pix ou boleto +

${priceCreditFormatted} no cartão

+ + ` + }) + } +} + +function checkProductPrice() { + const { items } = vtexjs?.checkout?.orderForm + const products = [...document.querySelectorAll('.cart-template .cart-template-holder .product-item')] + + products?.map((product, index) => { + const item = items[index] + const hasPixPrice = item.sellingPrice !== item.price + const alreadyAppended = !!product.querySelector('.hide-pix-price') + + if (!hasPixPrice && !alreadyAppended) { + product.classList.add('hide-pix-price') + } else if (hasPixPrice && alreadyAppended) { + product.classList.remove('hide-pix-price') + } + }) +} + +function checkSharedCart() { + const {hash} = window.location + + if ( hash !== '#/payment') return null + + const inStoreParams = new URLSearchParams(window.location.search) + const orderId = inStoreParams.get('orderFormId') + const code = inStoreParams.get('code') + + const isSharedCart = orderId && code + + if (isSharedCart) { + document.querySelector("body")?.classList?.add('shared-cart') + + setDefaultPayment() + } + +} + +function setDefaultPayment() { + const element = document.querySelector('#payment-group-PagalevePixAVistaTransparentePaymentGroup') + + if (element) { + element?.click() + } +} + +function observeElement(nodeElement, action) { + const { hash } = window.location + if (hash !== '#/cart') return + + const targetNode = document.querySelector('body') + + if (!targetNode) { + return + } + + const config = { childList: true, subtree: true } + + const callback = function (mutationsList, observer) { + for (let mutation of mutationsList) { + if (mutation.type === 'childList') { + const elements = nodeElement + if (elements) { + action() + observer.disconnect() + break + } + } + } + } + + const observer = new MutationObserver(callback) + observer.observe(targetNode, config) +} + +async function checkPostalCodeOnLoad() { + console.log('checkPostalCodeOnLoad') + const { hash } = window.location + + if (hash !== '#/cart') return null + + const { postalCode } = vtexjs.checkout.orderForm.shippingData.selectedAddresses[0] ?? {} + + if (postalCode) { + await handleVtexAddress(postalCode) + } +} + +const debouncedValidatePostalCode = debounce(validatePostalCode, 300) + + +$(window).on('load', async function () { + showDeliveryOptions() + checkSharedCart() + observeElement(document.querySelectorAll('.cart-template .cart-template-holder .product-item'), checkProductPrice) + observeElement( + document.querySelector('.summary-totalizers tfoot tr td.monetary'), + addingPixPriceIntoSummaryTotalizers + ) + await checkPostalCodeOnLoad() + setTimeout(() => { + updateBreadcrumb() + settingCupomToggle() + }, 2000) +}) + +$(window).on('hashchange', async function () { + updateBreadcrumb() + checkSharedCart() + observeElement(document.querySelectorAll('.cart-template .cart-template-holder .product-item'), checkProductPrice) + observeElement( + document.querySelector('.summary-totalizers tfoot tr td.monetary'), + addingPixPriceIntoSummaryTotalizers + ) + + setTimeout(() => { + settingCupomToggle() + }, 1000) + + const { orderForm } = vtexjs.checkout + + if (orderForm) { + debouncedValidatePostalCode() + await checkPostalCodeOnLoad() + } +}) + +$(window).on('orderFormUpdated.vtex', function (evt, orderForm) { + debouncedValidatePostalCode() + handleCouponSuccess() + showDeliveryOptions() + observeElement(document.querySelectorAll('.cart-template .cart-template-holder .product-item'), checkProductPrice) + observeElement( + document.querySelector('.summary-totalizers tfoot tr td.monetary'), + addingPixPriceIntoSummaryTotalizers + ) + setTimeout(() => { + settingCupomToggle() + showDeliveryOptions() + addingPixPriceIntoSummaryTotalizers() + }, 1000) +}) + +window.addEventListener('DOMContentLoaded', () => { + window.vtexjs.checkout.getOrderForm() +}) diff --git a/checkout-ui-settings/docs/README.md b/checkout-ui-settings/docs/README.md new file mode 100644 index 00000000..5f7b1054 --- /dev/null +++ b/checkout-ui-settings/docs/README.md @@ -0,0 +1,28 @@ +# Checkout UI Settings + +The Checkout UI Settings app is responsible for **customizing your store's Checkout UI through scripts**. + +The main advantage of using the app instead of the [store's admin](https://help.vtex.com/tutorial/configure-template-in-smartcheckout-update--ToTE5XB39t0SwtHgpgwSv?locale=en) for this customization is that your Checkout scripts will behave as configurations for platform apps. + +In practice, it means that Checkout UI Settings allows A/B testing in your store's scripts, in addition to the possibility of quick rollbacks for old scripts (i.e. scripts pertaining to older Checkout UI Settings app's versions). + +## Configuration + +1. Using your terminal and the [VTEX IO Toolbelt](https://vtex.io/docs/recipes/development/vtex-io-cli-installment-and-command-reference), log into the desired account; +2. Run `vtex list` to access the list of apps that are already installed on the account you're working on. If the Checkout UI Settings option already exists, you can skip to step 7 of this step-by-step; +3. If the Checkout UI Settings app was not found in the list of installed apps, run the `vtex init` command; +4. Select the `checkout-ui-settings` option; +5. Open the `checkout-ui-settings` app in whichever code editor you prefer; +6. In the `manifest.json` file, change the predefined default value `vendor` to the name of the account in which you want to install the app; +7. In the `checkout-ui-custom` folder, create the files in which the scripts will be included, just as you would do in the [admin's interface](https://help.vtex.com/tutorial/configure-template-in-smartcheckout-update--ToTE5XB39t0SwtHgpgwSv?locale=en#configure-code). Notice that a few defaults files already exist in the `checkout-ui-custom` folder, files which you can use to insert the scripts; +8. According to the Checkout customization you are looking for, open the most suitable file and insert the desired scripts; +9. Save your changes. Then, [publish](https://vtex.io/docs/recipes/development/publishing-an-app) the app's new version; +10. Still logged into the desired account, [create a production workspace](https://vtex.io/docs/recipes/development/creating-a-production-workspace) and [install the app](https://vtex.io/docs/recipes/development/installing-an-app); +10. If everything is working as expected, [promote the workspace to master](https://vtex.io/docs/recipes/development/promoting-a-workspace-to-master). + +## Modus Operandi + +Once the app is deployed and installed in the account, every scripts contained in it will be automatically linked to your store and used to [build the templates](https://help.vtex.com/tutorial/configure-template-in-smartcheckout-update--ToTE5XB39t0SwtHgpgwSv?locale=en#configuring-templates-from-the-code-menu) to customize your Checkout. + + +:warning: **Scripts used by Checkout are linked to the Checkout UI Settings version that's installed in your store**. If a prior app version was already installed and your want to change the scripts linked to it, you'll need to repeat the already existing code and thereafter launch the app's new version containing the changes you just did. Housekeeper is responsible for updating app versions in the accounts it's installed in. diff --git a/checkout-ui-settings/lint.sh b/checkout-ui-settings/lint.sh new file mode 100644 index 00000000..cae4ddb0 --- /dev/null +++ b/checkout-ui-settings/lint.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +yarn +yarn format +yarn lint diff --git a/checkout-ui-settings/manifest.json b/checkout-ui-settings/manifest.json new file mode 100644 index 00000000..ee7a9490 --- /dev/null +++ b/checkout-ui-settings/manifest.json @@ -0,0 +1,16 @@ +{ + "name": "checkout-ui-settings", + "vendor": "roland", + "version": "0.1.0", + "title": "Checkout UI Settings", + "description": "Declare custom settings to be used by checkout ui", + "builders": { + "docs": "0.x", + "checkout-ui-custom": "0.x" + }, + "scripts": { + "prereleasy": "bash lint.sh" + }, + "credentialType": "absolute", + "$schema": "https://raw.githubusercontent.com/vtex/node-vtex-api/master/gen/manifest.schema" +} diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 00000000..70daf51a --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,107 @@ +const gulp = require('gulp'), + concat = require('gulp-concat'), + path = require('path'), + glob = require('glob') + +const sass = require('gulp-sass')(require('sass')) + +// @TODO: melhorar a organização +/** + ___ _ __ _ ___ + / __| |_ ___ _ _ ___ / _|_ _ ___ _ _| |_ / __| __ _ ______ + \__ \ _/ _ \ '_/ -_) _| '_/ _ \ ' \ _| \__ \/ _` (_-<_-< + |___/\__\___/_| \___|_| |_| \___/_||_\__| |___/\__,_/__/__/ + + */ +// Custom sass para o storefront +const pathsStore = { + styles: { + styles: 'styles/sass/**/', + ext: 'styles/sass/**/*.{css,scss,sass}', + dest: 'styles/css', + }, +} + +// Quick/efficient way to get the unique values from a array. +function uniqValuesArray(a) { + var seen = {} + var out = [] + var len = a.length + var j = 0 + for (var i = 0; i < len; i++) { + var item = a[i] + if (seen[item] !== 1) { + seen[item] = 1 + out[j++] = item + } + } + return out +} +function getCurrentTimestamp() { + const date = new Date() + + const hours = String(date.getHours()).padStart(2, '0') + const minutes = String(date.getMinutes()).padStart(2, '0') + const seconds = String(date.getSeconds()).padStart(2, '0') + + return `\x1b[35m[${hours}:${minutes}:${seconds}]\x1b[0m` +} + +let filteredFiles = [] + +gulp.task('getFiles', function (done) { + glob(pathsStore.styles.ext, function (er, files) { + filteredFiles = uniqValuesArray([ + ...files.map((file) => path.basename(file)), + ]) + done() + }) +}) + +gulp.task('sass', function (done) { + filteredFiles.forEach((file) => { + const fileName = file + + gulp + .src([ + 'styles/sass/utils/_mixin.scss', + 'styles/sass/utils/_vars.scss', + pathsStore.styles.styles + fileName, + ]) + .pipe(concat(fileName)) + .pipe(sass().on('error', sass.logError)) + .pipe(gulp.dest(pathsStore.styles.dest)) + }) + done() +}) + +gulp.task('run', gulp.series('getFiles', 'sass')) + +gulp.task('watch', function () { + gulp.watch(pathsStore.styles.ext).on('change', function (fileName) { + fileName = path.basename(fileName) + + if (fileName.includes('.css')) { + gulp + .src(pathsStore.styles.styles + fileName) + .pipe(concat(fileName)) + .pipe(gulp.dest(pathsStore.styles.dest)) + } else { + gulp + .src([ + 'styles/sass/utils/_mixin.scss', + 'styles/sass/utils/_vars.scss', + pathsStore.styles.styles + fileName, + ]) + .pipe(concat(fileName)) + .pipe(sass().on('error', sass.logError)) + .pipe(gulp.dest(pathsStore.styles.dest)) + } + + console.log( + getCurrentTimestamp() + ' File: \x1b[32m' + fileName + '\x1b[0m builded.' + ) + }) +}) + +gulp.task('build', gulp.series('run', 'watch')) diff --git a/manifest.json b/manifest.json index 78cd80e4..140b998b 100644 --- a/manifest.json +++ b/manifest.json @@ -1,11 +1,13 @@ { - "vendor": "vtex", - "name": "minimumtheme", - "version": "0.1.1", + "vendor": "roland", + "name": "store-theme", + "version": "1.0.32", "builders": { "styles": "2.x", "store": "0.x", - "docs": "0.x" + "docs": "0.x", + "assets": "0.x", + "react": "3.x" }, "scripts": { "postreleasy": "vtex publish --verbose" @@ -19,6 +21,8 @@ "vtex.styleguide": "9.x", "vtex.slider": "0.x", "vtex.carousel": "2.x", + "vtex.device-detector": "0.x", + "vtex.order-manager": "0.x", "vtex.shelf": "1.x", "vtex.menu": "2.x", "vtex.minicart": "2.x", @@ -44,7 +48,36 @@ "vtex.iframe": "0.x", "vtex.breadcrumb": "1.x", "vtex.sticky-layout": "0.x", - "vtex.add-to-cart-button": "0.x" + "vtex.add-to-cart-button": "0.x", + "vtex.list-context": "0.x", + "vtex.info-card-list": "0.x", + "vtex.store-link": "0.x", + "vtex.search": "2.x", + "vtex.product-price": "1.x", + "vtex.product-list-context": "0.x", + "vtex.product-list": "0.x", + "vtex.store-icons": "0.x", + "vtex.checkout-summary": "0.x", + "vtex.format-currency": "0.x", + "vtex.search-graphql": "0.x", + "vtex.product-context": "0.x", + "vtex.store-graphql": "2.x", + "vtex.store-image": "0.x", + "vtex.pixel-manager": "1.x", + "vtex.store-newsletter": "1.x", + "vtex.native-types": "0.x", + "vtex.disclosure-layout": "1.x", + "vtex.checkout-graphql": "0.x", + "vtex.modal-layout": "0.x", + "vtex.condition-layout": "2.x", + "vtex.product-highlights": "2.x", + "vtex.catalog-graphql": "1.x", + "roland.buy-together": "0.x" + }, + "peerDependencies": { + "vtex.wish-list": "1.x", + "vtex.wordpress-integration": "2.x", + "vtex.availability-notify": "1.x" }, "$schema": "https://raw.githubusercontent.com/vtex/node-vtex-api/master/gen/manifest.schema" } diff --git a/package.json b/package.json new file mode 100644 index 00000000..729c7a4a --- /dev/null +++ b/package.json @@ -0,0 +1,53 @@ +{ + "name": "roland-store", + "private": true, + "license": "UNLICENSED", + "scripts": { + "lint": "eslint --ext js,jsx,ts,tsx .", + "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json}\"", + "build": "gulp build" + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "*.{ts,js,tsx,jsx}": [ + "eslint --fix", + "prettier --write" + ], + "*.{json,graphql,gql}": [ + "prettier --write" + ] + }, + "devDependencies": { + "@types/node": "^12.12.21", + "@vtex/prettier-config": "^0.3.6", + "babel-eslint": "^10.1.0", + "commitizen": "^4.2.4", + "eslint": "^7.16.0", + "eslint-config-vtex": "^12.9.3", + "eslint-config-vtex-react": "^6.7.0", + "gulp": "^4.0.2", + "gulp-clean-css": "^4.3.0", + "gulp-concat": "^2.6.1", + "gulp-sass": "^5.1.0", + "gulp-wait": "0.0.2", + "husky": "^4.3.6", + "lint-staged": "^10.5.3", + "prettier": "^2.2.1", + "sass": "^1.53.0", + "typescript": "^3.7.5" + }, + "dependencies": { + "classnames": "^2.5.1", + "date-fns": "^2.29.3", + "formik": "^2.2.9", + "react-input-mask": "^2.0.4", + "react-markdown": "^8.0.3", + "react-slick": "^0.29.0", + "yup": "^1.0.0" + }, + "version": "0.0.0" +} diff --git a/pull_request_template.md b/pull_request_template.md new file mode 100644 index 00000000..d7c72a52 --- /dev/null +++ b/pull_request_template.md @@ -0,0 +1,26 @@ +#### What is the type of problem? + +- [ ] Fix +- [ ] Feature +- [ ] Release +- [ ] Docs + +#### What problem is being solved? + +Footer had broken social networks, with this fix you can see the improvement. + +#### Briefly explain where to validate: + +[WorkSpace](https://liz.myvtex.com) + +#### Screenshot: + +![Image](https://picsum.photos/300/100) + +#### Vídeo + + + +#### Task + +[Task]() diff --git a/react/.eslintrc b/react/.eslintrc new file mode 100644 index 00000000..5f820fe3 --- /dev/null +++ b/react/.eslintrc @@ -0,0 +1,9 @@ +{ + "extends": "vtex-react/io", + "rules": { + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/no-explicit-any": "off", + "import/order": "off", + "no-console": "off" + } +} diff --git a/react/AnchorSections.ts b/react/AnchorSections.ts new file mode 100644 index 00000000..06f7771c --- /dev/null +++ b/react/AnchorSections.ts @@ -0,0 +1,3 @@ +import AnchorSections from './components/product/AnchorSections' + +export default AnchorSections diff --git a/react/BlogPosts.ts b/react/BlogPosts.ts new file mode 100644 index 00000000..693e06b8 --- /dev/null +++ b/react/BlogPosts.ts @@ -0,0 +1,3 @@ +import BlogPosts from './components/blog-posts' + +export default BlogPosts diff --git a/react/BuyButtonPopupContent.ts b/react/BuyButtonPopupContent.ts new file mode 100644 index 00000000..cf8bb2fe --- /dev/null +++ b/react/BuyButtonPopupContent.ts @@ -0,0 +1,3 @@ +import BuyButtonPopupContent from './components/product/buy-button-popup-content' + +export default BuyButtonPopupContent diff --git a/react/ChallengeSellerChannel.tsx b/react/ChallengeSellerChannel.tsx new file mode 100644 index 00000000..1fd25066 --- /dev/null +++ b/react/ChallengeSellerChannel.tsx @@ -0,0 +1,177 @@ +import type { ReactNode } from 'react' +import React, { Fragment, useEffect, useMemo, useState } from 'react' + +// Components +import PreOwnedPopupAlert from './PreOwnedPopupAlert' + +// Hooks +import { useQuery } from 'react-apollo' +// @ts-ignore +import { useRuntime } from 'vtex.render-runtime' + +// Queries +import GET_ORDERFORM from './graphql/queries/getOrderForm.gql' +import GET_PRE_OWNED_PRODUCTS from './graphql/queries/getProductsFromCollection.gql' + +const ChallengeSellerChannel = ({ children }: { children: ReactNode }) => { + const [showPopupAlert, setShowPopupAlert] = useState(false) + const { data, loading: orderFormLoading } = useQuery(GET_ORDERFORM, { + ssr: false, + }) + + const { data: preOwnedProducts, loading: productsLoading } = useQuery( + GET_PRE_OWNED_PRODUCTS, + { + variables: { id: '169' }, + ssr: false, + } + ) + + const { page, route } = useRuntime() + + const orderFormItems = useMemo( + () => data?.orderForm.items ?? [], + [data?.orderForm.items] + ) + + const preOwnedItems = useMemo( + () => preOwnedProducts?.productsOrder.items ?? [], + [preOwnedProducts?.productsOrder.items] + ) + + const hasPreOwnedProductInCart = orderFormItems.some((orderItem: any) => + preOwnedItems.some( + (preOwnedItem: any) => preOwnedItem.skuId === orderItem.id + ) + ) + + const disableElements = (elements: string[]) => { + elements.forEach((element) => { + const elementToDisable = document.querySelector(element) as HTMLElement + + if (elementToDisable) { + elementToDisable.style.display = 'none' + } + }) + } + + useEffect(() => { + if (orderFormLoading || productsLoading || !preOwnedItems?.length) { + return + } + + const isPreOwnedPage = page === 'store.custom#pre-owned' + const isHomePage = page === 'store.home' + const isProductPage = page === 'store.product' + const isPreOwnedProduct = document.referrer.includes('seminovos') + + const currentUrl = new URL(window.location.href) + const hasScParameter = currentUrl.searchParams.has('sc') + const hasRefreshed = currentUrl.searchParams.has('refreshed') + + if (isProductPage && isPreOwnedProduct && !hasScParameter) { + currentUrl.searchParams.set('sc', '2') + window.location.href = currentUrl.toString() + + const elementsToDisable = [ + '.roland-store-theme-1-x-menuContainer', + '.vtex-breadcrumb-1-x-container', + ] + + disableElements(elementsToDisable) + + return + } + + if (isProductPage && (isPreOwnedProduct || hasScParameter)) { + const elementsToDisable = [ + '.roland-store-theme-1-x-menuContainer', + '.vtex-breadcrumb-1-x-container', + ] + + disableElements(elementsToDisable) + + return + } + + if (isProductPage && !isPreOwnedProduct && !hasScParameter) { + const elementsToDisable = [ + '.vtex-flex-layout-0-x-flexRow--pre-owned-tab', + '.vtex-flex-layout-0-x-flexRow--breadcrumb--pre-owned', + ] + + const preOwnedClass = document.querySelector( + '.vtex-flex-layout-0-x-flexRow--pre-owned' + ) as HTMLElement + + preOwnedClass?.classList.add( + 'vtex-flex-layout-0-x-flexRow--pre-owned-product' + ) + + disableElements(elementsToDisable) + + return + } + + if (isPreOwnedPage && !hasScParameter) { + currentUrl.searchParams.set('sc', '2') + currentUrl.searchParams.set('refreshed', 'true') + window.location.href = currentUrl.toString() + + return + } + + if (isPreOwnedPage && !hasRefreshed) { + currentUrl.searchParams.set('refreshed', 'true') + window.location.href = currentUrl.toString() + + return + } + + if (orderFormItems.length > 0) { + if (isPreOwnedPage && !hasPreOwnedProductInCart) { + setShowPopupAlert(true) + } + + if (!isPreOwnedPage && hasPreOwnedProductInCart) { + setShowPopupAlert(true) + } + } else { + setShowPopupAlert(false) + } + + if (isHomePage && !hasScParameter) { + currentUrl.searchParams.set('sc', '1') + window.location.href = currentUrl.toString() + } + }, [ + data, + preOwnedProducts, + page, + hasPreOwnedProductInCart, + orderFormItems, + preOwnedItems, + showPopupAlert, + orderFormLoading, + productsLoading, + route.params.id, + ]) + + return ( + + {children} + {showPopupAlert && ( + + )} + + ) +} + +export default React.memo(ChallengeSellerChannel) diff --git a/react/CollapsibleContent.ts b/react/CollapsibleContent.ts new file mode 100644 index 00000000..47e64d71 --- /dev/null +++ b/react/CollapsibleContent.ts @@ -0,0 +1,3 @@ +import CollapsibleContent from './components/CollapsibleContent' + +export default CollapsibleContent diff --git a/react/Countdown.ts b/react/Countdown.ts new file mode 100644 index 00000000..1c9ccde3 --- /dev/null +++ b/react/Countdown.ts @@ -0,0 +1,3 @@ +import Countdown from './components/countdown' + +export default Countdown diff --git a/react/CustomBanner.ts b/react/CustomBanner.ts new file mode 100644 index 00000000..aea1b1d1 --- /dev/null +++ b/react/CustomBanner.ts @@ -0,0 +1,3 @@ +import CustomBanner from './components/CustomBanner' + +export default CustomBanner diff --git a/react/CustomFlagDiscount.ts b/react/CustomFlagDiscount.ts new file mode 100644 index 00000000..fbc51b66 --- /dev/null +++ b/react/CustomFlagDiscount.ts @@ -0,0 +1,3 @@ +import CustomFlagDiscount from "./components/CustomFlagDiscount"; + +export default CustomFlagDiscount \ No newline at end of file diff --git a/react/CustomInfoCard.ts b/react/CustomInfoCard.ts new file mode 100644 index 00000000..79322c44 --- /dev/null +++ b/react/CustomInfoCard.ts @@ -0,0 +1,3 @@ +import CustomInfoCard from './components/custom-infocard' + +export default CustomInfoCard diff --git a/react/DisclosureList.ts b/react/DisclosureList.ts new file mode 100644 index 00000000..dadcbe1b --- /dev/null +++ b/react/DisclosureList.ts @@ -0,0 +1,3 @@ +import DisclosureList from './components/DisclosureList' + +export default DisclosureList diff --git a/react/DisplayCondition.tsx b/react/DisplayCondition.tsx new file mode 100644 index 00000000..6ee81dad --- /dev/null +++ b/react/DisplayCondition.tsx @@ -0,0 +1,3 @@ +import DisplayCondition from './components/DisplayCondition' + +export default DisplayCondition diff --git a/react/FloatingAppearanceController.ts b/react/FloatingAppearanceController.ts new file mode 100644 index 00000000..5d93bba5 --- /dev/null +++ b/react/FloatingAppearanceController.ts @@ -0,0 +1,3 @@ +import FloatingAppearanceController from './components/FloatingAppearanceController' + +export default FloatingAppearanceController diff --git a/react/GlobalStyles.ts b/react/GlobalStyles.ts new file mode 100644 index 00000000..aeedce16 --- /dev/null +++ b/react/GlobalStyles.ts @@ -0,0 +1,3 @@ +import GlobalStyles from './components/GlobalStyles' + +export default GlobalStyles diff --git a/react/HandleAddToCartPixelEvent.ts b/react/HandleAddToCartPixelEvent.ts new file mode 100644 index 00000000..9701c354 --- /dev/null +++ b/react/HandleAddToCartPixelEvent.ts @@ -0,0 +1,3 @@ +import HandleAddToCartPixelEvent from './components/HandleAddToCartPixelEvent' + +export default HandleAddToCartPixelEvent diff --git a/react/ImageSlider.ts b/react/ImageSlider.ts new file mode 100644 index 00000000..864a37cd --- /dev/null +++ b/react/ImageSlider.ts @@ -0,0 +1,3 @@ +import ImageSlider from './components/product/image-slider' + +export default ImageSlider diff --git a/react/Menu.ts b/react/Menu.ts new file mode 100644 index 00000000..a5bc1926 --- /dev/null +++ b/react/Menu.ts @@ -0,0 +1,3 @@ +import Menu from './components/Menu' + +export default Menu diff --git a/react/MinicartCustomPrice.ts b/react/MinicartCustomPrice.ts new file mode 100644 index 00000000..55c36739 --- /dev/null +++ b/react/MinicartCustomPrice.ts @@ -0,0 +1,3 @@ +import MinicartCustomPrice from './components/MinicartCustomPrice' + +export default MinicartCustomPrice diff --git a/react/MinicartSummary.ts b/react/MinicartSummary.ts new file mode 100644 index 00000000..2e231271 --- /dev/null +++ b/react/MinicartSummary.ts @@ -0,0 +1,3 @@ +import MinicartSummary from "./components/MinicartSummary"; + +export default MinicartSummary; \ No newline at end of file diff --git a/react/PreOwnedCartFlag.ts b/react/PreOwnedCartFlag.ts new file mode 100644 index 00000000..56f2b5e6 --- /dev/null +++ b/react/PreOwnedCartFlag.ts @@ -0,0 +1,3 @@ +import PreOwnedCartFlag from './components/PreOwnedCartFlag' + +export default PreOwnedCartFlag diff --git a/react/PreOwnedPopupAlert.ts b/react/PreOwnedPopupAlert.ts new file mode 100644 index 00000000..bfa5583e --- /dev/null +++ b/react/PreOwnedPopupAlert.ts @@ -0,0 +1,3 @@ +import PreOwnedPopupAlert from './components/PreOwnedPopupAlert' + +export default PreOwnedPopupAlert diff --git a/react/PreOwnedSectionCondition.ts b/react/PreOwnedSectionCondition.ts new file mode 100644 index 00000000..c3de7dbe --- /dev/null +++ b/react/PreOwnedSectionCondition.ts @@ -0,0 +1,3 @@ +import PreOwnedSectionCondition from './components/PreOwnedSectionCondition' + +export default PreOwnedSectionCondition diff --git a/react/PricePerCommercialPolicy.ts b/react/PricePerCommercialPolicy.ts new file mode 100644 index 00000000..f3b5b68d --- /dev/null +++ b/react/PricePerCommercialPolicy.ts @@ -0,0 +1,3 @@ +import PricePerCommercialPolicy from './components/PricePerCommercialPolicy' + +export default PricePerCommercialPolicy diff --git a/react/ProductContentItems.ts b/react/ProductContentItems.ts new file mode 100644 index 00000000..e894f8d6 --- /dev/null +++ b/react/ProductContentItems.ts @@ -0,0 +1,3 @@ +import ProductContentItems from './components/product/ProductContentItems' + +export default ProductContentItems diff --git a/react/ProductDescriptionCustom.ts b/react/ProductDescriptionCustom.ts new file mode 100644 index 00000000..75807ecc --- /dev/null +++ b/react/ProductDescriptionCustom.ts @@ -0,0 +1,3 @@ +import ProductDescriptionCustom from './components/product/ProductDescriptionCustom' + +export default ProductDescriptionCustom diff --git a/react/ProductInstructionManual.ts b/react/ProductInstructionManual.ts new file mode 100644 index 00000000..96e7f17f --- /dev/null +++ b/react/ProductInstructionManual.ts @@ -0,0 +1,3 @@ +import ProductInstructionManual from './components/product/ProductInstructionManual' + +export default ProductInstructionManual diff --git a/react/ProductLinkShare.ts b/react/ProductLinkShare.ts new file mode 100644 index 00000000..567c9262 --- /dev/null +++ b/react/ProductLinkShare.ts @@ -0,0 +1,3 @@ +import ProductLinkShare from './components/product/ProductLinkShare' + +export default ProductLinkShare diff --git a/react/ProductReadMoreDescription.ts b/react/ProductReadMoreDescription.ts new file mode 100644 index 00000000..1f28ce3d --- /dev/null +++ b/react/ProductReadMoreDescription.ts @@ -0,0 +1,3 @@ +import ProductReadMoreDescription from './components/product/ProductReadMoreDescription' + +export default ProductReadMoreDescription diff --git a/react/ProductTechnicalSpecifications.ts b/react/ProductTechnicalSpecifications.ts new file mode 100644 index 00000000..d580cb29 --- /dev/null +++ b/react/ProductTechnicalSpecifications.ts @@ -0,0 +1,3 @@ +import ProductTechnicalSpecifications from './components/product/ProductTechnicalSpecifications' + +export default ProductTechnicalSpecifications diff --git a/react/ProductTrustvoxAvaliations.ts b/react/ProductTrustvoxAvaliations.ts new file mode 100644 index 00000000..0e7a3fbe --- /dev/null +++ b/react/ProductTrustvoxAvaliations.ts @@ -0,0 +1,3 @@ +import ProductTrustvoxAvaliations from './components/product/ProductTrustvoxAvaliations' + +export default ProductTrustvoxAvaliations diff --git a/react/ProductVideo.ts b/react/ProductVideo.ts new file mode 100644 index 00000000..94152f35 --- /dev/null +++ b/react/ProductVideo.ts @@ -0,0 +1,3 @@ +import ProductVideo from './components/product/ProductVideo' + +export default ProductVideo diff --git a/react/SalesChannelriggerCondition.ts b/react/SalesChannelriggerCondition.ts new file mode 100644 index 00000000..3a84aa1b --- /dev/null +++ b/react/SalesChannelriggerCondition.ts @@ -0,0 +1,3 @@ +import SalesChannelConditionTrigger from './components/SalesChannelConditionTrigger' + +export default SalesChannelConditionTrigger diff --git a/react/ShippingBar.ts b/react/ShippingBar.ts new file mode 100644 index 00000000..22c9abce --- /dev/null +++ b/react/ShippingBar.ts @@ -0,0 +1,3 @@ +import ShippingBar from "./components/ShippingBar"; + +export default ShippingBar; diff --git a/react/ShippingCalculator.ts b/react/ShippingCalculator.ts new file mode 100644 index 00000000..95f8ed69 --- /dev/null +++ b/react/ShippingCalculator.ts @@ -0,0 +1,3 @@ +import ShippingCalculator from './components/shipping-calculator' + +export default ShippingCalculator diff --git a/react/Topbar.ts b/react/Topbar.ts new file mode 100644 index 00000000..4934036e --- /dev/null +++ b/react/Topbar.ts @@ -0,0 +1,3 @@ +import Topbar from './components/Topbar' + +export default Topbar diff --git a/react/TrustVoxStars.ts b/react/TrustVoxStars.ts new file mode 100644 index 00000000..99cd12a9 --- /dev/null +++ b/react/TrustVoxStars.ts @@ -0,0 +1,3 @@ +import TrustVoxStars from './components/TrustVox' + +export default TrustVoxStars diff --git a/react/components/CollapsibleContent/index.tsx b/react/components/CollapsibleContent/index.tsx new file mode 100644 index 00000000..a8fe5079 --- /dev/null +++ b/react/components/CollapsibleContent/index.tsx @@ -0,0 +1,39 @@ +// Dependencies +import React, { useState } from 'react' +import classNames from 'classnames' + +// Styles +import styles from './styles.css' + +// Types +import type { ReactNode } from 'react' + +interface CollapsibleContentProps { + children: ReactNode +} + +const CollapsibleContent = ({ children }: CollapsibleContentProps) => { + const [isCollapsed, setIsCollapsed] = useState(true) + + const handleToggle = () => { + setIsCollapsed(!isCollapsed) + } + + const containerClasses = classNames(styles.collapsibleContentContainer, { + [styles.collapsibleContentContainerOpen]: isCollapsed, + }) + + return ( +
+ {children} + +
+ ) +} + +export default CollapsibleContent diff --git a/react/components/CollapsibleContent/styles.css b/react/components/CollapsibleContent/styles.css new file mode 100644 index 00000000..a532fee8 --- /dev/null +++ b/react/components/CollapsibleContent/styles.css @@ -0,0 +1,41 @@ +.collapsibleContentContainer { + max-width: 720px; + width: 100%; +} + +.collapsibleContentContainer p { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-box-orient: vertical; + max-height: fit-content; +} + +.collapsibleContentContainerOpen p { + -webkit-line-clamp: 4; + +} + +.collapsibleContentButton { + border-radius: var(--radius-rounded-sm, 2px); + border: 1.25px solid var(--border-neutral-subtle, #D4D4D8); + background: #FFF; + padding: 12px 20px; + margin-top: 24px; + color: var(--text-neutral-subtle, #3F3F46); + font-family: "Proxima Nova"; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; /* 150% */ + letter-spacing: -0.16px; + transition: all 0.2s ease-in-out; + cursor: pointer; +} + +.collapsibleContentButton:hover { + border-color: var(--border-brand-primary-base, #EE8146); + background: var(--bg-brand-primary-subtlest-hover, #FDF2EC); + color: var(--text-brand-primary-base, #FF5A00); + +} \ No newline at end of file diff --git a/react/components/CustomBanner/index.tsx b/react/components/CustomBanner/index.tsx new file mode 100644 index 00000000..2b9e57f8 --- /dev/null +++ b/react/components/CustomBanner/index.tsx @@ -0,0 +1,88 @@ +import React from 'react' +import styles from './styles.css' +import { useRuntime } from 'vtex.render-runtime' +import { SliderLayout } from 'vtex.slider-layout' +import { BANNER_SCHEMA } from './schema' + +interface BannerProps { + items: ItemProps[] + infinite: boolean +} + +interface ItemProps { + initialDate?: string + finalDate?: string + visible: boolean + image: string + imageMobile: string + itemLink?: string +} + +const CustomBanner: StorefrontFunctionComponent = ({ + items, + infinite, +}) => { + const { deviceInfo } = useRuntime() + const actualDate = Date.now() + + if (!items || items.length === 0) return null + + const configSlider: any = { + itemsPerPage: { + desktop: 1, + tablet: 1, + phone: 1, + }, + infinite, + autoplay: { + timeout: 5000, + }, + usePagination: true, + showNavigationArrows: 'never', + showPaginationDots: 'always', + } + + const filteredBanners = + items?.filter((item) => { + if (!item.visible) return false + + const initialDate = item.initialDate ? Date.parse(item.initialDate) : null + const finalDate = item.finalDate ? Date.parse(item.finalDate) : null + + if (initialDate && !finalDate) { + return actualDate >= initialDate + } + + if (initialDate && finalDate) { + return actualDate >= initialDate && actualDate < finalDate + } + + if (!initialDate && finalDate) { + return actualDate < finalDate + } + + return true + }) ?? [] + + return ( +
+ + {filteredBanners.map((item) => ( +
+ + Banner + +
+ ))} +
+
+ ) +} + +CustomBanner.schema = BANNER_SCHEMA + +export default CustomBanner diff --git a/react/components/CustomBanner/schema.ts b/react/components/CustomBanner/schema.ts new file mode 100644 index 00000000..73505ec2 --- /dev/null +++ b/react/components/CustomBanner/schema.ts @@ -0,0 +1,64 @@ +export const BANNER_SCHEMA = { + type: 'object', + properties: { + items: { + title: 'Banners', + type: 'array', + items: { + title: 'Banner', + type: 'object', + properties: { + __editorItemTitle: { + title: 'Nome do banner (para organização)', + type: 'string', + }, + visible: { + title: 'Visível', + type: 'boolean', + default: true, + }, + image: { + title: 'Imagem DESKTOP', + type: 'string', + widget: { + 'ui:widget': 'image-uploader', + }, + }, + imageMobile: { + title: 'Imagem MOBILE', + type: 'string', + widget: { + 'ui:widget': 'image-uploader', + }, + }, + itemLink: { + title: 'Link', + type: 'string', + default: '', + }, + initialDate: { + title: 'Data Inicial', + type: 'string', + widget: { + 'ui:widget': 'date-time', + }, + default: '', + }, + finalDate: { + title: 'Data Final', + type: 'string', + widget: { + 'ui:widget': 'date-time', + }, + default: '', + }, + }, + }, + }, + infinite: { + title: 'Infinite', + type: 'boolean', + default: true, + }, + }, +} diff --git a/react/components/CustomBanner/styles.css b/react/components/CustomBanner/styles.css new file mode 100644 index 00000000..a90f8a2a --- /dev/null +++ b/react/components/CustomBanner/styles.css @@ -0,0 +1,40 @@ +.bannerWrapper, +.bannerContent, +.bannerImage, +.slideChildrenContainer { + max-width: 100% !important; + max-height: 100% !important; + height: 100%; + width: 100%; + margin: 0 !important; +} + +.bannerWrapper { + padding: 0 !important; + .sliderLayoutContainer { + .paginationDotsContainer { + border-radius: 200px; + background: #fff; + display: inline-flex; + padding: 4px 8px; + justify-content: center; + align-items: center; + gap: var(--spacing-2, 8px); + width: fit-content; + margin: 0 auto; + height: 16px; + bottom: 8px; + } + + .paginationDot { + width: 6px !important; + height: 6px !important; + border-radius: 9999px !important; + background: #71717c; + } + + .paginationDot--isActive { + background: #ff5a00 !important; + } + } +} diff --git a/react/components/CustomFlagDiscount/index.tsx b/react/components/CustomFlagDiscount/index.tsx new file mode 100644 index 00000000..cf16f9fb --- /dev/null +++ b/react/components/CustomFlagDiscount/index.tsx @@ -0,0 +1,80 @@ +import React, { Fragment } from 'react' +import { useProduct } from 'vtex.product-context' + +// Types +interface CustomFlagDiscountProps { + children: React.ReactNode + flagType: string + backgroundColor: string + color: string +} + +const CustomFlagDiscount: StorefrontFunctionComponent< + CustomFlagDiscountProps +> = ({ children, flagType, backgroundColor, color }) => { + const { product } = useProduct() ?? {} + + const hasDiscount = + product?.priceRange?.listPrice.highPrice !== + product?.priceRange?.sellingPrice.highPrice + + if (!hasDiscount) { + return null + } + + const style: React.CSSProperties = { + backgroundColor, + color, + fontFamily: 'Monument Extended', + fontSize: flagType === '-n%' ? '14px' : '9px', + borderRadius: flagType === '-n%' ? '16px' : '50%', + padding: flagType === '-n%' ? '4px' : '9px 4px', + display: 'flex', + flexDirection: flagType === '-n%' ? 'row' : 'column', + position: 'absolute', + zIndex: '1', + } + + return ( +
+ + {flagType === '-n%' && -} + {children} + {flagType === 'n%off' && ( + OFF + )} + +
+ ) +} + +CustomFlagDiscount.schema = { + title: 'Tipo de flag', + type: 'object', + properties: { + flagType: { + title: 'Qual o tipo de flag?', + enum: ['-n%', 'n%off'], + enumNames: ['-50%', '50% OFF'], + default: '-n%', + }, + backgroundColor: { + title: 'Cor de fundo', + type: 'string', + widget: { + 'ui:widget': 'color', + }, + default: '#FF5A00', + }, + color: { + title: 'Cor do texto', + type: 'string', + widget: { + 'ui:widget': 'color', + }, + default: '#FFFFFF', + }, + }, +} + +export default CustomFlagDiscount diff --git a/react/components/DisclosureList/index.tsx b/react/components/DisclosureList/index.tsx new file mode 100644 index 00000000..2fd02698 --- /dev/null +++ b/react/components/DisclosureList/index.tsx @@ -0,0 +1,128 @@ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +import React, { useState } from 'react' +import marked from 'marked' +import styles from './styles.css' +import classNames from 'classnames' + +interface Question { + question: string + answer: string +} + +interface Props { + questions: Question[] +} + +const DisclosureList = ({ questions }: Props) => { + const [openIndex, setOpenIndex] = useState(null) + + const toggleAccordion = (index: number) => { + setOpenIndex(openIndex === index ? null : index) + } + + return ( +
+ {questions.map((question, index: number) => ( +
+
toggleAccordion(index)} + > +

{question.question}

+ + {openIndex === index ? ( + + + + ) : ( + + + + + )} + +
+
+
+ ))} +
+ ) +} + +DisclosureList.schema = { + title: 'Lista de Perguntas', + type: 'object', + properties: { + questions: { + title: 'Perguntas e respostas', + type: 'array', + items: { + title: 'Pergunta', + type: 'object', + properties: { + __editorItemTitle: { + title: 'Pergunta (para organização)', + type: 'string', + }, + question: { + title: 'Pergunta', + type: 'string', + }, + answer: { + title: 'Resposta', + type: 'string', + description: 'Utilize markdown para formatar o texto.', + widget: { + 'ui:widget': 'textarea', + }, + }, + }, + }, + }, + }, +} + +export default DisclosureList diff --git a/react/components/DisclosureList/styles.css b/react/components/DisclosureList/styles.css new file mode 100644 index 00000000..25d47c5d --- /dev/null +++ b/react/components/DisclosureList/styles.css @@ -0,0 +1,74 @@ +.accordtion-list-wrapper { + display: flex; + flex-direction: column; + gap: 12px; +} +.accordion { + border-radius: 2px; + background: #0E0E0E; + padding: 24px 32px; + transition: all 0.2s ease-in-out; + border: 2px solid transparent; + + +} + +.accordionHeader { + display: flex; + position: relative; +} + +.accordionHeader h3 { + color: #FFF; + font-family: "Proxima Nova"; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; /* 150% */ + letter-spacing: -0.16px; + margin: 0; + width: 90%; +} + +.accordion.active { + border-color: var(--text-brand-primary-base, #FF5A00); +} + +.accordion.active .accordionContent { + max-height: 1000px; + opacity: 1; +} + +.accordionContent { + color: #FFF; + font-family: "Proxima Nova"; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; /* 142.857% */ + letter-spacing: -0.14px; + height: fit-content; + max-height: 0; + transition: all 0.2s ease-in-out; + overflow: hidden; + opacity: 0; +} + +.icon { + position: absolute; + right: 0; + top: 0; + cursor: pointer; +} + +@media screen and (max-width: 768px) { + .accordion { + padding: 16px; + } + + .icon { + top: 50%; + transform: translateY(-50%); + } +} + diff --git a/react/components/DisplayCondition/index.tsx b/react/components/DisplayCondition/index.tsx new file mode 100644 index 00000000..b3f7a55a --- /dev/null +++ b/react/components/DisplayCondition/index.tsx @@ -0,0 +1,24 @@ +import type { ReactNode } from 'react' +import React, { Fragment } from 'react' + +type Props = { + children: ReactNode + isActive: boolean +} +const DisplayCondition = ({ children, isActive }: Props) => { + if (!isActive) return null + + return {children} +} + +DisplayCondition.schema = { + type: 'object', + properties: { + isActive: { + title: 'Está ativo?', + type: 'boolean', + }, + }, +} + +export default DisplayCondition diff --git a/react/components/FloatingAppearanceController/index.tsx b/react/components/FloatingAppearanceController/index.tsx new file mode 100644 index 00000000..3e5d1e8e --- /dev/null +++ b/react/components/FloatingAppearanceController/index.tsx @@ -0,0 +1,54 @@ +import { useLayoutEffect } from 'react' +import { useDevice } from 'vtex.device-detector' + +const FloatingAppearanceController = () => { + const { isMobile } = useDevice() + + useLayoutEffect(() => { + const options = { + root: null, + rootMargin: '0px', + threshold: 0.5, + } + + const intersectionCallback = (entries: any[]) => { + const floatingBuyBox = document.querySelector( + '.vtex-sticky-layout-0-x-wrapper--buy-button-fixed' + ) as HTMLDivElement + + entries.forEach((entry) => { + if (entry.isIntersecting) { + floatingBuyBox.style.display = 'none' + floatingBuyBox.style.opacity = '0' + } else { + if (isMobile && window.scrollY < 360) { + return + } + + floatingBuyBox.style.display = 'block' + floatingBuyBox.style.opacity = '1' + } + }) + } + + const observer = new IntersectionObserver(intersectionCallback, options) + + const buyButtonContainerElement: Element = document.querySelector( + '.vtex-flex-layout-0-x-flexRow--product-buy-button' + ) as HTMLDivElement + + if (buyButtonContainerElement) { + observer.observe(buyButtonContainerElement) + } + + return () => { + if (buyButtonContainerElement) { + observer.unobserve(buyButtonContainerElement) + } + } + }, []) + + return null +} + +export default FloatingAppearanceController diff --git a/react/components/GlobalStyles/index.tsx b/react/components/GlobalStyles/index.tsx new file mode 100644 index 00000000..cc81a244 --- /dev/null +++ b/react/components/GlobalStyles/index.tsx @@ -0,0 +1,7 @@ +import './styles.global.css' + +const GlobalStyles = () => { + return null +} + +export default GlobalStyles diff --git a/react/components/GlobalStyles/styles.global.css b/react/components/GlobalStyles/styles.global.css new file mode 100644 index 00000000..49696fac --- /dev/null +++ b/react/components/GlobalStyles/styles.global.css @@ -0,0 +1,137 @@ +.vtex-store-newsletter-1-x-confirmationCheckboxContainer + .vtex-checkbox__inner-container.bg-action-primary { + background-color: #ff5a00; + border-color: #ff5a00 !important; +} + +.vtex-order-placed-2-x-orderPaymentItem .t-body .c-muted-1.mb3 { + display: none; +} + +.render-route-store-home-black .vtex-store-header-2-x-headerStickyRow, +.render-route-store-home-black .roland-store-theme-1-x-menuContainer, +.render-route-store-home-black + .vtex-store-header-2-x-headerRowContentContainer--main-container, +.render-route-store-home-black + .vtex-store-header-2-x-headerRowContainer--main-container { + background-color: #000; +} +@media screen and (min-width: 64rem) { + .render-route-store-home-black .roland-store-theme-1-x-menuItem > a, + .render-route-store-home-black + .vtex-store-components-3-x-searchBarInnerContainer + .vtex-styleguide-9-x-input { + color: #fff !important; + } +} + +/* .render-route-store-home-black .bg-base, */ +.render-route-store-home-black + .vtex-store-header-2-x-headerRowContainer--main-container, +.render-route-store-home-black .vtex-store-components-3-x-searchBarContainer, +.render-route-store-home-black .roland-store-theme-1-x-menuContainer, +.render-route-store-home-black .vtex-flex-layout-0-x-flexRow--shelf-container, +.render-route-store-home-black + .vtex-store-header-2-x-headerStickyRow--search-container, +.render-route-store-home-black + .vtex-store-components-3-x-searchBarContainer + .vtex-styleguide-9-x-input, +.render-route-store-home-black + .vtex-store-components-3-x-searchBarContainer + .vtex-input-prefix__group + .bg-base, +.render-route-store-home-black .bg-base, +.render-route-store-home-black + .vtex-flex-layout-0-x-flexRow--back-to-top-button { + background-color: #000; +} + +.render-route-store-home-black .roland-store-theme-1-x-menuContainer { + border-bottom: none; +} +.render-route-store-home-black + .vtex-store-newsletter-1-x-newsletterForm--newsletter-form + .vtex-styleguide-9-x-input { + background-color: #fff; +} + +.render-route-store-home-black + .vtex-store-components-3-x-searchBarContainer + .vtex-store-components-3-x-searchBarIcon--search-bar { + filter: invert(1); +} + +.render-route-store-home-black + .vtex-store-newsletter-1-x-newsletterForm--newsletter-form + .vtex-styleguide-9-x-input::placeholder { + color: #000 !important; +} + +.render-route-store-home-black .vtex-styleguide-9-x-input::placeholder { + color: #fff !important; +} + +@media screen and (min-width: 768px) { + .render-route-store-home-black .roland-store-theme-1-x-menuItem span, + .render-route-store-home-black .vtex-login-2-x-label, + .render-route-store-home-black .vtex-styleguide-9-x-input::placeholder, + .render-route-store-home-black .vtex-store-link-0-x-label--wishlist { + color: #fff !important; + } +} + +.render-route-store-home-black + .vtex-flex-layout-0-x-flexRow--black-friday-shelf-offer + .vtex-flex-layout-0-x-flexRow--shelf-title-container { + display: none; +} + +.render-route-store-home-black.roland-store-theme-1-x-menuContainer { + border: none; +} + +.render-route-store-home-black .vtex-minicart-2-x-openIconContainer::before { + content: url('data:image/svg+xml,'); + position: relative; + top: 7px; +} + +.render-route-store-home-black + .vtex-minicart-2-x-openIconContainer + .vtex-store-components-3-x-imageElement { + display: none; +} + +.render-route-store-home-black.vtex-store-components-3-x-imageElement { + display: none; +} + +.render-route-store-home-black + .roland-store-theme-1-x-menuItem + > a + > span:hover { + color: #ff5a00 !important; +} + +.render-route-store-home-black .vtex-login-2-x-container .vtex-button:hover { + background-color: transparent; +} + +@media screen and (min-width: 64rem) { + .render-route-store-home-black .vtex-rich-text-0-x-paragraph br { + display: none !important; + } +} + +@media screen and (max-width: 64rem) { + /* .render-route-store-home-black .vtex-store-components-3-x-imageElement--banner-main{ + width: 100%; + height: 228px; + object-fit: cover; + object-position: -75px; + } */ + + .render-route-store-home-black .roland-store-theme-1-x-menuButton { + background-image: url('data:image/svg+xml,'); + } +} diff --git a/react/components/HandleAddToCartPixelEvent/index.tsx b/react/components/HandleAddToCartPixelEvent/index.tsx new file mode 100644 index 00000000..2506a300 --- /dev/null +++ b/react/components/HandleAddToCartPixelEvent/index.tsx @@ -0,0 +1,72 @@ +import { useRef, useEffect } from 'react' +import { usePixelEventCallback } from 'vtex.pixel-manager' + +type IntervalId = ReturnType +type TimeoutId = ReturnType + +function closeMiniCart() { + const selector = '[class^="vtex-minicart"][class*="closeIconButton"]' + + const closeButton = document.querySelector(selector) + + const event = new CustomEvent('click', { + bubbles: true, + }) + + closeButton?.dispatchEvent(event) + + return !!closeButton +} + +interface HandleAddToCartPixelEventProps { + waitTimeMS?: number + intervalMS?: number + customPixelEventId?: string +} + +type PixelConfig = Parameters[0] + +const HandleAddToCartPixelEvent: React.FC = ({ + customPixelEventId, + intervalMS = 500, + waitTimeMS = 3000, +}) => { + const timeoutId = useRef() + const intervalId = useRef() + + function sleep(time: number) { + return new Promise((resolve) => { + timeoutId.current = setTimeout(resolve, time) + }) + } + + const config: PixelConfig = { + eventId: customPixelEventId, + handler: async () => { + await sleep(waitTimeMS) + + intervalId.current = setInterval(() => { + const closed = closeMiniCart() + + if (closed && intervalId.current) { + clearInterval(intervalId.current) + } + }, intervalMS) + }, + eventName: 'addToCart', + } + + usePixelEventCallback(config) + + // Use the useEffect to clear side effects + useEffect(() => { + return () => { + timeoutId.current && clearTimeout(timeoutId.current) + intervalId.current && clearInterval(intervalId.current) + } + }, []) + + return null +} + +export default HandleAddToCartPixelEvent diff --git a/react/components/Menu/components/LoginMobile/index.tsx b/react/components/Menu/components/LoginMobile/index.tsx new file mode 100644 index 00000000..6419a442 --- /dev/null +++ b/react/components/Menu/components/LoginMobile/index.tsx @@ -0,0 +1,79 @@ +// Dependencies +import React from 'react' + +import { OrderForm } from 'vtex.order-manager' + +// Styles +import styles from './styles.css' + +// Queries +import GET_USER_PROFILE from '../../../../graphql/queries/getUserProfile.gql' +import { useQuery } from 'react-apollo' + +const { useOrderForm } = OrderForm + +const LoginMobile = () => { + const { + orderForm: { loggedIn }, + } = useOrderForm() ?? {} + + const { data } = useQuery(GET_USER_PROFILE, { ssr: false }) + + return ( +
+
+ +
+
+ ) +} + +export default LoginMobile diff --git a/react/components/Menu/components/LoginMobile/styles.css b/react/components/Menu/components/LoginMobile/styles.css new file mode 100644 index 00000000..34ade82e --- /dev/null +++ b/react/components/Menu/components/LoginMobile/styles.css @@ -0,0 +1,38 @@ +.loginMobileWrapper { +} + +.userWrapper { + width: 100%; +} + +.userWrapper ul { + display: flex; + flex-direction: column; + list-style: none; + padding: 0; + gap: 16px; + margin: 0; +} + +.userWrapper ul li { + display: flex; + align-items: center; + gap: 16px; +} + +.userWrapper ul li:first-child :where(span, a) { + font-size: 20px; + letter-spacing: -0.2px; + padding: 6px 0; +} + +.userWrapper ul li :where(span, a) { + color: var(--bg-brand-secondary-bold-base, #2b2b3a); + font-family: 'Proxima Nova'; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 20px; + text-decoration: none; + letter-spacing: -0.14px; +} diff --git a/react/components/Menu/components/MenuContent/index.tsx b/react/components/Menu/components/MenuContent/index.tsx new file mode 100644 index 00000000..ae95d5c3 --- /dev/null +++ b/react/components/Menu/components/MenuContent/index.tsx @@ -0,0 +1,228 @@ +/* eslint-disable jsx-a11y/anchor-has-content */ +/* eslint-disable @typescript-eslint/no-use-before-define */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +// Dependencies +import React, { useEffect, useState } from 'react' +import classnames from 'classnames' + +// Styles +import styles from './styles.css' + +// Hooks +import { useMenu } from '../../../../hooks/useMenu' + +// @ts-ignore +import { useDevice } from 'vtex.device-detector' + +// Types +import type { MenuDepartment } from '../../typing' +import LoginMobile from '../LoginMobile' + +interface MenuContentProps { + staticLink: any +} + +const MenuContent = ({ staticLink }: MenuContentProps) => { + const [activeDepartment, setActiveDepartment] = useState(null) + const [menuOpen, setMenuOpen] = useState(false) + const { departments } = useMenu() + const { isMobile } = useDevice() + + useEffect(() => { + const body = document.querySelector('body') as HTMLBodyElement + + if (isMobile) { + if (menuOpen) { + body.style.overflow = 'hidden' + } else { + body.style.overflow = 'unset' + } + } + }, [menuOpen, isMobile]) + + const menuClasses = classnames(styles.menuWrapper, { + [styles.open]: isMobile && menuOpen, + }) + + const handleMenuClose = () => { + setMenuOpen(false) + setActiveDepartment(null) + } + + return ( +
+ {isMobile && ( + + )} + + {hasCategories && ( +
+
+
+ {isMobile && departmentImageMobile?.src && ( + {name} + )} +
+ + + {departmentImageDesktop?.src && ( +
+ {name} +
+ )} +
+
+ )} + + ) + })} + + {isMobile && ( + + )} + {isMobile && ( + + Central de Ajuda + + )} + {!isMobile && staticLink?.active && ( + + {staticLink.name} + + )} +
+ + {(menuOpen || activeDepartment !== null) && ( +
{ + setActiveDepartment(null) + }} + /> + )} +
+ ) +} + +export default MenuContent diff --git a/react/components/Menu/components/MenuContent/styles.css b/react/components/Menu/components/MenuContent/styles.css new file mode 100644 index 00000000..543aa617 --- /dev/null +++ b/react/components/Menu/components/MenuContent/styles.css @@ -0,0 +1,506 @@ +.menuContainer { + width: 100%; + position: sticky; + top: 72px; + background: var(--Gray-Scale-White, #fff); + + z-index: 99; + border-bottom: 1px solid var(--border-neutral-subtlest, #E4E4E7); +} + +.staticDepartment { + position: absolute; + right: 32px; + bottom: 0; + color: var(--Gray-Scale-White, #FFF); + font-family: "Proxima Nova"; + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: 24px; + letter-spacing: -0.16px; + text-decoration: none; + border-radius: var(--radius-rounded-sm, 2px); + padding: 4px 8px; +} + +.stickyMenu .menuList { + gap: 16px; +} + +.stickyMenu :global(.vtex-minicart-2-x-minicartIconContainer) img { + display: none; +} + +.stickyMenu :global(.vtex-minicart-2-x-minicartIconContainer)::before { + content: url('data:image/svg+xml,'); + width: 24px; + height: 24px; + display: block; +} + + +.stickyMenu .staticDepartment { + display: none; +} + +.logo { + opacity: 0; + max-width: 0; + z-index: -1; + transition: opacity 0.1s ease-in-out; +} + +.stickyMenu .logo { + opacity: 1; + max-width: 100%; + margin-right: 16px; + height: 28px; + z-index: 1; +} + +.stickyMenu .menuItem { + padding-top: 16px; +} + +.stickyMenu .menuItem { + padding-bottom: 16px; +} + +.stickyMenu .menuWrapper { + align-items: center; +} + +.stickyMenu :global(.vtex-login-2-x-profile)::after { + display: none; +} + +.menuButton { + background: transparent; + background-image: url('data:image/svg+xml,'); + background-repeat: no-repeat; + width: 21px; + height: 21px; + border: none; +} + +.menuOverlay { + width: 100%; + height: 100vw; + background-color: rgba(0, 0, 0, 0.5); + position: absolute; + left: 0; + z-index: 5; +} + +.menuWrapper { + max-width: 1440px; + margin: 0 auto; + padding: 0 32px; + display: flex; + position: relative; +} + +.userInteractions { + display: none; + opacity: 0; + max-width: 0; + transition: opacity 0.1s ease-in-out; + justify-content: space-between; +} + +.userInteractions.sticky { + opacity: 1; + display: flex; + max-width: 100%; + align-items: center; +} + +.userInteractions :global(.vtex-store-components-3-x-searchBarContainer) { + max-width: 152px; + margin: 0 24px; +} + +.userInteractions :global(.vtex-store-link-0-x-label--wishlist) { + font-size: 0 !important; + width: 48px; +} + +.userInteractions :global(.vtex-login-2-x-profile) { + font-size: 0; + width: 48px; +} + +.userInteractions :global(.vtex-login-2-x-label) { + font-size: 0 !important; +} + +.userInteractions :global(.vtex-login-2-x-profile)::before { + content: url('data:image/svg+xml,'); + width: 20px; + height: 20px; + display: block; +} + +.closeButton { + background: transparent; + background-image: url('data:image/svg+xml,'); + border: none; + width: 20px; + height: 20px; + display: block; + padding: 0; + position: absolute; + left: 24px; + top: 24px; + z-index: 99999999999; +} + +.menuList { + display: flex; + align-items: center; + list-style: none; + padding: 0; + margin: 0; +} + +.menuItem { + padding-bottom: 8px; + padding-right: 32px; + cursor: pointer; +} + +.menuItem button:not(.hideCategory), +.menuItem>a:not(.hideCategory) { + text-decoration: none; + color: var(--Gray-Scale-Black, #000); + font-family: 'Proxima Nova'; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px; + background-color: transparent; + border: none; + cursor: pointer; + padding: 0; + display: flex; + align-items: center; + gap: 8px; +} + +.categoryWrapper { + max-height: 0; + overflow: hidden; + position: absolute; + z-index: 9; + background: #fff; + box-shadow: 0px 16px 40px 0px rgba(0, 0, 0, 0.1); + width: fit-content; + min-width: 678px; + margin-top: 8px; + opacity: 0; + transition: all 0.2s ease-in-out; +} + +.categoryWrapper.active { + max-height: 1000px; + opacity: 1; + height: fit-content; +} + +.departmentTitleWrapper { + width: 100%; + display: flex; + padding: var(--spacing-4, 16px) var(--spacing-8, 32px); + align-items: center; + gap: var(--spacing-4, 16px); + align-self: stretch; + + background: var(--bg-accent-zinc-subtlest, #f4f4f5); + justify-content: space-between; +} + +.departmentTitle { + color: var(--text-neutral-bold, #18181b); + font-family: 'Proxima Nova'; + font-size: 24px; + font-style: normal; + font-weight: 500; + line-height: 32px; + letter-spacing: -0.24px; + margin: 0; +} + +:global(.vtex-minicart-2-x-drawer):nth-child(2) { + display: none !important; +} + +.viewAllLink { + display: flex; + padding: var(--spacing-25, 10px) var(--spacing-4, 16px); + justify-content: center; + align-items: center; + gap: var(--spacing-2, 8px); + border-radius: var(--radius-rounded-sm, 2px); + background: var(--bg-brand-secondary-bold-base, #2b2b3a); + color: var(--text-inverse-bold, #fff); + font-family: 'Proxima Nova'; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + text-decoration: none; +} + +.subMenuCategoryContent { + display: flex; + padding: var(--spacing-10, 40px) var(--spacing-8, 32px); + align-items: flex-start; + gap: var(--spacing-6, 24px); +} + +.subMenuCategoryList { + list-style: none; + padding: 0; + display: flex; + flex-direction: column; + gap: 8px; + max-width: 230px; + width: 100%; +} + +.subMenuCategoryItem:last-child .subMenuCategoryLink { + color: rgba(255, 90, 0, 1); +} + +.subMenuCategoryLink { + text-decoration: none; + color: var(--text-link-secondary-default-base, #3f3f46); + font-family: 'Proxima Nova'; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + transition: color 0.2s ease-in-out; +} + +.hideCategory { + display: none; +} + +.subMenuCategoryLink:hover { + color: rgba(255, 90, 0, 1); +} + +.departmentImage { + max-width: 360px; + max-height: 246px; + width: 100%; + height: 100%; + border-radius: var(--radius-rounded-lg, 8px); +} + +.departmentImage img { + border-radius: var(--radius-rounded-lg, 8px); +} + +@media screen and (max-width: 1025px) { + .menuContainer { + width: fit-content; + border-bottom: none; + } + + .menuWrapper { + transform: translate(-100%, 0); + position: fixed; + height: 100%; + max-width: 312px; + flex-direction: column; + width: 100%; + top: 0; + left: 0; + background-color: #fff; + transition: transform 0.3s ease-in-out; + padding: 24px; + z-index: 9999; + padding-top: 60px; + justify-items: start; + } + + .menuWrapper.open { + transform: translate(0, 0); + } + + .menuList { + flex-direction: column; + align-items: flex-start; + gap: 0; + + margin-bottom: 16px; + border-bottom: 1px solid rgba(156, 160, 174, 0.4); + } + + .menuItem { + width: 100%; + padding: 8px 0; + } + + .departmentImageMobile { + border-radius: var(--radius-rounded, 4px); + background: var(--bg-brand-secondary-bold-base, #2b2b3a); + max-width: 264px; + width: 100%; + height: 54px; + margin: 12px auto 0 auto; + display: flex; + } + + .viewAllLink { + display: none; + } + + .listTitleMobile { + color: #000; + font-family: 'Proxima Nova'; + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: 24px; + letter-spacing: -0.16px; + width: 100%; + padding: 12px 0; + display: block; + margin-top: 16px; + border-top: 1px solid rgba(156, 160, 174, 0.4); + } + + .menuItem button:not(.hideCategory) .menuItem a:not(.hideCategory) { + display: flex; + align-items: center; + gap: 8px; + width: 100%; + } + + .menuItem button span, + .menuItem a span { + width: 100%; + text-align: left; + } + + /* .menuItem button:not(.hideCategory):after, + .menuItem a:not(.hideCategory):after { + content: url('data:image/svg+xml,'); + width: 16px; + height: 16px; + display: block; + } */ + + .menuItem button img, + .menuItem a img { + width: 54px; + height: 40px; + border-radius: var(--radius-rounded, 4px); + } + + .departmentTitleWrapper { + background-color: transparent; + padding: 0; + justify-content: flex-start; + align-items: center; + margin-top: 72px; + padding-left: 24px; + } + + .brandSwitcherMobile { + background-image: url('/assets/vtex.file-manager-graphql/images/6407a28d-6ab0-4982-b372-2d0ac877249f___ac7b85eac007fbb01b8a3a585bf70040.png'); + border-radius: 4px; + border: 1px solid var(--text-inverse-subtle, #d4d4d8); + width: 100%; + height: 36px; + background-repeat: no-repeat; + background-position: center; + background-color: #0064FF; + } + + .logo { + height: 0; + } + + .categoryWrapper { + transform: translate(-100%, 0); + max-height: 100%; + position: fixed; + top: 0; + left: 0; + opacity: 1; + height: 100%; + max-width: 312px; + min-width: unset; + width: 100%; + } + + .categoryWrapper.active { + transform: translate(0, 0); + height: 100%; + } + + .departmentTitle { + color: var(--icon-brand-secondary-base, #2b2b3a); + + /* text-sm/semibold */ + font-family: 'Proxima Nova'; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 20px; + /* 142.857% */ + letter-spacing: -0.14px; + padding-right: 24px; + } + + .hideCategory { + display: block; + border: none; + background-color: transparent; + background-image: url('data:image/svg+xml,'); + width: 16px; + height: 16px; + background-repeat: no-repeat; + } + + .subMenuCategoryContent { + padding: 16px 24px; + } + + .menuOverlay { + height: 100%; + position: fixed; + top: 0; + } + + .helpCenterMobile { + color: var(--icon-brand-secondary-inverse, #5A5A66); + font-family: "Proxima Nova"; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 20px; + /* 142.857% */ + letter-spacing: -0.14px; + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 16px; + + } + + .helpCenterMobile::after { + content: url('data:image/svg+xml,'); + display: block; + width: 24px; + height: 24px; + } +} \ No newline at end of file diff --git a/react/components/Menu/context/index.tsx b/react/components/Menu/context/index.tsx new file mode 100644 index 00000000..cf34eac6 --- /dev/null +++ b/react/components/Menu/context/index.tsx @@ -0,0 +1,19 @@ +// Dependencies +import React, { createContext } from 'react' + +// Types +import type { FC, ReactNode } from 'react' +import type { MenuRoot } from '../typing' + +interface MenuContextProps { + children: ReactNode + value: MenuRoot +} + +const MenuContext = createContext>({}) + +const MenuProvider: FC = ({ children, value }) => { + return {children} +} + +export { MenuContext, MenuProvider } diff --git a/react/components/Menu/index.tsx b/react/components/Menu/index.tsx new file mode 100644 index 00000000..38e72318 --- /dev/null +++ b/react/components/Menu/index.tsx @@ -0,0 +1,29 @@ +// Dependencies +import React from 'react' + +// Components +import MenuContent from './components/MenuContent' + +// Schema +import { MENU_SCHEMA } from './schema' +import { MenuProvider } from './context' + +// Types +import type { MenuRoot } from './typing' + +interface MenuProps { + departments: MenuRoot + staticLink: any +} + +const Menu = ({ departments, staticLink }: MenuProps) => { + return ( + + + + ) +} + +Menu.schema = MENU_SCHEMA + +export default Menu diff --git a/react/components/Menu/schema.ts b/react/components/Menu/schema.ts new file mode 100644 index 00000000..96f5750d --- /dev/null +++ b/react/components/Menu/schema.ts @@ -0,0 +1,118 @@ +export const MENU_SCHEMA = { + title: 'Menu Customizado', + type: 'object', + properties: { + departments: { + title: 'Departamentos', + type: 'array', + items: { + title: 'Departamento', + type: 'object', + properties: { + __editorItemTitle: { + title: 'Nome do Departamento (para organização)', + type: 'string', + }, + name: { + title: 'Nome do Departamento', + type: 'string', + }, + link: { + title: 'Link do Departamento', + type: 'string', + }, + departmentImageDesktop: { + type: 'object', + properties: { + src: { + title: 'Imagem do departamento - Desktop', + type: 'string', + widget: { + 'ui:widget': 'image-uploader', + }, + }, + }, + }, + departmentThumbImageMobile: { + type: 'object', + properties: { + src: { + title: 'Thumb do departamento - Mobile', + type: 'string', + widget: { + 'ui:widget': 'image-uploader', + }, + }, + }, + }, + departmentImageMobile: { + type: 'object', + properties: { + src: { + title: 'Imagem do departamento - Mobile', + type: 'string', + widget: { + 'ui:widget': 'image-uploader', + }, + }, + }, + }, + categories: { + title: 'Categorias', + type: 'array', + items: { + title: 'Categoria', + type: 'object', + properties: { + __editorItemTitle: { + title: 'Nome da Categoria (para organização)', + type: 'string', + }, + name: { + title: 'Nome da Categoria', + type: 'string', + }, + link: { + title: 'Link da Categoria', + type: 'string', + }, + }, + }, + }, + }, + }, + }, + staticLink: { + title: 'Link estático', + type: 'object', + properties: { + active: { + title: 'Departamento estático ativo', + type: 'boolean', + }, + name: { + title: 'Nome do Departamento', + type: 'string', + }, + link: { + title: 'Link do Departamento', + type: 'string', + }, + color: { + title: 'Cor do texto', + type: 'string', + widget: { + 'ui:widget': 'color', + }, + }, + backgroundColor: { + title: 'Cor de fundo', + type: 'string', + widget: { + 'ui:widget': 'color', + }, + }, + }, + }, + }, +} diff --git a/react/components/Menu/typing.ts b/react/components/Menu/typing.ts new file mode 100644 index 00000000..40cfdefa --- /dev/null +++ b/react/components/Menu/typing.ts @@ -0,0 +1,23 @@ +export interface MenuRoot { + departments: MenuDepartment[] +} + +export interface MenuDepartment { + departmentImageDesktop: MenuImage + departmentThumbImageMobile: MenuImage + departmentImageMobile: MenuImage + __editorItemTitle: string + name: string + link: string + categories?: MenuCategory[] +} + +export interface MenuImage { + src?: string +} + +export interface MenuCategory { + __editorItemTitle: string + name: string + link: string +} diff --git a/react/components/MinicartCustomPrice/index.tsx b/react/components/MinicartCustomPrice/index.tsx new file mode 100644 index 00000000..9a7326b4 --- /dev/null +++ b/react/components/MinicartCustomPrice/index.tsx @@ -0,0 +1,64 @@ +// Dependencies +import React, { useEffect } from 'react' + +// Styles +import styles from './styles.css' + +// Hooks +import { ItemContext } from 'vtex.product-list' +import { FormattedCurrency } from 'vtex.format-currency' +import { useLazyQuery } from 'react-apollo' + +// Query +import GET_PRODUCT_BY_ID from '../../graphql/queries/getProductById.gql' + +const { useItemContext } = ItemContext + +const MinicartCustomPrice = () => { + const [getProductById, { data, loading, error }] = + useLazyQuery(GET_PRODUCT_BY_ID) + + const { + item: { productId }, + } = useItemContext() ?? {} + + useEffect(() => { + if (productId) { + getProductById({ + variables: { identifier: { field: 'id', value: productId } }, + }) + } + }, [productId, getProductById]) + + if (loading) return
Carregando...
+ + const { + Price = 0, + ListPrice = 0, + spotPrice = 0, + } = data?.product.items?.[0].sellers?.[0].commertialOffer ?? {} + + if (!Price || !ListPrice || !spotPrice || error) return null + + const hasOldPrice = ListPrice > Price + + return ( +
+ + {hasOldPrice && } + + + no pix + + + ou{' '} + + + {' '} + no cartão + +
+ ) +} + +export default MinicartCustomPrice diff --git a/react/components/MinicartCustomPrice/styles.css b/react/components/MinicartCustomPrice/styles.css new file mode 100644 index 00000000..30bdea17 --- /dev/null +++ b/react/components/MinicartCustomPrice/styles.css @@ -0,0 +1,39 @@ +.priceWrapper { + display: flex; + flex-direction: column; +} + +.oldPrice { + overflow: hidden; + color: var(--text-neutral-subtlest, #71717A); + text-overflow: ellipsis; + font-family: "Proxima Nova"; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; /* 133.333% */ + letter-spacing: -0.12px; + text-decoration: line-through; +} + +.sellingPrice { + overflow: hidden; + color: var(--text-neutral-bold, #18181B); + text-overflow: ellipsis; + font-family: "Proxima Nova"; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 20px; /* 142.857% */ + letter-spacing: -0.14px; +} + +.price, .priceLoading { + color: var(--text-neutral-bold, #18181B); + font-family: "Proxima Nova"; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; /* 133.333% */ + letter-spacing: -0.12px; +} \ No newline at end of file diff --git a/react/components/MinicartSummary/index.tsx b/react/components/MinicartSummary/index.tsx new file mode 100644 index 00000000..8f2bb6a1 --- /dev/null +++ b/react/components/MinicartSummary/index.tsx @@ -0,0 +1,111 @@ +/* eslint-disable no-await-in-loop */ +/* eslint-disable @typescript-eslint/restrict-plus-operands */ +import React, { useEffect, useState, useCallback } from 'react' +import styles from './styles.css' + +import { OrderForm } from 'vtex.order-manager' +import { FormattedCurrency } from 'vtex.format-currency' +import { useApolloClient } from 'react-apollo' + +import GET_PRODUCT_BY_ID from '../../graphql/queries/getProductById.gql' + +const { useOrderForm } = OrderForm + +const MinicartSummary: React.FC = () => { + const client = useApolloClient() + const { + orderForm: { items }, + } = useOrderForm() + + const [spotPriceTotal, setSpotPriceTotal] = useState(0) + const [priceTotal, setPriceTotal] = useState(0) + const [listPriceTotal, setListPriceTotal] = useState(0) + + const fetchProductPricesById = useCallback( + async (productId: string) => { + const { data } = await client.query({ + query: GET_PRODUCT_BY_ID, + variables: { identifier: { field: 'id', value: productId } }, + }) + + if (data?.product?.items) { + return data.product.items.reduce( + ( + acc: { spotPrice: number; price: number; listPrice: number }, + productItem: any + ) => { + const itemSpotPrice = + productItem?.sellers?.[0]?.commertialOffer?.spotPrice ?? 0 + + const itemPrice = + productItem?.sellers?.[0]?.commertialOffer?.Price ?? 0 + + const itemListPrice = + productItem?.sellers?.[0]?.commertialOffer?.ListPrice ?? 0 + + return { + spotPrice: acc.spotPrice + itemSpotPrice, + price: acc.price + itemPrice, + listPrice: acc.listPrice + itemListPrice, + } + }, + { spotPrice: 0, price: 0, listPrice: 0 } + ) + } + + return { spotPrice: 0, price: 0, listPrice: 0 } + }, + [client] + ) + + const fetchProductsPrices = useCallback(async () => { + let totalSpotPrice = 0 + let totalPrice = 0 + let totalListPrice = 0 + + for (const item of items) { + const { spotPrice, price, listPrice } = await fetchProductPricesById( + item.productId + ) + + totalSpotPrice += spotPrice + totalPrice += price + totalListPrice += listPrice + } + + setSpotPriceTotal(totalSpotPrice) + setPriceTotal(totalPrice) + setListPriceTotal(totalListPrice) + }, [items, fetchProductPricesById]) + + useEffect(() => { + fetchProductsPrices() + }, [items, fetchProductsPrices]) + + const maxInstallments = 10 + + return ( +
+
+ Subtotal + + + + + + +
+ + no pix ou boleto +

+ ou{' '} + + + {' '} + em até {maxInstallments}x sem juros +

+
+ ) +} + +export default MinicartSummary diff --git a/react/components/MinicartSummary/styles.css b/react/components/MinicartSummary/styles.css new file mode 100644 index 00000000..73478630 --- /dev/null +++ b/react/components/MinicartSummary/styles.css @@ -0,0 +1,76 @@ +.minicartSummary { + width: 100%; +} + + +.subtotalTitle { + width: 100%; + float: left; + color: var(--text-neutral-bold, #18181B); + font-family: "Proxima Nova"; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px; +} + +.pixText { + color: var(--text-neutral-subtlest, #71717A); + text-align: right; + width: 100%; + display: block; + /* text-xs/semibold */ + font-family: "Proxima Nova"; + font-size: 12px; + font-style: normal; + font-weight: 600; + line-height: 16px; /* 133.333% */ + letter-spacing: -0.12px; + margin-bottom: 4px; +} + +.totalPrice { + color: var(--text-neutral-subtlest, #71717A); + text-align: right; + font-family: "Proxima Nova"; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 24px; + letter-spacing: -0.14px; + text-decoration: line-through; +} + +.priceWithDiscount { + color: var(--text-neutral-bold, #18181B); + text-align: right; + font-family: "Proxima Nova"; + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: 24px; /* 150% */ + letter-spacing: -0.16px; +} + + +.subtotalWrapper { + display: flex; + width: 100%; + align-items: center; + gap: 8px; +} + + + +.installments { + color: var(--text-neutral-bold, #18181B); + text-align: right; + font-family: "Proxima Nova"; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; + letter-spacing: -0.12px; + margin: 0; +} \ No newline at end of file diff --git a/react/components/PreOwnedCartFlag/index.tsx b/react/components/PreOwnedCartFlag/index.tsx new file mode 100644 index 00000000..2117054a --- /dev/null +++ b/react/components/PreOwnedCartFlag/index.tsx @@ -0,0 +1,47 @@ +// Dependencies +import React from 'react' + +// Styles +import styles from './styles.css' + +// Hooks +import { useQuery } from 'react-apollo' + +// Queries +import GET_PRE_OWNED_PRODUCTS from '../../graphql/queries/getProductsFromCollection.gql' +import GET_ORDERFORM from '../../graphql/queries/getOrderForm.gql' + +// Context +import { ItemContext } from 'vtex.product-list' + +export const useItemContext = () => { + try { + return ItemContext?.useItemContext() + } catch (error) { + return null + } +} + +const PreOwnedCartFlag = () => { + const { item } = useItemContext() ?? {} + const { data: orderForm, loading: orderFormLoading } = useQuery(GET_ORDERFORM) + + const { orderForm: { salesChannel = '1' } = {} } = orderForm ?? {} + + const { data, loading } = useQuery(GET_PRE_OWNED_PRODUCTS, { + variables: { id: '169' }, + ssr: false, + }) + + const isPreOwned = data?.productsOrder.items.some( + (preOwnedItem: any) => preOwnedItem.skuId === item?.id + ) + + if (!isPreOwned || loading || salesChannel === '1' || orderFormLoading) { + return null + } + + return
Seminovo
+} + +export default PreOwnedCartFlag diff --git a/react/components/PreOwnedCartFlag/styles.css b/react/components/PreOwnedCartFlag/styles.css new file mode 100644 index 00000000..bb362e26 --- /dev/null +++ b/react/components/PreOwnedCartFlag/styles.css @@ -0,0 +1,17 @@ +.preOwnedFlag { + border-radius: var(--radius-rounded-full, 9999px); + background: var(--text-accent-brand-subtlest, #F5C09E); + padding: 2px 8px; + overflow: hidden; + color: var(--Gray-Scale-Black, #000); + text-overflow: ellipsis; + font-family: "Proxima Nova"; + font-size: 12px; + font-style: normal; + font-weight: 600; + line-height: 16px; /* 133.333% */ + letter-spacing: -0.12px; + width: fit-content; + margin-bottom: 12px; + margin-top: -6px; +} \ No newline at end of file diff --git a/react/components/PreOwnedPopupAlert/index.tsx b/react/components/PreOwnedPopupAlert/index.tsx new file mode 100644 index 00000000..6cc7a7d2 --- /dev/null +++ b/react/components/PreOwnedPopupAlert/index.tsx @@ -0,0 +1,168 @@ +// Dependencies +import type { FC } from 'react' +import React, { useState } from 'react' + +// Styles +import styles from './styles.css' + +// Components +import { Spinner } from 'vtex.styleguide' + +// Hooks +import { OrderForm } from 'vtex.order-manager' +import { useMutation } from 'react-apollo' +import { useRuntime } from 'vtex.render-runtime' + +// Mutations +import REMOVE_ALL_PRODUCTS_MUTATION from '../../graphql/mutations/removeAllProductsFromCart.gql' + +const { useOrderForm } = OrderForm + +// Interface + +interface PreOwnedPopupAlertProps { + action: any + hasPreOwnedProductsOnCart: boolean + modalIsOpen?: boolean + orderFormId?: string + orderFormItems?: any + isChallenge?: boolean +} + +const PreOwnedPopupAlert: FC = ({ + action = null, + hasPreOwnedProductsOnCart = false, + modalIsOpen, + orderFormId, + orderFormItems, + isChallenge, +}) => { + const { orderForm } = useOrderForm() + const runtime = useRuntime() + const [isModalOpen, setIsModalOpen] = useState( + modalIsOpen ?? orderForm.items.length > 0 + ) + + const [isLoading, setIsLoading] = useState(false) + + const items = orderFormItems ?? orderForm.items + + const [removeAllProductsFromCart] = useMutation(REMOVE_ALL_PRODUCTS_MUTATION) + const handleDecline = () => { + if (isChallenge) { + if (runtime.page === 'store.home' && hasPreOwnedProductsOnCart) { + window.location.href = '/seminovos?sc=2' + } else { + window.location.href = '/?sc=1' + } + + setIsModalOpen(false) + action(false) + } else if (runtime.page === 'store.home') { + setIsModalOpen(false) + action(false) + } else if (hasPreOwnedProductsOnCart) { + setIsModalOpen(false) + action(false) + } else if (runtime.page === 'store.custom#pre-owned') { + setIsModalOpen(false) + action(false) + window.location.href = '/?sc=1' + } + } + + const handleAccept = async () => { + setIsLoading(true) + + try { + const id = orderFormId ?? orderForm.id + const itemsToRemove = items.map((_item: any, index: number) => ({ + index, + quantity: 0, + })) + + await removeAllProductsFromCart({ + variables: { + id, + orderItems: itemsToRemove, + }, + }) + setIsLoading(false) + setIsModalOpen(false) + action(false) + + if (isChallenge) { + if ( + runtime.page === 'store.custom#pre-owned' && + items.length > 0 && + !hasPreOwnedProductsOnCart + ) { + window.location.reload() + } else if ( + runtime.page === 'store.home' && + items.length > 0 && + hasPreOwnedProductsOnCart + ) { + window.location.reload() + } + } else if (runtime.page === 'store.home') { + window.location.href = '/seminovos?sc=2' + } else { + window.location.href = '/?sc=1' + } + } catch (err) { + console.error('Error while removing items from order form', err) + setIsLoading(false) + } + } + + if (!isModalOpen) return null + + return ( +
+
+ +
+

+ Quer começar um novo carrinho? +

+

+ Os produtos novos e seminovos não podem ser + adicionados ao mesmo carrinho simultaneamente. +

+
+
+ + +
+
+
+ ) +} + +export default PreOwnedPopupAlert diff --git a/react/components/PreOwnedPopupAlert/styles.css b/react/components/PreOwnedPopupAlert/styles.css new file mode 100644 index 00000000..0a6feca0 --- /dev/null +++ b/react/components/PreOwnedPopupAlert/styles.css @@ -0,0 +1,111 @@ +.overlayContainer { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 1000; + display: flex; + justify-content: center; + align-items: center; +} + +.popupWrapper { + max-width: 330px; + max-height: 336px; + width: 100%; + height: 100%; + padding: 32px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background-color: #fff; +} + +.popupIcon { + +} + +.popupContent { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.popupTitle { + color: var(--Neutral-darkest, #13171B); + text-align: center; + font-family: "Proxima Nova"; + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: 24px; /* 150% */ + letter-spacing: -0.16px; + margin: 8px 0; + width: 50%; +} + +.popupText { + color: var(--text-brand-secondary-base, #2B2B3A); + text-align: center; + font-family: "Proxima Nova"; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; /* 133.333% */ + letter-spacing: -0.12px; + margin: 0; + margin-bottom: 16px; +} + +.popupActions { + width: 100%; + display: flex; + flex-direction: column; + gap: 16px; +} + +.declineButton, +.acceptButton { + border-radius: var(--radius-rounded-sm, 2px); + padding: 12px 20px; + font-family: "Proxima Nova"; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px; + width: 100%; + transition: all 0.2s ease-in-out; + border: none; + cursor: pointer; + max-height: 48px; +} + +.acceptButton svg { + height: 26px; +} +.acceptButton svg circle { + stroke: #FF5A00; +} + +.declineButton { + background: var(--bg-brand-secondary-bold-base, #2B2B3A); + color: #FFF; +} + +.declineButton:hover { + background: var(--bg-brand-secondary-bold-hover, #424250); +} + +.acceptButton { + background: var(--bg-brand-primary-subtle-base, #FDF2EC); + color: #FF5A00; +} + +.acceptButton:hover { + background: var(--bg-brand-primary-subtle-hover, #FBE5D8); +} \ No newline at end of file diff --git a/react/components/PreOwnedSectionCondition/index.tsx b/react/components/PreOwnedSectionCondition/index.tsx new file mode 100644 index 00000000..a16205d1 --- /dev/null +++ b/react/components/PreOwnedSectionCondition/index.tsx @@ -0,0 +1,36 @@ +// Dependencies +import type { ReactNode } from 'react' +import React, { Fragment, useEffect, useState } from 'react' + +const PreOwnedSectionCondition = ({ children }: { children: ReactNode }) => { + const [hasPreOwnedProducts, setHasPreOwnedProducts] = useState(false) + const getPreOwnedCollection = async () => { + try { + const response = await fetch( + '/api/catalog_system/pub/products/search?fq=productClusterIds:169' + ) + + const data = await response.json() + + const isAvailable = data?.map((product: any) => + product.items.some( + (item: any) => item.sellers[0].commertialOffer.AvailableQuantity > 0 + ) + ) + + setHasPreOwnedProducts(isAvailable && data?.length > 0) + } catch (error) { + console.error('Error while fetching pre-owned products', error) + } + } + + useEffect(() => { + getPreOwnedCollection() + }, []) + + if (!hasPreOwnedProducts) return null + + return {children} +} + +export default PreOwnedSectionCondition diff --git a/react/components/PricePerCommercialPolicy/index.tsx b/react/components/PricePerCommercialPolicy/index.tsx new file mode 100644 index 00000000..0d7f71f0 --- /dev/null +++ b/react/components/PricePerCommercialPolicy/index.tsx @@ -0,0 +1,42 @@ +import React from 'react' + +// Styles +import styles from './styles.css' + +// Hooks +import { useQuery } from 'react-apollo' +import { useProduct } from 'vtex.product-context' + +// Queries +import GET_PRICE_PER_COMMERCIAL_POLICY from '../../graphql/queries/getPricePerCommercialPolicy.gql' +import formatPrice from '../../utils/formatPrice' + +interface PricePerCommercialPolicyProps { + salesChannel: number +} + +const PricePerCommercialPolicy = ({ + salesChannel, +}: PricePerCommercialPolicyProps) => { + const { product } = useProduct() ?? {} + + const { data, loading } = useQuery(GET_PRICE_PER_COMMERCIAL_POLICY, { + variables: { + slug: product?.linkText, + salesChannel, + }, + }) + + if (loading || !product) return null + + const { Price } = + data?.product?.items?.[0]?.sellers?.[0]?.commertialOffer ?? null + + return ( +
+ {formatPrice(Price)} +
+ ) +} + +export default PricePerCommercialPolicy diff --git a/react/components/PricePerCommercialPolicy/styles.css b/react/components/PricePerCommercialPolicy/styles.css new file mode 100644 index 00000000..8916da54 --- /dev/null +++ b/react/components/PricePerCommercialPolicy/styles.css @@ -0,0 +1,8 @@ +.priceWrapperProductSummary >span { + font-size: 20px; + font-style: normal; + font-weight: 600; + line-height: 28px; + color: #18181B; + letter-spacing: -0.2px; +} diff --git a/react/components/SalesChannelConditionTrigger/index.tsx b/react/components/SalesChannelConditionTrigger/index.tsx new file mode 100644 index 00000000..12d23585 --- /dev/null +++ b/react/components/SalesChannelConditionTrigger/index.tsx @@ -0,0 +1,101 @@ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +// Dependencies +import type { ReactNode } from 'react' +import React, { + Fragment, + useEffect, + useRef, + useState, + useCallback, + useMemo, +} from 'react' + +// Hooks +import { OrderForm } from 'vtex.order-manager' + +// Components +import PreOwnedPopupAlert from '../PreOwnedPopupAlert' + +const { useOrderForm } = OrderForm + +const SalesChannelriggerCondition = ({ children }: { children: ReactNode }) => { + const { orderForm } = useOrderForm() + const ref = useRef(null) + const [showPopupAlert, setShowPopupAlert] = useState(false) + const [hasPreOwnedProductsOnCart, setHasPreOwnedProductsOnCart] = + useState(false) + + const preOwnedProductIds = useMemo(() => { + const fetchPreOwnedProducts = async () => { + try { + const response = await fetch( + '/api/catalog_system/pub/products/search?fq=productClusterIds:169' + ) + + const data = await response.json() + + return data.map((product: any) => product.productId) + } catch (error) { + console.error('Error while fetching pre-owned products', error) + + return [] + } + } + + return fetchPreOwnedProducts() + }, []) + + useEffect(() => { + const checkPreOwnedProductsInCart = async () => { + const preOwnedIds = await preOwnedProductIds + const hasPreOwned = orderForm.items.some((item: any) => + preOwnedIds.includes(item.productId) + ) + + setHasPreOwnedProductsOnCart(hasPreOwned) + } + + checkPreOwnedProductsInCart() + }, [orderForm, preOwnedProductIds]) + + const handleClick = useCallback( + (evt: MouseEvent) => { + evt.preventDefault() + evt.stopPropagation() + + const link = ref.current?.querySelector('a')?.getAttribute('href') + + if (hasPreOwnedProductsOnCart) { + setShowPopupAlert(true) + } else { + window.location.href = link ?? '/?sc=1' + } + }, + [orderForm.items, hasPreOwnedProductsOnCart] + ) + + useEffect(() => { + const link = ref.current?.children?.[0] as HTMLAnchorElement + + link.addEventListener('click', handleClick) + + return () => { + link.removeEventListener('click', handleClick) + } + }, [handleClick]) + + return ( + + {children} + {showPopupAlert && ( + + )} + + ) +} + +export default SalesChannelriggerCondition diff --git a/react/components/ShippingBar/index.tsx b/react/components/ShippingBar/index.tsx new file mode 100644 index 00000000..2af28cc5 --- /dev/null +++ b/react/components/ShippingBar/index.tsx @@ -0,0 +1,94 @@ +import React from "react"; + +// Styles +import styles from "./styles.css"; +import formatPrice from "../../utils/formatPrice"; +import { OrderForm } from "vtex.order-manager"; + +const { useOrderForm } = OrderForm; + +interface ShippingBarProps { + minValue: number; + text: string; + fullBarText: string; +} + +const ShippingBar = ({ + minValue = 199, + text = "Faltam $value para você conseguir *frete grátis* nesta compra.", + fullBarText = "Você ganhou *frete grátis* nesta compra.", +}: ShippingBarProps) => { + const { orderForm } = useOrderForm(); + + const differenceToMinValue = (orderForm?.value - minValue * 100) / 100; + + + const parseMarkdown = (text: string) => { + return text + ?.replace(/\*([^*]+)\*/g, "$1") // Negrito + ?.replace(/_([^_]+)_/g, "$1"); // Itálico + }; + + return ( +
+
+ +
+
+
+
+ ); +}; + +export default ShippingBar; + +ShippingBar.schema = { + title: "Barra de Frete - Configurações", + type: "object", + properties: { + minValue: { + title: "Valor mínimo", + description: "Valor mínimo para frete grátis", + type: "number", + default: 200, + }, + text: { + title: "Texto da barra", + description: "Texto exibido na barra de frete", + type: "string", + default: + "Faltam $value para você conseguir *frete grátis* nesta compra.", + }, + fullBarText: { + title: "Texto da barra completa", + description: + "Texto exibido na barra de frete quando o valor mínimo for atingido", + type: "string", + default: "Você ganhou *frete grátis* nesta compra.", + }, + }, +}; diff --git a/react/components/ShippingBar/styles.css b/react/components/ShippingBar/styles.css new file mode 100644 index 00000000..6ab8c433 --- /dev/null +++ b/react/components/ShippingBar/styles.css @@ -0,0 +1,50 @@ +.shippingBarWrapper { + padding: 20px 24px 24px; +} + +.shippingBarText { + color: var(--text-neutral-subtle, #3f3f46); + text-align: center; + font-family: "Proxima Nova"; + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; + letter-spacing: -0.12px; + + margin-bottom: 12px; +} + +.shippingBarText strong { + color: var(--text-neutral-strong, #ee8146); +} + +.shippingBarLine { + background-color: #a1a1aa; + height: 2px; +} + +.shippingBarProgress { + height: 2px; + background-color: #ee8146; + position: relative; + display: flex; + align-items: center; +} + +.shippingBarProgress::after { + content: ""; + display: block; + width: 12px; + height: 12px; + border-radius: 50%; + background-color: #ee8146; + position: absolute; + right: 0; +} + +.shippingBarDot { + width: 12px; + height: 12px; + border-radius: 50%; +} diff --git a/react/components/Topbar/components/TopbarContent/index.tsx b/react/components/Topbar/components/TopbarContent/index.tsx new file mode 100644 index 00000000..93a777ca --- /dev/null +++ b/react/components/Topbar/components/TopbarContent/index.tsx @@ -0,0 +1,29 @@ +import React from 'react' + +import styles from './styles.css' + +interface TopbarContentProps { + backgroundColor: string + color: string + link: string + text: string +} + +const TopbarContent = ({ + backgroundColor, + color, + text, + link, +}: TopbarContentProps) => { + return ( + + ) +} + +export default TopbarContent diff --git a/react/components/Topbar/components/TopbarContent/styles.css b/react/components/Topbar/components/TopbarContent/styles.css new file mode 100644 index 00000000..c03de532 --- /dev/null +++ b/react/components/Topbar/components/TopbarContent/styles.css @@ -0,0 +1,23 @@ +.topbarContetWrapper { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 32px; +} + +.topbarContetWrapper a { + text-decoration: none; +} + +.contentText { + color: var(--Gray-Scale-White, #fff); + + /* text-sm/semibold */ + font-family: 'Proxima Nova'; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 20px; /* 142.857% */ + letter-spacing: -0.14px; +} diff --git a/react/components/Topbar/index.tsx b/react/components/Topbar/index.tsx new file mode 100644 index 00000000..27ace259 --- /dev/null +++ b/react/components/Topbar/index.tsx @@ -0,0 +1,82 @@ +import React from 'react' + +// @ts-ignore +import { useListContext, ListContextProvider } from 'vtex.list-context' +import TopbarContent from './components/TopbarContent' + +const Topbar = ({ items, children, showSearchBar }: any) => { + const { list } = useListContext() || [] + + if (!showSearchBar) return null + const topbarContentItems = items.map((item: any, index: number) => { + const { backgroundColor, color, text, link } = item + + return ( + + ) + }) + + const newListContextValue = list.concat(topbarContentItems) + + return ( + + {children} + + ) +} + +export default Topbar + +Topbar.schema = { + name: 'Topbar', + title: 'Lista de opções do Topbar', + type: 'object', + properties: { + showSearchBar: { + title: 'Mostrar topbar?', + type: 'boolean', + default: false, + }, + items: { + title: 'Itens do Topbar', + type: 'array', + items: { + type: 'object', + properties: { + __editorItemTitle: { + title: 'Nome para organização', + type: 'string', + }, + link: { + title: 'Link', + type: 'string', + }, + backgroundColor: { + title: 'Cor de fundo', + type: 'string', + widget: { + 'ui:widget': 'color', + }, + }, + color: { + title: 'Cor do texto', + type: 'string', + widget: { + 'ui:widget': 'color', + }, + }, + text: { + title: 'Texto', + type: 'string', + }, + }, + }, + }, + }, +} diff --git a/react/components/TrustVox/index.tsx b/react/components/TrustVox/index.tsx new file mode 100644 index 00000000..38548b07 --- /dev/null +++ b/react/components/TrustVox/index.tsx @@ -0,0 +1,53 @@ +import React, { useEffect } from 'react' +import styles from './styles.css' +import './styles.global.css' +import { useProduct } from 'vtex.product-context' + +const TrustVoxStars = () => { + const { product } = useProduct() ?? {} + + // @ts-ignore + window._trustvox_shelf_rate = [] + // @ts-ignore + window._trustvox_shelf_rate.push(['_storeId', '114129']) + + useEffect(() => { + const script = document.createElement('script') + + script.src = '//rate.trustvox.com.br/widget.js' + script.async = true + document.head.appendChild(script) + }, []) + function ajustingWindowPosition() { + const element = document.getElementById('reviews') as HTMLElement + console.log('here element', element) + if (!element) return + const deslocationToCentralize = -50 + + const quantityToScroll = Number(element.offsetTop) + deslocationToCentralize + + window.scrollTo({ + top: quantityToScroll, + behavior: 'smooth', + }) + } + + return ( +
+ +
+ ) +} + +export default TrustVoxStars diff --git a/react/components/TrustVox/styles.css b/react/components/TrustVox/styles.css new file mode 100644 index 00000000..1285383f --- /dev/null +++ b/react/components/TrustVox/styles.css @@ -0,0 +1,211 @@ +.evaluationContainer { + padding: 0 15px; + margin-bottom: 60px; + z-index: 0; +} + +.evaluationContainer h2 { + background-color: rgb(255, 255, 255); + color: #000; + display: table; + font-size: 25px; + font-weight: 700; + margin: 15px auto; + padding: 10px; + z-index: 2; + letter-spacing: 0.5px; +} +@media (min-width: 980px) { + .fullContainer { + max-width: 75%; + margin: auto; + } +} + +.contentContainer { + display: flex; + justify-content: center; + align-items: center; + width: 100%; +} + +.contentContainer > div { + padding: 9px; + width: 50%; + text-align: center; + cursor: pointer; +} + +@media (min-width: 980px) { + .contentContainer::after { + content: ''; + width: 100%; + height: 1px; + background: #cccccc; + position: relative; + top: 18px; + } + + .contentContainer > div { + width: 300px; + } +} + +.review { + border-top-left-radius: 5px; + border-top-right-radius: 5px; + border-bottom: 1px solid #ccc; +} + +.reviewActive { + border-left: 1px solid #ccc; + border-top: 1px solid #ccc; + border-bottom: none; + border-right: 1px solid #ccc; +} + +.avaliation_container { + margin-bottom: 50px; + padding: 0 30px; +} + +.trustvox_selo { +} + +:global(.trustvox-shelf-container) { + text-align: left; +} + +:global(.trustvox-certificate__fixed-tiny) { + background-size: auto !important; + background-position: -12px !important; +} + +:global(.ts-store-opinions-widget) { + display: flex; + flex-direction: row-reverse; +} + +:global(.ts-audited) { + display: flex; + justify-content: center !important; + flex-direction: column; + width: auto !important; + margin: 30px !important; + padding-right: 20px !important; +} +:global(.ts-768px) { + display: flex; + justify-content: center; +} + +:global(.ts-next-slide) { + right: -65px !important; +} +:global(.ts-prev-slide) { + left: -30px !important; +} +:global(.ts-prev-slide)::after { + content: ''; + width: 40px; + height: 40px; + display: block; + top: 0; + left: -14px; + position: absolute; +} +:global(.ts-next-slide)::after { + content: ''; + width: 40px; + height: 40px; + display: block; + top: 0; + right: -14px; + position: absolute; +} +:global(.ts-frame) { + width: 920px !important; +} +:global(.ts-trust-gray), +:global(.ts-opinion) { + width: 297px !important; +} +:global(.ts-trust-gray) { + background: #ffffff !important; + border: 1px solid #ced0ca !important; + border-radius: 6px !important; +} +:global(.ts-store-opinions-widget) { + max-width: 1300px; +} + +:gobal(.ts-customer-questions-form) h2 { + margin: 0; +} +:global(.ts-customer-questions) { + display: none !important; +} + +@media only screen and(max-width:1025px) { + :global(.trustvox-certificate__fixed-tiny) { + width: 100px !important; + background-size: auto !important; + background-position: -5px !important; + } +} +@media (max-width: 1025px) { + :global(.ts-store-opinions-widget) { + width: 610px; + overflow: hidden; + display: flex; + flex-direction: column-reverse; + } + :global(#_trustvox_colt), + :global(.ts-slider) { + display: flex; + justify-content: center; + align-items: center; + } + :global(.ts-audited) { + align-items: center; + } + :global(.ts-slider) { + width: 610px !important; + } +} + +@media (max-width: 800px) { + :global(.ts-audited) { + margin-top: 0 !important; + } +} + +@media (max-width: 500px) { + :global(.ts-store-opinions-widget) { + width: 300px; + overflow: hidden; + display: flex; + flex-direction: column-reverse; + } + :global(#_trustvox_colt), + :global(.ts-slider) { + display: flex; + justify-content: center; + align-items: center; + } + :global(.ts-audited) { + align-items: center; + } + :global(.ts-trust-gray), + :global(.ts-opinion) { + width: 230px !important; + } +} + +:global(.trustvox-shelf-container) { + display: table; +} +.stars_container button { + background-color: transparent !important; + border: none; +} diff --git a/react/components/TrustVox/styles.global.css b/react/components/TrustVox/styles.global.css new file mode 100644 index 00000000..1515de47 --- /dev/null +++ b/react/components/TrustVox/styles.global.css @@ -0,0 +1,3 @@ +.ts-shelf-rate-count { + display: none!important; +} \ No newline at end of file diff --git a/react/components/blog-posts/components/PostCard/index.tsx b/react/components/blog-posts/components/PostCard/index.tsx new file mode 100644 index 00000000..b678d09b --- /dev/null +++ b/react/components/blog-posts/components/PostCard/index.tsx @@ -0,0 +1,43 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import React from 'react' +import styles from './styles.css' +import type { WpPostProps } from '../../typing' + +interface PostCardProps { + post: WpPostProps + categoryName: string +} + +const PostCard = ({ post, categoryName }: PostCardProps) => { + const { excerpt, yoast_head_json, title, link } = post + + return ( +
+
+ {yoast_head_json?.og_title} +
+
+ {categoryName} +

{title?.rendered}

+ +
+ ) +} + +export default PostCard diff --git a/react/components/blog-posts/components/PostCard/styles.css b/react/components/blog-posts/components/PostCard/styles.css new file mode 100644 index 00000000..3f425f3e --- /dev/null +++ b/react/components/blog-posts/components/PostCard/styles.css @@ -0,0 +1,213 @@ +.slideChildrenContainer { + max-width: 400px; + max-height: 436px; + height: 100%; + margin-right: 24px; +} + +.postCardWrapper { + border-radius: 2px; + background: rgba(0, 0, 0, 1); + padding: 32px; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + gap: 12px; + box-sizing: border-box; + border-bottom: 2px solid transparent; + + &:hover { + border-bottom: 2px solid #FF5A00; + } +} + +.postCardImageWrapper { + width: 100%; + height: 200px; +} + +.postCardImage { + width: 100%; + height: 200px; + object-fit: cover; +} + +.postCardInfos { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 10px; + align-self: stretch; +} + +.postCardCategoryName { + color: #FFF; + font-family: "Proxima Nova"; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; +} + +.postCardTitle { + margin: 0; + overflow: hidden; + color: #FFF; + text-overflow: ellipsis; + font-family: "Proxima Nova"; + font-size: 20px; + font-style: normal; + font-weight: 500; + line-height: 28px; + letter-spacing: -0.2px; + text-align: left; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + padding: 0; + height: 56px; +} + +.postCardExcerpt p { + padding: 0; + margin: 0; + overflow: hidden; + color: #FFF; + text-overflow: ellipsis; + font-family: "Proxima Nova"; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; +} + +.postCardReadMore { + color: #FFF; + font-family: "Proxima Nova"; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + text-decoration-line: underline; +} + +.paginationDotsContainer { + bottom: -24px +} + +.paginationDot { + width: 6px!important; + height: 6px!important; + padding: 0!important; + border-radius: 9999px; + background: #A1A1AA; +} + +.paginationDot--isActive { + background: #FF5A00; +} + +.sliderLeftArrow svg, +.sliderRightArrow svg { + display: none; +} + +.sliderLeftArrow { + left: -64px; +} + +.sliderRightArrow { + right: -43px; +} +.sliderLeftArrow::before, +.sliderRightArrow::before { + display: block; + width: 40px; + height: 40px; +} + + + +.sliderLeftArrow::before { + content: url('data:image/svg+xml,'); + +} + +.sliderRightArrow::before { + content: url('data:image/svg+xml,'); + +} + +@media screen and (min-width: 768px) { + .sliderLeftArrow:hover::before, + .sliderRightArrow:hover::before { + position: relative; + top: 1px; + } + + .sliderRightArrow:hover::before { + content: url('data:image/svg+xml,'); + } + + .sliderLeftArrow:hover::before { + content: url('data:image/svg+xml,'); + } +} + +@media screen and (max-width: 768px) { + .slideChildrenContainer { + margin-right: 0; + } + + .sliderLeftArrow::before, + .sliderRightArrow::before { + display: block; + width:32px; + height:32px; + } + + .sliderLeftArrow, + .sliderRightArrow { + margin: 0; + padding: 0; + } + + + .sliderLeftArrow { + left: -14px; + } + + .sliderRightArrow { + right: -15px; + } + + .sliderLeftArrow::before { + content: url('data:image/svg+xml,'); + } + + .sliderRightArrow::before { + content: url('data:image/svg+xml,'); + } + + .postCardWrapper { + border-bottom: 2px solid #FF5A00; + } + + .postCardCategoryName { + color: #FF5A00; + } +} + +@media screen and (max-width: 639px) { + .slideChildrenContainer { + max-width: 100%; + } +} + diff --git a/react/components/blog-posts/index.tsx b/react/components/blog-posts/index.tsx new file mode 100644 index 00000000..e0d128d3 --- /dev/null +++ b/react/components/blog-posts/index.tsx @@ -0,0 +1,72 @@ +import React, { useEffect, useState } from 'react' +import { SliderLayout } from 'vtex.slider-layout' +import axios from 'axios' +import PostCard from './components/PostCard' +import type { WpPostProps } from './typing' +// import styles from './styles.css' + +export interface CategoryPostProps { + id: number + name: string + link: string +} + +export default function WordpressHomePosts() { + const [posts, setPosts] = useState() + const [categories, setCategories] = useState() + + async function getPosts() { + const req = await axios.get( + 'https://blog.rolandbrasil.com.br/wp-json/wp/v2/posts' + ) + + setPosts(req.data) + } + + async function getWpCategories() { + const req = await axios.get( + 'https://blog.rolandbrasil.com.br/wp-json/wp/v2/categories' + ) + + setCategories(req.data) + } + + const configSlider: any = { + itemsPerPage: { + desktop: 3, + tablet: 2, + phone: 1, + }, + showNavigationArrows: 'always', + } + + useEffect(() => { + getPosts() + getWpCategories() + }, []) + + if (!posts || !categories) return null + + return ( + <> +
+ + {posts.map((post) => { + const { slug } = post + const category = categories.find( + (cat) => cat.id === post.categories?.[0] + ) + + return ( + + ) + })} + +
+ + ) +} diff --git a/react/components/blog-posts/typing.ts b/react/components/blog-posts/typing.ts new file mode 100644 index 00000000..e689893b --- /dev/null +++ b/react/components/blog-posts/typing.ts @@ -0,0 +1,260 @@ +export interface CategoryPostProps { + id: number + name: string + link: string +} + +export interface WpPostProps { + id: number + date: string + date_gmt: string + guid: Guid + modified: string + modified_gmt: string + slug: string + status: string + type: string + link: string + title: Title + content: Content + excerpt: Excerpt + author: number + featured_media: number + comment_status: string + ping_status: string + sticky: boolean + template: string + format: string + meta: Meta + categories: number[] + tags: number[] + yoast_head: string + yoast_head_json: YoastHeadJson + _links: Links +} + +export interface Guid { + rendered: string +} + +export interface Title { + rendered: string +} + +export interface Content { + rendered: string + protected: boolean +} + +export interface Excerpt { + rendered: string + protected: boolean +} + +export interface Meta { + footnotes: string +} + +export interface YoastHeadJson { + title: string + robots: Robots + canonical: string + og_locale: string + og_type: string + og_title: string + og_description: string + og_url: string + og_site_name: string + article_publisher: string + article_published_time: string + article_modified_time: string + og_image: OgImage[] + author: string + twitter_card: string + twitter_creator: string + twitter_site: string + twitter_misc: TwitterMisc + schema: Schema +} + +export interface Robots { + index: string + follow: string + 'max-snippet': string + 'max-image-preview': string + 'max-video-preview': string +} + +export interface OgImage { + width: number + height: number + url: string + type: string +} + +export interface TwitterMisc { + 'Escrito por': string + 'Est. tempo de leitura': string +} + +export interface Schema { + '@context': string + '@graph': Graph[] +} + +export interface Graph { + '@type': string + '@id': string + isPartOf?: IsPartOf + author?: Author + headline?: string + datePublished?: string + dateModified?: string + mainEntityOfPage?: MainEntityOfPage + wordCount?: number + commentCount?: number + publisher?: Publisher + image?: Image + thumbnailUrl?: string + keywords?: string[] + articleSection?: string[] + inLanguage?: string + potentialAction?: PotentialAction[] + url?: string + name?: string + primaryImageOfPage?: PrimaryImageOfPage + breadcrumb?: Breadcrumb + contentUrl?: string + width?: number + height?: number + itemListElement?: ItemListElement[] + description?: string + logo?: Logo + sameAs?: string[] +} + +export interface IsPartOf { + '@id': string +} + +export interface Author { + name: string + '@id': string +} + +export interface MainEntityOfPage { + '@id': string +} + +export interface Publisher { + '@id': string +} + +export interface Image { + '@type'?: string + inLanguage?: string + '@id': string + url?: string + contentUrl?: string + caption?: string +} + +export interface PotentialAction { + '@type': string + target: any + 'query-input'?: string + name?: string +} + +export interface PrimaryImageOfPage { + '@id': string +} + +export interface Breadcrumb { + '@id': string +} + +export interface ItemListElement { + '@type': string + position: number + name: string + item?: string +} + +export interface Logo { + '@type': string + inLanguage: string + '@id': string + url: string + contentUrl: string + width: number + height: number + caption: string +} + +export interface Links { + self: Self[] + collection: Collection[] + about: About[] + author: Author2[] + replies: Reply[] + 'version-history': VersionHistory[] + 'predecessor-version': PredecessorVersion[] + 'wp:featuredmedia': Featuredmedum[] + 'wp:attachment': WpAttachment[] + 'wp:term': WpTerm[] + curies: Cury[] +} + +export interface Self { + href: string +} + +export interface Collection { + href: string +} + +export interface About { + href: string +} + +export interface Author2 { + embeddable: boolean + href: string +} + +export interface Reply { + embeddable: boolean + href: string +} + +export interface VersionHistory { + count: number + href: string +} + +export interface PredecessorVersion { + id: number + href: string +} + +export interface Featuredmedum { + embeddable: boolean + href: string +} + +export interface WpAttachment { + href: string +} + +export interface WpTerm { + taxonomy: string + embeddable: boolean + href: string +} + +export interface Cury { + name: string + href: string + templated: boolean +} diff --git a/react/components/countdown/index.tsx b/react/components/countdown/index.tsx new file mode 100644 index 00000000..98aa5f28 --- /dev/null +++ b/react/components/countdown/index.tsx @@ -0,0 +1,153 @@ +/* eslint-disable vtex/prefer-early-return */ +import React, { useState, useEffect, useRef } from 'react' +import styles from './styles.css' + +const formatTime = (time: number): string => { + return time < 10 ? `0${time}` : time.toString() +} + +interface TimeLeft { + days: number + hours: number + minutes: number + seconds: number +} + +interface CountdownProps { + targetDate: string + targetToBeDesabled: string[] + active: boolean +} + +const getVtexComponentClass = (component: string) => { + const [, blockId] = component.split('#') + + return `vtex-flex-layout-0-x-flexRow--${blockId}` +} + +const Countdown = ({ + targetDate: deadline, + active, + targetToBeDesabled, +}: CountdownProps) => { + const targetDate = new Date(deadline).getTime() + + const [timeLeft, setTimeLeft] = useState({ + days: 0, + hours: 0, + minutes: 0, + seconds: 0, + }) + + const savedTimeLeft = useRef({ + days: 0, + hours: 0, + minutes: 0, + seconds: 0, + }) + + useEffect(() => { + if (!active) { + return + } + + const updateCountdown = () => { + const now = new Date().getTime() + const distance = targetDate - now + + if (distance >= 0) { + const days = Math.floor(distance / (1000 * 60 * 60 * 24)) + const hours = Math.floor( + (distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60) + ) + + const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)) + const seconds = Math.floor((distance % (1000 * 60)) / 1000) + + const newTimeLeft = { days, hours, minutes, seconds } + + if ( + JSON.stringify(savedTimeLeft.current) !== JSON.stringify(newTimeLeft) + ) { + savedTimeLeft.current = newTimeLeft + setTimeLeft(newTimeLeft) + } + } + } + + updateCountdown() + const interval = setInterval(updateCountdown, 1000) + + return () => clearInterval(interval) + }, [targetDate, active]) + + useEffect(() => { + if (!active || targetDate < new Date().getTime()) { + targetToBeDesabled.forEach((component) => { + const selector = `.${getVtexComponentClass(component)}` + const element = document.querySelector(selector) as HTMLElement + + if (element) { + element.style.display = 'none' + } + }) + } + }, [active, targetDate, targetToBeDesabled]) + + if (!active || targetDate < new Date().getTime()) { + return null + } + + return ( +
+
+
+ {formatTime(timeLeft.days)} + Dias +
+
+
+ {formatTime(timeLeft.hours)} + Horas +
+
+
+ {formatTime(timeLeft.minutes)} + Minutos +
+
+
+ {formatTime(timeLeft.seconds)} + Segundos +
+
+
+ ) +} + +Countdown.schema = { + title: 'Configuração - Countdown', + type: 'object', + properties: { + targetDate: { + title: 'Data final', + type: 'string', + widget: { + 'ui:widget': 'date-time', + }, + }, + active: { + title: 'Ativar contagem regressiva?', + type: 'boolean', + }, + targetToBeDesabled: { + title: 'Elementos a serem desabilitados', + type: 'array', + items: { + type: 'string', + }, + }, + }, +} + +export default Countdown diff --git a/react/components/countdown/styles.css b/react/components/countdown/styles.css new file mode 100644 index 00000000..137d9a6d --- /dev/null +++ b/react/components/countdown/styles.css @@ -0,0 +1,96 @@ +.countdown-wrapper { + +} + +.time-container { + display: flex; + justify-content: center; + align-items: center; + gap: 16px; +} + + +.time-container >div { + display: flex; + flex-direction: column-reverse; + align-items: center; +} + +.time-container div:nth-of-type(2) { + width: var(--spacing-05, 2px); + height: 50px; + background: #FFF; + display: block; +} + +.time-container div:nth-of-type(2)::after { + display: none; +} + +.time-container .separator::after { + content: url('data:image/svg+xml,'); + + +} + + +.time-container .number { + color: var(--greyscale-700, #FDFDFD); + font-family: "Monument Extended"; + font-size: 48px; + font-style: normal; + font-weight: 700; + line-height: 56px; + padding: 8px; +} + +.time-container .label { + color: #FFF; + text-align: center; + font-family: "Monument Extended"; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: normal; + text-transform: capitalize; +} + + +@media screen and (max-width: 768px) { + + .time-container { + gap: 8px; + padding: 0 16px; + } + + .time-container .number { + font-size: 32px; + font-weight: 400; + line-height: 32px; + padding: 0; + } + + .time-container .label { + font-size: 10px; + font-weight: 400; + line-height: 16px; + } + + .time-container .separator::after { + content: ':'; + color: #FF5A00; + text-align: center; + font-family: Pluto; + font-size: 32px; + font-style: normal; + font-weight: 300; + line-height: 34.345px; /* 107.327% */ + } + + .time-container div:nth-of-type(2) { + width: 0.6px; + height: 27px; + background: #FF5A00; + display: block; + } +} diff --git a/react/components/custom-infocard/index.tsx b/react/components/custom-infocard/index.tsx new file mode 100644 index 00000000..40796eb4 --- /dev/null +++ b/react/components/custom-infocard/index.tsx @@ -0,0 +1,62 @@ +// Dependencies +import React from 'react' + +// Styles +import styles from './styles.css' + +// Context +import { CUSTOM_INFOCARD_SCHEMA } from './schema' + +// Hooks +// @ts-ignore +import { useDevice } from 'vtex.device-detector' +// Interface +interface CustomInfoCardProps { + cards: any + cardSeeAll: any +} + +const CustomInfoCard = ({ cards, cardSeeAll }: CustomInfoCardProps) => { + const { isMobile } = useDevice() + + if (!cards || !cardSeeAll) { + return null + } + + const filteredCards = cards.slice(0, isMobile ? 5 : 7) + + return ( +
+ {filteredCards.map((card: any) => { + const { image, hoverImage, title, link, buttonLabel } = card + + return ( + +
+
+ {title} +
+
+ {title} +
+
+

{title}

+ +
+
+
+ ) + })} +
+ {cardSeeAll.title} + + {cardSeeAll.buttonLabel} + +
+
+ ) +} + +CustomInfoCard.schema = CUSTOM_INFOCARD_SCHEMA + +export default CustomInfoCard diff --git a/react/components/custom-infocard/schema.ts b/react/components/custom-infocard/schema.ts new file mode 100644 index 00000000..3f853681 --- /dev/null +++ b/react/components/custom-infocard/schema.ts @@ -0,0 +1,74 @@ +export const CUSTOM_INFOCARD_SCHEMA = { + type: 'object', + properties: { + cards: { + title: 'Cards e Card Geral', + type: 'array', + items: { + title: 'Card', + type: 'object', + properties: { + __editorItemTitle: { + title: 'Nome do card (para organização)', + type: 'string', + }, + visible: { + title: 'Visivel', + type: 'boolean', + default: true, + }, + image: { + title: 'Imagem de fundo', + type: 'string', + widget: { + 'ui:widget': 'image-uploader', + }, + }, + hoverImage: { + title: 'Imagem no hover', + type: 'string', + widget: { + 'ui:widget': 'image-uploader', + }, + }, + title: { + title: 'Título', + type: 'string', + default: '', + }, + link: { + title: 'Link de redirecionamento', + type: 'string', + default: '', + }, + buttonLabel: { + title: 'Button Label', + type: 'string', + default: 'Ver tudo', + }, + }, + }, + }, + cardSeeAll: { + title: 'Card Geral', + type: 'object', + properties: { + title: { + title: 'Título Card Geral', + type: 'string', + default: 'Ver todas as categorias', + }, + link: { + title: 'Link de redirecionamento Card Geral', + type: 'string', + default: '/#', + }, + buttonLabel: { + title: 'Button Label Card Geral', + type: 'string', + default: 'Ver tudo', + }, + }, + }, + }, +} diff --git a/react/components/custom-infocard/styles.css b/react/components/custom-infocard/styles.css new file mode 100644 index 00000000..4a45c423 --- /dev/null +++ b/react/components/custom-infocard/styles.css @@ -0,0 +1,213 @@ +.cards-container { + max-width: 1376px; + display: grid; + grid-template-columns: repeat(4, 1fr); + grid-template-rows: repeat(2, 1fr); + gap: 1rem; +} + +.cards-container .sliderTrack { + margin: 0 -8px; +} + +.cards-container .slide { + margin: 0 8px; +} + +.cards-container .slideChildrenContainer { + max-width: 332px; + max-height: 320px; +} + +.cards-container .slideChildrenContainer a, +.cards-container a { + width: 100%; + height: 100%; + text-decoration: none; +} + +.card-wrapper { + border-radius: var(--radius-rounded-sm, 2px); + background: #f0f0f0; + display: flex; + flex-direction: column; + position: relative; + align-items: center; + padding: 40px 32px; + justify-content: center; + transition: all 0.3s ease-in-out; + width: 100%; + height: 100%; +} + +.hover-image { + transition: all 0.3s ease-in-out; + position: absolute; + left: 0; + top: 0; + opacity: 0; + border-radius: var(--radius-rounded-sm, 2px); + background-color: rgba(0, 0, 0, 0.4); + width: 100%; + height: 100%; +} +.hover-image img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.card-image { + opacity: 1; + max-width: 200px; + max-height: 200px; + transition: all 0.3s ease-in-out; +} + +.card-image img { + mix-blend-mode: multiply; + width: 100%; + height: 100%; + max-width: 200px; + max-height: 200px; +} + +.card-content h3 { + opacity: 1; + color: var(--Gray-Scale-Black, #000); + text-align: center; + font-family: 'Proxima Nova'; + font-size: 24px; + font-style: normal; + font-weight: 500; + line-height: 32px; + letter-spacing: -0.24px; + margin: 0; +} + +.card-content button { + border-radius: var(--radius-rounded-sm, 2px); + background: var(--Gray-Scale-White, #fff); + border: none; + color: var(--text-neutral-bold, #18181b); + font-family: 'Proxima Nova'; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; /* 142.857% */ + letter-spacing: -0.14px; + position: absolute; + left: 50%; + transform: translateX(-50%); + bottom: 40px; + height: 40px; + padding: 10px 16px; + width: 183px; + opacity: 0; + transition: all 0.3s ease-in-out; + cursor: pointer; +} + +.caretIcon { + display: none; +} +.cards-container .see-all-card { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + width: 100%; + height: 100%; + position: relative; +} +.cards-container .see-all-card .see-all-card-title { + font-family: 'Monument Extended'; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: 28px; + text-transform: uppercase; + color: #ff5a00; + text-align: center; + margin-bottom: 1.5rem; +} +.cards-container .see-all-card .see-all-card-button { + border-radius: 2px; + border: 1.25px solid #d4d4d8; + background: #fff; + width: calc(100% - 4rem); + height: 3rem; + color: #3f3f46; + font-family: 'Proxima Nova'; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.16px; + display: flex; + align-items: center; + justify-content: center; +} + +.cards-container .see-all-card .see-all-card-button:hover { + transition: all 0.3s ease-in-out; + border-color: #ee8146; + background: #fdf2ec; + color: #ff5a00; +} + +@media screen and (min-width: 768px) { + .card-wrapper:hover .card-content h3, + .card-wrapper:hover .card-image { + opacity: 0; + } + .card-wrapper:hover .hover-image, + .card-wrapper:hover .card-content button { + opacity: 1; + } +} + +@media screen and (max-width: 64rem) { + .card-wrapper .card-content h3 { + text-align: center; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + } + .card-link { + max-width: 15rem; + max-height: 15rem; + } + .card-wrapper { + padding: 12px 0; + padding-top: 18px; + max-width: 15rem; + max-height: 15rem; + } + + .card-image img { + max-width: 90px; + max-height: 90px; + } + + .cards-container { + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-template-rows: repeat(3, 1fr); + gap: auto; + justify-items: center; + } + + .cards-container .see-all-card .see-all-card-title { + margin-bottom: 0.75rem; + font-size: 14px; + line-height: 20px; + } + .cards-container .see-all-card .see-all-card-button { + max-width: 16.75rem; + width: 100%; + height: 2.5rem; + } +} diff --git a/react/components/product/AnchorSections/index.tsx b/react/components/product/AnchorSections/index.tsx new file mode 100644 index 00000000..68f12cf5 --- /dev/null +++ b/react/components/product/AnchorSections/index.tsx @@ -0,0 +1,155 @@ +// Dependencies +import React, { useEffect, useState } from 'react' +import { useDevice } from 'vtex.device-detector' + +// Styles +import styles from './styles.css' + +const initialAnchors = [ + { + id: 'description', + label: 'Informações do produto', + showItem: false, + }, + { + id: 'specifications', + label: 'Especificações Técnicas', + showItem: false, + }, + { + id: 'manual', + label: 'Manual de Instruções', + showItem: false, + }, + { + id: 'content', + label: 'O que está incluso?', + showItem: false, + }, + { + id: 'video', + label: 'Vídeo do produto', + showItem: false, + }, + { + id: 'reviews', + label: 'Avaliações', + showItem: false, + }, +] + +const AnchorSections = () => { + const [isOpen, setIsOpen] = useState(false) + const [selectedAnchor, setSelectedAnchor] = useState(initialAnchors[0]) + const [anchors, setAnchors] = useState(initialAnchors) + const { isMobile } = useDevice() + + const handleAnchorClick = (anchor: (typeof initialAnchors)[0]) => { + console.log('here anchor', anchor) + + ajustingWindowPosition(anchor.id) + setSelectedAnchor(anchor) + setIsOpen(false) + } + function ajustingWindowPosition(itemId: string) { + console.log('ajustingWindowPosition, here', itemId) + const element = document.getElementById(itemId) as HTMLElement + console.log('here element', element) + if (!element) return + const deslocationToCentralize = -50 + console.log('here deslocationToCentralize', deslocationToCentralize) + + const quantityToScroll = Number(element.offsetTop) + deslocationToCentralize + console.log('here quantityToScroll', quantityToScroll) + + window.scrollTo({ + top: quantityToScroll, + behavior: 'smooth', + }) + } + + function checkingActiveAnchors() { + const observers: MutationObserver[] = [] + let timeoutId: any + + const checkAnchors = () => { + const updatedAnchors = initialAnchors.map((anchor) => ({ + ...anchor, + showItem: !!document.getElementById(anchor.id), + })) + setAnchors(updatedAnchors) + } + + initialAnchors.forEach((anchor) => { + const observer = new MutationObserver(() => { + const element = document.getElementById(anchor.id) + if (element) { + checkAnchors() + observer.disconnect() + } + }) + observer.observe(document.body, { childList: true, subtree: true }) + observers.push(observer) + }) + + timeoutId = setTimeout(() => { + observers.forEach((observer) => observer.disconnect()) + }, 30000) + + return () => { + clearTimeout(timeoutId) + observers.forEach((observer) => observer.disconnect()) + } + } + + useEffect(() => { + checkingActiveAnchors() + }, []) + + return ( +
+ {isMobile ? ( +
+ + +
+ {anchors.map((anchor) => + anchor.showItem ? ( + + ) : null + )} +
+
+ ) : ( +
+ {anchors.map((anchor) => + anchor.showItem ? ( + + ) : null + )} +
+ )} +
+ ) +} + +export default AnchorSections diff --git a/react/components/product/AnchorSections/styles.css b/react/components/product/AnchorSections/styles.css new file mode 100644 index 00000000..a0a10edd --- /dev/null +++ b/react/components/product/AnchorSections/styles.css @@ -0,0 +1,114 @@ +.anchorSectionsWrapper { + width: 100%; +} + +.desktopView { + display: none; +} + +.mobileDropdown { + width: 100%; + position: relative; +} + +.anchorButton { + cursor: pointer; + background-color: transparent; + border: none; + max-width: 190px; + width: 100%; + padding: 12px 0; + text-decoration: none; + color: var(--text-inverse-subtlest, #71717a); + font-family: 'Proxima Nova'; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; +} + +.anchorButton:first-child { + border-bottom: 1.5px solid var(--text-brand-primary-base, #ff5a00); +} + +.dropdownToggle { + width: 100%; + padding: 10px 16px; + border: 1px solid #ddd; + border-radius: 4px; + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + border-radius: var(--radius-rounded-sm, 2px); + background: var(--bg-brand-secondary-bold-pressed, #2b2b3a); + color: #fff; + font-family: 'Proxima Nova'; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; +} + +.dropdownToggle::after { + content: url('data:image/svg+xml,'); +} + +.dropdownContent { + display: none; + position: absolute; + width: 100%; + background: #fff; + border: 1px solid #ddd; + border-top: none; + border-radius: 0 0 4px 4px; + z-index: 1; +} + +.dropdownContent.open { + display: flex; +} + +.arrow { + transition: transform 0.3s ease; +} + +.arrowUp { + transform: rotate(180deg); +} + +/* Media query para desktop */ +@media (min-width: 768px) { + .mobileDropdown { + display: none; + } + + .desktopView { + display: flex; + width: 100%; + gap: 24px; + justify-content: center; + } +} + +@media screen and (max-width: 768px) { + .anchorButton:first-child { + border-bottom: none; + } + + .anchorButton { + text-align: left; + max-width: 100%; + text-align: left; + padding: 0; + } + + .dropdownContent.open { + padding: 12px; + display: flex; + flex-direction: column; + gap: 16px; + } +} diff --git a/react/components/product/ProductContentItems/index.tsx b/react/components/product/ProductContentItems/index.tsx new file mode 100644 index 00000000..ce4b2d0d --- /dev/null +++ b/react/components/product/ProductContentItems/index.tsx @@ -0,0 +1,45 @@ +import React from 'react' +import styles from './styles.css' +import { useProduct } from 'vtex.product-context' +import type { IProductProperties } from '../../../typings/productsInfos' +import { formatTextAsHTML } from '../../../utils/formatTextAsHTML' + +const ProductContentItems: React.FC = () => { + const context = useProduct() + + if (!context) return null + + const product = context?.product + const properties = product?.properties as IProductProperties[] | undefined + + if (!properties) return null + + const productContentList = properties + .filter((item) => item.name.startsWith('O que está incluso ')) + .map((item) => item.values[0]) + + if (productContentList.length === 0) return null + + const formattedProductContentList = productContentList.map((item) => + formatTextAsHTML(item) + ) + + return ( +
+
+

O que está incluso?

+
    + {formattedProductContentList.map((item, i) => ( +
  • + ))} +
+
+
+ ) +} + +export default ProductContentItems diff --git a/react/components/product/ProductContentItems/styles.css b/react/components/product/ProductContentItems/styles.css new file mode 100644 index 00000000..fd401bd7 --- /dev/null +++ b/react/components/product/ProductContentItems/styles.css @@ -0,0 +1,44 @@ +.productContentItemsWrapper { + background-color: #f4f4f5; +} +.productContentItemsContainer { + max-width: 90rem; + margin: 0 auto; + padding: 3rem 2rem; +} +.productContentItemsTitle { + color: #3f3f46; + font-family: 'Proxima Nova'; + font-size: 32px; + font-style: normal; + font-weight: 500; + line-height: 40px; + letter-spacing: -0.32px; + margin: 0 0 1.5rem; +} +.productContentItemsContentItem { + color: #5a5a66; + font-family: 'Proxima Nova'; + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 24px; + letter-spacing: -0.16px; +} +.productContentItemsContentItem::marker { + font-size: 14px; +} +.productContentItemsContent { + margin: 0; + padding-left: 2rem; +} +@media screen and (max-width: 64rem) { + .productContentItemsContainer { + padding: 1.5rem 1rem; + } + .productContentItemsTitle { + font-size: 24px; + line-height: 32px; + letter-spacing: -0.24px; + } +} diff --git a/react/components/product/ProductDescriptionCustom/index.tsx b/react/components/product/ProductDescriptionCustom/index.tsx new file mode 100644 index 00000000..bd0d0e1d --- /dev/null +++ b/react/components/product/ProductDescriptionCustom/index.tsx @@ -0,0 +1,59 @@ +/* eslint-disable react/no-unescaped-entities */ +import React from 'react' +import { useProduct } from 'vtex.product-context' + +import type { IProductProperties } from '../../../typings/productsInfos' +import styles from './styles.css' +import { getPropertyByName } from '../../../utils/getPropertyByName' +import { formatTextAsHTML } from '../../../utils/formatTextAsHTML' + +const ProductDescriptionCustom = () => { + const context = useProduct() + + if (!context) return null + const product = context?.product + + const properties = product?.properties as IProductProperties[] | undefined + + if (!properties) return null + + const qualitiesContent: string[] = [] + + properties?.forEach((item: IProductProperties) => { + if (item.name.substring(0, 10) === 'Qualidade ') { + qualitiesContent.push(item.values[0]) + } + }) + const descriptionTitle = getPropertyByName(properties, 'Descrição Título') + const descriptionText = getPropertyByName(properties, 'Descrição Texto') + + return ( +
+

Informações do produto

+ {qualitiesContent.length > 0 && ( +
    + {qualitiesContent?.map((item: any) => ( +
  • + ))} +
+ )} + {descriptionTitle && descriptionText && ( + <> +

{descriptionTitle}

+

+ + )} +

+ ) +} + +export default ProductDescriptionCustom diff --git a/react/components/product/ProductDescriptionCustom/styles.css b/react/components/product/ProductDescriptionCustom/styles.css new file mode 100644 index 00000000..92c95ef3 --- /dev/null +++ b/react/components/product/ProductDescriptionCustom/styles.css @@ -0,0 +1,51 @@ +.descriptionQualityList { + margin: 0 0 3rem; + padding-inline-start: 1.75rem; +} +.descriptionQualityListItem, +.descriptionText { + color: #5a5a66; + font-family: 'Proxima Nova'; + font-style: normal; + font-weight: 400; + font-size: 16px; + line-height: 24px; + letter-spacing: -0.16px; +} +.descriptionText { + max-width: 48.875rem; + margin: 0; +} +.descriptionTitle, +.descriptionGeneralTitle { + color: #3f3f46; + font-family: 'Proxima Nova'; + font-size: 32px; + font-style: normal; + font-weight: 500; + line-height: 40px; + letter-spacing: -0.32px; + margin: 0 0 1.5rem; +} +@media screen and (max-width: 64rem) { + .descriptionQualityList { + margin-bottom: 2rem; + } + .descriptionText { + max-width: 100%; + margin-bottom: 2rem; + } + .descriptionQualityListItem, + .descriptionText { + font-size: 14px; + line-height: 20px; + letter-spacing: -0.14px; + } + .descriptionTitle, + .descriptionGeneralTitle { + font-size: 24px; + line-height: 32px; + letter-spacing: -0.24px; + margin-bottom: 1rem; + } +} diff --git a/react/components/product/ProductInstructionManual/index.tsx b/react/components/product/ProductInstructionManual/index.tsx new file mode 100644 index 00000000..c4222090 --- /dev/null +++ b/react/components/product/ProductInstructionManual/index.tsx @@ -0,0 +1,71 @@ +import React, { useEffect, useState } from 'react' +import styles from './styles.css' +import { useProduct } from 'vtex.product-context' +import { IProductProperties } from '../../../typings/productsInfos' +import { getPropertyByName } from '../../../utils/getPropertyByName' + +const ProductInstructionManual: React.FC = () => { + const [manualUrlInfo, setManualUrlInfo] = useState(null) + const context = useProduct() + + if (!context) return null + const product = context?.product + + const properties = product?.properties as IProductProperties[] | undefined + + useEffect(() => { + if (!properties) return + + const manualUrl = getPropertyByName(properties, 'Manual de instruções') + + setManualUrlInfo(manualUrl) + }, [properties]) + + return ( + <> + {manualUrlInfo ? ( +
+

+ Manual de instruções +

+
+ + + + + +

+ Clique{' '} + + aqui + {' '} + para baixar o
manual de instruções. +

+
+
+ ) : null} + + ) +} + +export default ProductInstructionManual diff --git a/react/components/product/ProductInstructionManual/styles.css b/react/components/product/ProductInstructionManual/styles.css new file mode 100644 index 00000000..f344bbca --- /dev/null +++ b/react/components/product/ProductInstructionManual/styles.css @@ -0,0 +1,66 @@ +.productInstructionManualContainer { + max-width: 90rem; + margin: 0 auto; + padding: 3rem 2rem; +} +.productInstructionManualTitle { + color: #3f3f46; + font-family: 'Proxima Nova'; + font-size: 32px; + font-style: normal; + font-weight: 500; + line-height: 40px; + letter-spacing: -0.32px; + margin: 0 0 1.5rem; +} +.productInstructionManualContent { + display: flex; + align: center; + justify-content: flex-start; + column-gap: 0.75rem; +} +.productInstructionManualLink { + display: flex; + align-items: center; + justify-content: center; + background-color: #2b2b3a; + padding: 0.75rem; + border-radius: 2px; + box-sizing: border-box; + height: 3.125rem; + width: 3.125rem; + cursor: pointer; +} + +.productInstructionManualPhrase { + color: #5a5a66; + font-family: 'Proxima Nova'; + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 24px; + letter-spacing: -0.16px; + margin: 0; +} +.productInstructionManualSimpleLink { + color: #18181b; + font-family: 'Proxima Nova'; + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: 24px; + letter-spacing: -0.16px; + text-decoration: underline; + cursor: pointer; +} + +@media screen and (max-width: 64rem) { + .productContentItemsContainer { + padding: 1.5rem 1rem; + } + .productInstructionManualTitle { + font-size: 24px; + line-height: 32px; + letter-spacing: -0.24px; + } +} diff --git a/react/components/product/ProductLinkShare/index.tsx b/react/components/product/ProductLinkShare/index.tsx new file mode 100644 index 00000000..ae2980c4 --- /dev/null +++ b/react/components/product/ProductLinkShare/index.tsx @@ -0,0 +1,75 @@ +import React, { useState } from 'react' +// Styles +import styles from './styles.css' + +const ProductLinkShare = () => { + const [isCopied, setIsCopied] = useState(false) + + const handleButtonClick = async () => { + if (isCopied === true) { + setIsCopied(false) + + return + } + + const productLink = window.location.href + + try { + await navigator.clipboard.writeText(productLink) + setIsCopied(true) + } catch (error) { + console.error('Erro ao copiar o link:', error) + } + } + + return ( + + ) +} + +export default ProductLinkShare diff --git a/react/components/product/ProductLinkShare/styles.css b/react/components/product/ProductLinkShare/styles.css new file mode 100644 index 00000000..3801374c --- /dev/null +++ b/react/components/product/ProductLinkShare/styles.css @@ -0,0 +1,31 @@ +.share-button { + display: flex; + align-items: center; + border: none; + background: none; + cursor: pointer; + padding: 8px; + margin: 20px auto 28px auto; + position: relative; +} +.share-button-copied-text { + margin-left: 8px; + position: absolute; + top: 10px; + left: 26px; + white-space: nowrap; + color: #000; + font-family: 'Proxima Nova'; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; +} +.share-button-icon { + filter: brightness(0); +} +.share-button:hover .share-button-icon { + filter: brightness(1); + transition: all 0.5s ease-in-out; +} diff --git a/react/components/product/ProductReadMoreDescription/index.tsx b/react/components/product/ProductReadMoreDescription/index.tsx new file mode 100644 index 00000000..e2849467 --- /dev/null +++ b/react/components/product/ProductReadMoreDescription/index.tsx @@ -0,0 +1,41 @@ +import React from 'react' +import { useProduct } from 'vtex.product-context' + +import styles from './styles.css' + +const ProductReadMoreDescription = () => { + const context = useProduct() + + if (!context) return null + + const shortDescription = context?.selectedItem?.complementName + + if (!shortDescription) return null + + function ajustingWindowPosition() { + const element = document.querySelector('#description') as HTMLElement + + if (!element) return + window.scrollTo({ + top: Number(element.offsetTop) - 100, + behavior: 'smooth', + }) + } + + return ( +
+

+ {shortDescription} +

+ + +
+ ) +} + +export default ProductReadMoreDescription diff --git a/react/components/product/ProductReadMoreDescription/styles.css b/react/components/product/ProductReadMoreDescription/styles.css new file mode 100644 index 00000000..8dd04577 --- /dev/null +++ b/react/components/product/ProductReadMoreDescription/styles.css @@ -0,0 +1,30 @@ +.productReadMoreDescriptionText { + color: #5e5e5e; + font-family: 'Proxima Nova'; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.14px; + margin-top: 16px; + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + text-overflow: ellipsis; + -webkit-line-clamp: 4; + margin: 0 0 0.5rem; +} +.productReadMoreDescriptionButton { + border: none; + background: transparent; + padding: 0; + color: #353535; + font-family: 'Proxima Nova'; + font-size: 12px; + font-style: normal; + font-weight: 600; + line-height: 16px; + letter-spacing: -0.12px; + text-decoration: underline; + cursor: pointer; +} diff --git a/react/components/product/ProductTechnicalSpecifications/index.tsx b/react/components/product/ProductTechnicalSpecifications/index.tsx new file mode 100644 index 00000000..dcb2bb3a --- /dev/null +++ b/react/components/product/ProductTechnicalSpecifications/index.tsx @@ -0,0 +1,109 @@ +import React, { useState } from 'react' +import { useProduct } from 'vtex.product-context' +import styles from './styles.css' + +// Interface para a especificação técnica +interface TechnicalSpecification { + name: string + text: string +} + +const ProductTechnicalSpecifications: React.FC = () => { + const [showMore, setShowMore] = useState(false) + const context = useProduct() + + if (!context) return null + const { product } = context + + if (!product) return null + + const { properties } = product + + const technicalSpecifications: TechnicalSpecification[] = + properties + ?.filter( + (item: any) => item.name.substring(0, 21) === 'Especificação Técnica' + ) + .map((item: any) => { + const [name, ...textParts] = item.values[0].split(':') + const text = textParts.join(':').trim() + + return { name: name.trim() || '', text } + }) || [] + + if (technicalSpecifications.length === 0) return null + const displayedItems = showMore + ? technicalSpecifications + : technicalSpecifications.slice(0, 13) + + return ( +
+

+ Especificações técnicas +

+
    + {displayedItems.map((item, i) => ( +
  • + + {item.name || ''} + + + {item.text} + +
  • + ))} +
+ {technicalSpecifications.length > 13 && ( + + )} +
+ ) +} + +export default ProductTechnicalSpecifications diff --git a/react/components/product/ProductTechnicalSpecifications/styles.css b/react/components/product/ProductTechnicalSpecifications/styles.css new file mode 100644 index 00000000..e799837a --- /dev/null +++ b/react/components/product/ProductTechnicalSpecifications/styles.css @@ -0,0 +1,89 @@ +.technicalSpecificationsContainer { + max-width: 90rem; + margin: 0 auto; + padding: 3rem 2rem; +} +.technicalSpecificationsTitle { + color: #3f3f46; + font-family: 'Proxima Nova'; + font-size: 32px; + font-style: normal; + font-weight: 500; + line-height: 40px; + letter-spacing: -0.32px; + margin: 0 0 2rem; +} +.technicalSpecificationsList { + list-style: none; + padding: 0; + margin: 0; + max-width: 52.5rem; + width: 100%; +} + +.technicalSpecificationsList li { + padding: 0.875rem 1.5rem; + border-radius: 0.25rem; + position: relative; + width: 100%; + display: flex; + column-gap: 0.5rem; + font-family: 'Proxima Nova'; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.14px; + color: #3f3f46; +} +.technicalSpecificationsList li .technicalSpecificationsName { + color: #18181b; + width: 15rem; + font-weight: 600; + display: inline-block; +} +.technicalSpecificationsText { + width: calc(100% - 15rem); + display: inline-block; +} +.technicalSpecificationsList li:nth-child(odd) { + background: #ededed; +} +.technicalSpecificationsButton { + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + border: none; + background: transparent; + text-decoration: underline; + color: #383838; + font-family: 'Proxima Nova'; + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: 20px; + letter-spacing: -0.16px; + padding: 0; + margin: 1.5rem 0 0; +} +@media screen and (max-width: 64rem) { + .technicalSpecificationsContainer { + padding: 1.5rem 1rem; + } + .technicalSpecificationsTitle { + font-size: 24px; + line-height: 32px; + letter-spacing: -0.24px; + margin-bottom: 1.5rem; + } +} +@media screen and (max-width: 48rem) { + .technicalSpecificationsList li { + column-gap: 0.25rem; + } + .technicalSpecificationsList li .technicalSpecificationsName, + .technicalSpecificationsList li .technicalSpecificationsText { + width: 50%; + } +} diff --git a/react/components/product/ProductTrustvoxAvaliations/index.tsx b/react/components/product/ProductTrustvoxAvaliations/index.tsx new file mode 100644 index 00000000..1ad03739 --- /dev/null +++ b/react/components/product/ProductTrustvoxAvaliations/index.tsx @@ -0,0 +1,48 @@ +/* eslint-disable @typescript-eslint/ban-types */ +/* eslint-disable no-undef */ +import React, { useEffect } from 'react' +import styles from './styles.css' +import { useProduct } from 'vtex.product-context' + +const ProductTrustvoxAvaliations: React.FC = () => { + const product = useProduct() + + ;(window as any)._trustvox = [] + ;(window as any)._trustvox.push(['_storeId', '114129']) + ;(window as any)._trustvox.push(['_productId', product?.product?.productId]) + ;(window as any)._trustvox.push([ + '_productName', + product?.product?.productName, + ]) + + useEffect(() => { + const script = document.createElement('script') + + script.src = '//static.trustvox.com.br/sincero/sincero.js' + script.async = true + document.body.appendChild(script) + }, []) + + return ( + <> +
+

+ Pergunte e veja a opinião de quem comprou +

+
+
+
+ Avaliação +
+
+ +
+
+
+
+
+ + ) +} + +export default ProductTrustvoxAvaliations diff --git a/react/components/product/ProductTrustvoxAvaliations/styles.css b/react/components/product/ProductTrustvoxAvaliations/styles.css new file mode 100644 index 00000000..4e6956e2 --- /dev/null +++ b/react/components/product/ProductTrustvoxAvaliations/styles.css @@ -0,0 +1,217 @@ +.avaliationsContainer { + max-width: 90rem; + margin: 0 auto; + padding: 3rem 2rem !important; + z-index: 0; +} + +.avaliationsTitle { + color: #3f3f46; + font-family: 'Proxima Nova'; + font-size: 32px; + font-style: normal; + font-weight: 500; + line-height: 40px; + letter-spacing: -0.32px; + margin: 0 0 0.5rem; +} +.avaliationsFullContainer { + max-width: 52.125rem; + margin: 0; + width: 100%; +} +@media screen and (max-width: 64rem) { + .avaliationsTitle { + font-size: 24px; + line-height: 32px; + letter-spacing: -0.24px; + margin: 0 0 1rem; + } + .avaliationsContainer { + padding: 0 1rem; + } +} + +.avaliationsContent { + display: flex; + justify-content: center; + align-items: center; + width: 100%; +} + +.avaliationsContent > div { + padding: 9px; + width: 50%; + text-align: center; + cursor: pointer; +} + +@media (min-width: 980px) { + .avaliationsContent::after { + content: ''; + width: 100%; + height: 1px; + background: #cccccc; + position: relative; + top: 18px; + } + + .avaliationsContent > div { + width: 300px; + } +} + +.review { + border-top-left-radius: 5px; + border-top-right-radius: 5px; + border-bottom: 1px solid #ccc; +} + +.reviewActive { + border-left: 1px solid #ccc; + border-top: 1px solid #ccc; + border-bottom: none; + border-right: 1px solid #ccc; +} + +.avaliation_container { + margin-bottom: 50px; + padding: 0 30px; +} + +.trustvox_selo { +} + +:global(.trustvox-shelf-container) { + text-align: left; +} + +:global(.trustvox-certificate__fixed-tiny) { + background-size: auto !important; + background-position: -12px !important; +} + +:global(.ts-store-opinions-widget) { + display: flex; + flex-direction: row-reverse; +} + +:global(.ts-audited) { + display: flex; + justify-content: center !important; + flex-direction: column; + width: auto !important; + margin: 30px !important; + padding-right: 20px !important; +} +:global(.ts-768px) { + display: flex; + justify-content: center; +} + +:global(.ts-next-slide) { + right: -65px !important; +} +:global(.ts-prev-slide) { + left: -30px !important; +} +:global(.ts-prev-slide)::after { + content: ''; + width: 40px; + height: 40px; + display: block; + top: 0; + left: -14px; + position: absolute; +} +:global(.ts-next-slide)::after { + content: ''; + width: 40px; + height: 40px; + display: block; + top: 0; + right: -14px; + position: absolute; +} +:global(.ts-frame) { + width: 920px !important; +} +:global(.ts-trust-gray), +:global(.ts-opinion) { + width: 297px !important; +} +:global(.ts-trust-gray) { + background: #ffffff !important; + border: 1px solid #ced0ca !important; + border-radius: 6px !important; +} +:global(.ts-store-opinions-widget) { + max-width: 1300px; +} + +:gobal(.ts-customer-questions-form) h2 { + margin: 0; +} +:global(.ts-customer-questions) { + display: none !important; +} + +@media only screen and(max-width:1025px) { + :global(.trustvox-certificate__fixed-tiny) { + width: 100px !important; + background-size: auto !important; + background-position: -5px !important; + } +} +@media (max-width: 1024px) { + :global(.ts-store-opinions-widget) { + width: 610px; + overflow: hidden; + display: flex; + flex-direction: column-reverse; + } + :global(#_trustvox_colt), + :global(.ts-slider) { + display: flex; + justify-content: center; + align-items: center; + } + :global(.ts-audited) { + align-items: center; + } + :global(.ts-slider) { + width: 610px !important; + } +} + +@media (max-width: 800px) { + :global(.ts-audited) { + margin-top: 0 !important; + } +} + +@media (max-width: 500px) { + :global(.ts-store-opinions-widget) { + width: 300px; + overflow: hidden; + display: flex; + flex-direction: column-reverse; + } + :global(#_trustvox_colt), + :global(.ts-slider) { + display: flex; + justify-content: center; + align-items: center; + } + :global(.ts-audited) { + align-items: center; + } + :global(.ts-trust-gray), + :global(.ts-opinion) { + width: 230px !important; + } +} + +:global(.trustvox-shelf-container) { + display: table; +} diff --git a/react/components/product/ProductVideo/index.tsx b/react/components/product/ProductVideo/index.tsx new file mode 100644 index 00000000..f97ef317 --- /dev/null +++ b/react/components/product/ProductVideo/index.tsx @@ -0,0 +1,40 @@ +import React from 'react' +import { useProduct } from 'vtex.product-context' +import { getPropertyByName } from '../../../utils/getPropertyByName' +import type { IProductProperties } from '../../../typings/productsInfos' + +import styles from './styles.css' + +export const ProductVideo: React.FC = () => { + const context = useProduct() + + if (!context) return null + const product = context?.product + + const properties = product?.properties as IProductProperties[] | undefined + + if (!properties) return null + const videoId = getPropertyByName(properties, 'Vídeo') + + if (!videoId) return null + + return ( +
+

+ Veja o vídeo sobre o produto abaixo: +

+
+