diff --git a/assets/app.js b/assets/app.js index 5ec4312..eea036e 100644 --- a/assets/app.js +++ b/assets/app.js @@ -12,12 +12,11 @@ import './bootstrap.js'; import HeaderScript from '@components/Layout/Header/Header.js'; import MobileDrawer from './js/mobileDrawer'; -import filterSelectFunction from '@components/Molecules/Filters/FilterSelect/FilterSelect'; +import filterSelect from '@components/Molecules/Filters/FilterSelect/FilterSelect'; import { quantityButton } from '@components/Molecules/Button/button'; import { FieldInputFunction } from '@components/Molecules/Fields/FieldInput/FieldInput'; import { ModalFunction } from '@components/Molecules/Modal/Modal'; import { slider } from '@js/slider'; -import ProductGallery from '@components/Layout/ProductGallery/ProductGallery'; import PasswordControlsFunction from '@components/Molecules/PasswordControls/PasswordControls'; import headerButtonProfileFunction from '@components/Molecules/HeaderButton/HeaderButtonProfile'; @@ -28,10 +27,9 @@ function main() { HeaderScript(); MobileDrawer(); - filterSelectFunction(); + filterSelect(); quantityButton(); slider(); - ProductGallery(); PasswordControlsFunction(); StepsFunction(); FieldInputFunction(); diff --git a/assets/controllers/filters_controller.js b/assets/controllers/filters_controller.js new file mode 100644 index 0000000..dbef01c --- /dev/null +++ b/assets/controllers/filters_controller.js @@ -0,0 +1,21 @@ +import { Controller } from '@hotwired/stimulus'; +import { getComponent } from '@symfony/ux-live-component'; + +class FiltersController extends Controller { + async initialize() { + this.component = await getComponent(this.element); + } + + filterChange() { + this.component.action('save'); + } + + sortChange(e) { + this.component.action('save', { order: e.target.value }); + } + resetForm() { + this.component.action('save', { reset: true }); + } +} + +export default FiltersController; diff --git a/assets/css/form.css b/assets/css/form.css new file mode 100644 index 0000000..9e5c1bc --- /dev/null +++ b/assets/css/form.css @@ -0,0 +1,47 @@ +.FilterChoice { + &-label { + @apply flex sm:text-black sm:font-semibold paragraph-4 sm:mb-2; + } + + &-list { + @apply flex-wrap gap-2 divide-y divide-grey-lighter sm:divide-y-0 sm:flex; + } + + &--drawer { + .FilterChoice-label { + @media screen and (max-width: theme('screens.sm')) { + position: relative; + cursor: pointer; + outline: none; + border: 1px solid var(--grey-lighter); + padding: 16px 14px; + justify-content: space-between; + align-items: center; + font-size: 0; + &:before { + content: attr(data-select-label); + font-size: rem-convert(14px); + } + &:after { + content: ''; + display: block; + background: url('/assets/icons/chevron-small-down.svg') no-repeat + center; + height: rem-convert(20px); + width: rem-convert(20px); + } + } + } + + &.FilterChoice--rounded { + .FilterChoice-label { + @media screen and (max-width: theme('screens.md')) { + border-radius: 50px; + justify-content: center; + color: var(--dark); + border-color: currentColor; + } + } + } + } +} diff --git a/assets/css/mobileDrawer.css b/assets/css/mobileDrawer.css index 1cd0ddc..4e93697 100644 --- a/assets/css/mobileDrawer.css +++ b/assets/css/mobileDrawer.css @@ -1,4 +1,6 @@ .MobileDrawer { + @apply transition-transform translate-y-full; + position: fixed; left: 0; right: 0; @@ -9,10 +11,10 @@ padding-top: rem-convert(50px); padding-bottom: rem-convert(42px); border-radius: rem-convert(20px) rem-convert(20px) 0px 0px; - @apply transition-transform translate-y-full; z-index: 20; + &:before { - content: ""; + content: ''; position: absolute; top: rem-convert(16px); left: calc(50% - 21px); @@ -41,10 +43,6 @@ @apply translate-y-0; } - @screen md { - display: none; - } - &-overlay { position: fixed; top: 0; @@ -55,4 +53,70 @@ mix-blend-mode: multiply; z-index: 10; } + + &--reset-sm { + @screen sm { + all: revert; + + &:before { + content: none; + } + .MobileDrawer-header { + display: none; + } + & + .MobileDrawer-overlay { + display: none; + } + } + } + &--reset-md { + @screen md { + all: revert; + + &:before { + content: none; + } + .MobileDrawer-header { + display: none; + } + & + .MobileDrawer-overlay { + display: none; + } + } + } + + &--reset-lg { + @screen lg { + all: revert; + + &:before { + content: none; + } + + .MobileDrawer-header { + display: none; + } + & + .MobileDrawer-overlay { + display: none; + } + } + } + + &--reset-xl { + @screen xl { + all: revert; + + &:before { + content: none; + } + + .MobileDrawer-header { + display: none; + } + + & + .MobileDrawer-overlay { + display: none; + } + } + } } diff --git a/assets/css/pages/category.css b/assets/css/pages/category.css new file mode 100644 index 0000000..9806d43 --- /dev/null +++ b/assets/css/pages/category.css @@ -0,0 +1,73 @@ +.Category { + &-grid { + display: grid; + padding: 24px; + + @screen md { + padding: 24px 48px; + } + @screen lg { + padding: 44px 0; + grid-template-columns: 240px 1fr; + gap: 48px; + margin: auto; + max-width: calc(theme('screens.lg') - 80px); + } + + @screen xl { + gap: 66px; + max-width: calc(theme('screens.xl') - 84px); + } + + @screen 2xl { + grid-template-columns: 310px 1fr; + max-width: calc(theme('screens.2xl') - 100px); + } + } +} + +.CategoryFilter { + display: block; + color: var(--black); + + @screen lg { + padding: 0; + margin-top: 48px; + transform: none; + position: relative; + } + + &:before { + @apply lg:hidden; + } + &-erase { + @screen lg { + position: absolute; + top: 0; + right: 0; + } + + &::empty { + display: none; + } + } + + .FilterPill { + background-color: white; + } + + .Accordion--filter { + @apply lg:bg-white; + + .Accordion-summary, + .Accordion-content { + @apply lg:px-0; + } + } + + .Fieldset { + &-group { + @apply flex flex-col gap-1 lg:divide-y lg:gap-0; + } + } +} diff --git a/assets/css/pages/product.css b/assets/css/pages/product.css index 3db8685..e97f4ec 100644 --- a/assets/css/pages/product.css +++ b/assets/css/pages/product.css @@ -1,10 +1,10 @@ .Product { - &-imageContainer { - width: 594px; - img { - width: 100%; - } - } + &-imageContainer { + width: 594px; + img { + width: 100%; + } + } &Gallery-item { border: 1px solid transparent; @@ -13,3 +13,91 @@ } } } + +.ProductPage { + color: var(--black); + &-grid { + display: grid; + + @screen lg { + grid-template-rows: auto auto; + grid-template-columns: repeat(12, 1fr); + gap: 46px 54px; + margin-bottom: 90px; + } + @screen xl { + gap: 16px 20px; + } + } + + &-gallery { + order: 1; + position: relative; + right: 50%; + left: 50%; + order: 1; + width: 100vw; + margin-right: -50vw; + margin-left: -50vw; + + @screen sm { + position: static; + width: auto; + margin: 0; + } + @screen lg { + grid-column: 1 / 7; + } + @screen xl { + grid-column: 1 / 8; + } + } + + &-infos { + order: 2; + margin-top: 30px; + + @screen lg { + grid-row: 1 / 3; + grid-column: 7 / 13; + margin: 0; + } + + @screen xl { + grid-column: 9 / 13; + } + } + + &-description { + order: 3; + @screen lg { + grid-column: 1 / 7; + } + @screen xl { + grid-column: 2 / 8; + } + } +} + +.PseSelector { + display: grid; + gap: 30px; + + legend { + @sreen lg { + display: none; + } + } + + .Fieldset { + &-group { + @apply grid sm:gap-4; + + li:last-child { + .FilterChoice-label { + border-top: none; + } + } + } + } +} diff --git a/assets/icons/arrow-right.svg b/assets/icons/arrow-right.svg index 6035528..c2979fe 100644 --- a/assets/icons/arrow-right.svg +++ b/assets/icons/arrow-right.svg @@ -1,3 +1,5 @@ - - + + diff --git a/assets/icons/bell.svg b/assets/icons/bell.svg index 4ebf4d7..6e4f673 100644 --- a/assets/icons/bell.svg +++ b/assets/icons/bell.svg @@ -1,3 +1,5 @@ - - - + + + \ No newline at end of file diff --git a/assets/icons/checkmark.svg b/assets/icons/checkmark.svg index 208d445..dd5037e 100644 --- a/assets/icons/checkmark.svg +++ b/assets/icons/checkmark.svg @@ -1,4 +1,6 @@ - - - + + + diff --git a/assets/icons/chevron-down.svg b/assets/icons/chevron-down.svg index 27e94d8..794b497 100644 --- a/assets/icons/chevron-down.svg +++ b/assets/icons/chevron-down.svg @@ -1,3 +1,5 @@ - - + + diff --git a/assets/js/mobileDrawer.js b/assets/js/mobileDrawer.js index 5c7db41..d023239 100644 --- a/assets/js/mobileDrawer.js +++ b/assets/js/mobileDrawer.js @@ -2,7 +2,7 @@ export default function MobileDrawer() { const toggleDrawers = document.querySelectorAll('[data-drawer-toggle]'); const closeDrawers = document.querySelectorAll('[data-drawer-close]'); const drawers = document.querySelectorAll('.MobileDrawer'); - const drawerOptions = document.querySelectorAll('.FilterSelect-option'); + const drawerOptions = document.querySelectorAll('[data-select-option]'); toggleDrawers.forEach(function (drawer) { drawer.addEventListener('click', () => { @@ -15,9 +15,7 @@ export default function MobileDrawer() { }); closeDrawers.forEach(function (drawer) { drawer.addEventListener('click', () => { - console.log({drawer}); const parent = drawer.closest('.MobileDrawer'); - console.log({parent}); if (!parent) return; closeDrawer(parent); @@ -53,22 +51,22 @@ export default function MobileDrawer() { function openDrawer(currentDrawer) { const isOpen = currentDrawer.classList.toggle('MobileDrawer-show'); - toggleOverlay(isOpen); + document.body.classList.toggle('locked'); + toggleOverlay(isOpen, currentDrawer); } function closeDrawer(currentDrawer) { currentDrawer.classList.remove('MobileDrawer-show'); + document.body.classList.remove('locked'); toggleOverlay(false); } -function toggleOverlay(open) { +function toggleOverlay(open, currentDrawer) { if (open) { const div = document.createElement('div'); div.classList.add('MobileDrawer-overlay'); - document.body.prepend(div); + currentDrawer.parentNode.insertBefore(div, currentDrawer.nextSibling); return; } - - console.log('close overlays'); - document.querySelector('.MobileDrawer-overlay').remove(); + document.querySelector('.MobileDrawer-overlay')?.remove(); } diff --git a/assets/js/routes/category.js b/assets/js/routes/category.js new file mode 100644 index 0000000..a5e7733 --- /dev/null +++ b/assets/js/routes/category.js @@ -0,0 +1 @@ +import '@assets/css/pages/category.css'; diff --git a/assets/js/routes/product.js b/assets/js/routes/product.js index 0e6f76f..cb3db9d 100644 --- a/assets/js/routes/product.js +++ b/assets/js/routes/product.js @@ -1,5 +1,5 @@ -import ProductGallery from "@components/Layout/ProductGallery/ProductGallery"; -import PseSelectorRoot from "@react/Layout/PseSelector/PseSelector"; +import '@splidejs/splide/css/core'; +import '@assets/css/pages/product.css'; +import ProductGallery from '@components/Layout/ProductGallery/ProductGallery'; ProductGallery(); -PseSelectorRoot(); diff --git a/base.html.twig b/base.html.twig index f1ed755..6264ee9 100644 --- a/base.html.twig +++ b/base.html.twig @@ -17,7 +17,7 @@ {% block header %} - {% include '@components/Layout/Header/Header.html.twig' with { type: "searchbar" } %} + {% include '@components/Layout/Header/Header.html.twig' with { type: "generic" } %} {% endblock %} {% block body %}{% endblock %} @@ -26,6 +26,6 @@ {% include '@components/Layout/Footer/Footer.html.twig' %} {% endblock %} - {% block modals %}{% endblock %} + {% block modals %}{% endblock %} diff --git a/category.html.twig b/category.html.twig index 1a0f9d8..bf6f368 100644 --- a/category.html.twig +++ b/category.html.twig @@ -1,14 +1,23 @@ {% extends 'base.html.twig' %} {% set page = app.request.get('page')|default(1) %} -{% block title %}{{ 'Category'|trans }} -{% endblock %} +{% set categoryId = attr('category', 'id') %} +{% set breadcrumb = [ + {label: 'Home'|trans, href:"/"}, + {label: attr('category', 'title')} +] %} -{% block body %} - {% set products = resources('/api/front/products', {'productCategories.category.id': attr('category', 'id'), itemsPerPage:9, page: page}) %} +{% block stylesheets %} + {{ parent() }} + {{ encore_entry_link_tags('category') }} +{% endblock %} - {% include '@components/Layout/Subheader/Category/SubheaderCategory.html.twig' with {title: attr('category', 'title'), description: attr('category', 'description'), nbProducts: products|length} %} - {{ component('Flexy:Layout:CategoryProduct', {categoryId: attr('category', 'id'), page}) }} +{% block title %} + {{ 'Category'|trans }} +{% endblock %} +{% block body %} + {% include '@components/Layout/Subheader/Category/SubheaderCategory.html.twig' with {title: attr('category', 'title'), description: attr('category', 'chapo'), nbProducts: 9, breadcrumb} %} + {{ component('Flexy:Layout:CategoryProducts', {categoryId, page}) }} {% include '@components/Layout/Reinsurance/Reinsurance.html.twig' with { data: [ { strongText: 'Free delivery' | trans, diff --git a/components/Layout/CategoryProduct/CategoryProduct.html.twig b/components/Layout/CategoryProduct/CategoryProduct.html.twig deleted file mode 100644 index 9abb0db..0000000 --- a/components/Layout/CategoryProduct/CategoryProduct.html.twig +++ /dev/null @@ -1,70 +0,0 @@ -{% set products = products|default([]) %} - -
- - -
- - -
- {% for product in products %} - {% include '@components/Organisms/ProductCard/ProductCard.html.twig' with product|merge({displayWishButton: true}) %} - {% endfor %} -
- -
- {% include '@components/Molecules/Pagination/Pagination.html.twig' with { - prevText: 'Previous' | trans, - nextText: 'Next' | trans, - currentPage: page, - totalPages: 3 - } %} -
- -

- {{ attr('category', 'description') }} -

-
-
diff --git a/components/Layout/CategoryProducts/CategoryProducts.html.twig b/components/Layout/CategoryProducts/CategoryProducts.html.twig new file mode 100644 index 0000000..9418114 --- /dev/null +++ b/components/Layout/CategoryProducts/CategoryProducts.html.twig @@ -0,0 +1,59 @@ +{% set products = products|default([]) %} +{% set filtersCount = filters_count(formValues|filter(f => f is iterable)) %} + +
+ {% if filters %} +
+
+ +
+ {{ form(form)}} +
+ + {% if filtersCount %} + +
+
+ {% endif %} +
+ + +
+ {% for product in products %} + {% include '@components/Organisms/ProductCard/ProductCard.html.twig' with product|merge({displayWishButton: true}) %} + {% endfor %} +
+ +
+ {% include '@components/Molecules/Pagination/Pagination.html.twig' with { + prevText: 'Previous' | trans, + nextText: 'Next' | trans, + currentPage: page, + totalPages: 3 + } %} +
+
+ {% if attr('category', 'description') %} +
+ {{ attr('category', 'description') }} +
+ {% endif %} + {{ component('Flexy:Components:Blocks', {item_type: 'category', item_id: categoryId}) }} +
+ +
+
diff --git a/components/Layout/CrossSelling/CrossSelling.html.twig b/components/Layout/CrossSelling/CrossSelling.html.twig index f33fa63..239da48 100644 --- a/components/Layout/CrossSelling/CrossSelling.html.twig +++ b/components/Layout/CrossSelling/CrossSelling.html.twig @@ -7,13 +7,13 @@
{{ title }}
{% for product in this.products %} - {% include '@components/Organisms/ProductCard/ProductCard.html.twig' with product|merge({displayWishButton: true}) %} + {{ component('Flexy:Components:ProductCard', {product}) }} {% endfor %}
- {% if button %} -
- {% include '@components/Molecules/Button/Button.html.twig' with {text: button.label, href: button.href,icon_right:'chevron-right', variant:'secondary'} %} -
- {% endif %} + {% if button %} +
+ {% include '@components/Molecules/Button/Button.html.twig' with {text: button.label, href: button.href,icon_right:'chevron-right', variant:'secondary'} %} +
+ {% endif %} {% endif %} diff --git a/components/Layout/Header/Header.html.twig b/components/Layout/Header/Header.html.twig index 3e7ea64..aeed976 100644 --- a/components/Layout/Header/Header.html.twig +++ b/components/Layout/Header/Header.html.twig @@ -1,7 +1,7 @@ {% set type = type|default("generic") %} {% set categories = resources('/api/front/categories') %} -
+
{% if type == "searchbar" %}