diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 19a3818..bdbdb91 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -6,7 +6,8 @@ "Bash(git commit:*)", "Bash(find:*)", "Bash(curl:*)", - "WebFetch(domain:snipcart.com)" + "WebFetch(domain:snipcart.com)", + "Bash(grep:*)" ] } } diff --git a/.gitignore b/.gitignore index 975043c..d2b4a11 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,9 @@ Icon # Guide d'intégration (contient des informations sensibles) # --------------- -GUIDE-INTEGRATION-MONDIAL-RELAY.md \ No newline at end of file +GUIDE-INTEGRATION-MONDIAL-RELAY.md + +# Claude settings +# --------------- +.claude +/.claude/* \ No newline at end of file diff --git a/assets/css/components/_shopify-buy-button.scss b/assets/css/components/_shopify-buy-button.scss new file mode 100644 index 0000000..ca48dde --- /dev/null +++ b/assets/css/components/_shopify-buy-button.scss @@ -0,0 +1,68 @@ +.product-purchase { + margin-top: 2rem; +} + +.product-stock-info { + margin-bottom: 1rem; +} + +.stock-status { + font-size: 0.9rem; + font-weight: 600; + margin: 0; +} + +.stock-status.in-stock { + color: #00cc00; +} + +.stock-status.low-stock { + color: #ff9900; +} + +.stock-status.out-of-stock { + color: #ff3333; +} + +.btn-add-to-cart { + font-family: "Open Sans", sans-serif; + font-weight: bold; + font-size: 1rem; + color: #000000; + background-color: #00ff00; + border: none; + border-radius: 40px; + padding: 12px 34px; + cursor: pointer; + transition: background-color 0.3s ease; + width: 100%; + max-width: 300px; +} + +.btn-add-to-cart:hover:not(:disabled) { + background-color: #00e600; +} + +.btn-add-to-cart:focus { + outline: 2px solid #00e600; + outline-offset: 2px; +} + +.btn-add-to-cart:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.btn-add-to-cart.success { + background-color: #00cc00; +} + +.btn-add-to-cart.error { + background-color: #ff3333; + color: #ffffff; +} + +.btn-add-to-cart.out-of-stock { + background-color: #cccccc; + color: #666666; +} diff --git a/assets/css/components/_shopify-cart-drawer.scss b/assets/css/components/_shopify-cart-drawer.scss new file mode 100644 index 0000000..c0b8b02 --- /dev/null +++ b/assets/css/components/_shopify-cart-drawer.scss @@ -0,0 +1,254 @@ +/* Cart Drawer Styles */ +.cart-drawer { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 9999; + pointer-events: none; + opacity: 0; + transition: opacity 0.3s ease; + color: #000; + + &.is-open { + pointer-events: auto; + opacity: 1; + + .cart-drawer__panel { + transform: translateX(0); + } + } + + &__overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + cursor: pointer; + } + + &__panel { + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 100%; + max-width: 420px; + background-color: #ffffff; + box-shadow: -2px 0 8px rgba(0, 0, 0, 0.15); + display: flex; + flex-direction: column; + transform: translateX(100%); + transition: transform 0.3s ease; + + @media (max-width: 768px) { + max-width: 100%; + } + } + + &__header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1.5rem; + border-bottom: 1px solid #e0e0e0; + + h3 { + margin: 0; + font-size: 1.5rem; + font-weight: bold; + } + } + + &__close { + background: none; + border: none; + cursor: pointer; + padding: 0.5rem; + display: flex; + align-items: center; + justify-content: center; + transition: opacity 0.2s; + + &:hover { + opacity: 0.7; + } + } + + &__content { + flex: 1; + overflow-y: auto; + padding: 1.5rem; + + &.is-loading { + opacity: 0.5; + pointer-events: none; + } + } + + &__empty { + text-align: center; + padding: 3rem 1rem; + color: #666; + + &.hidden { + display: none; + } + } + + &__items { + display: flex; + flex-direction: column; + gap: 1rem; + + &.hidden { + display: none; + } + } + + &__footer { + border-top: 1px solid #e0e0e0; + padding: 1.5rem; + display: flex; + flex-direction: column; + gap: 1rem; + } + + &__total { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 1.125rem; + font-weight: bold; + + &-label { + color: #000; + } + + &-amount { + color: #000; + font-size: 1.25rem; + } + } + + &__checkout-btn { + width: 100%; + font-family: "Open Sans", sans-serif; + font-weight: bold; + font-size: 1rem; + color: #000000; + background-color: #00ff00; + border: none; + border-radius: 40px; + padding: 14px 34px; + cursor: pointer; + transition: background-color 0.3s ease; + + &:hover:not(:disabled) { + background-color: #00e600; + } + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + } + } +} + +// Cart Item +.cart-item { + display: flex; + gap: 1rem; + padding: 1rem; + border: 1px solid #e0e0e0; + border-radius: 8px; + + &__image { + width: 80px; + height: 80px; + object-fit: cover; + border-radius: 4px; + flex-shrink: 0; + } + + &__details { + flex: 1; + display: flex; + flex-direction: column; + gap: 0.5rem; + } + + &__title { + font-weight: 600; + margin: 0; + font-size: 1rem; + } + + &__variant { + font-size: 0.875rem; + color: #666; + margin: 0; + } + + &__price { + font-weight: bold; + color: #000; + } + + &__quantity { + display: flex; + align-items: center; + gap: 0.5rem; + margin-top: auto; + } + + &__qty-btn { + width: 28px; + height: 28px; + border: 1px solid #000; + background: #fff; + color: #000; + border-radius: 4px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 1rem; + font-weight: bold; + transition: all 0.2s; + + &:hover:not(:disabled) { + background-color: #000; + color: #fff; + } + + &:disabled { + opacity: 0.4; + cursor: not-allowed; + } + } + + &__qty-value { + min-width: 30px; + text-align: center; + font-weight: 600; + } + + &__remove { + background: none; + border: none; + color: #ff3333; + cursor: pointer; + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + text-decoration: underline; + align-self: flex-start; + + &:hover { + color: #cc0000; + } + } +} diff --git a/assets/css/partials/_site-header.scss b/assets/css/partials/_site-header.scss index cf92821..f74bf25 100644 --- a/assets/css/partials/_site-header.scss +++ b/assets/css/partials/_site-header.scss @@ -43,14 +43,20 @@ } } - .header-left, - .header-right { + .header-left { width: 90px; display: flex; align-items: center; justify-content: flex-end; } + .header-right { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 1rem; + } + .header-center { display: flex; flex-direction: column; @@ -75,4 +81,39 @@ color: var(--color-txt); } } + + .header-cart-btn { + background: none; + border: none; + cursor: pointer; + font-size: 0.875rem; + text-transform: uppercase; + color: var(--color-txt); + padding: 0; + line-height: 1; + display: flex; + align-items: center; + gap: 0.25rem; + transition: opacity 0.2s; + + &:hover { + opacity: 0.7; + } + } + + .header-cart-count { + font-weight: normal; + + &:empty { + display: none; + } + + &:not(:empty)::before { + content: '('; + } + + &:not(:empty)::after { + content: ')'; + } + } } diff --git a/assets/css/style.css b/assets/css/style.css index 824c345..9d6f37c 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -524,13 +524,18 @@ main { #site-header.is-shrinked .site-title { width: 80px !important; } -#site-header .header-left, -#site-header .header-right { +#site-header .header-left { width: 90px; display: flex; align-items: center; justify-content: flex-end; } +#site-header .header-right { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 1rem; +} #site-header .header-center { display: flex; flex-direction: column; @@ -553,6 +558,35 @@ main { #site-header #toggle-lang li.is-selected { color: var(--color-txt); } +#site-header .header-cart-btn { + background: none; + border: none; + cursor: pointer; + font-size: 0.875rem; + text-transform: uppercase; + color: var(--color-txt); + padding: 0; + line-height: 1; + display: flex; + align-items: center; + gap: 0.25rem; + transition: opacity 0.2s; +} +#site-header .header-cart-btn:hover { + opacity: 0.7; +} +#site-header .header-cart-count { + font-weight: normal; +} +#site-header .header-cart-count:empty { + display: none; +} +#site-header .header-cart-count:not(:empty)::before { + content: "("; +} +#site-header .header-cart-count:not(:empty)::after { + content: ")"; +} #site-footer { background-color: black; @@ -1019,13 +1053,6 @@ body.is-fullscreen { margin-right: auto; } -.section__product, -.store__nav { - max-width: 1200px; - margin-left: auto; - margin-right: auto; -} - .store__nav { padding-top: calc(var(--spacing) * 1); padding-bottom: calc(var(--spacing) * 0.5); @@ -1035,11 +1062,17 @@ body.is-fullscreen { .store__nav a { text-decoration: none; } +.store__nav a::before { + content: "← "; +} .store__nav a:hover { text-decoration: underline; } -.store__nav a::before { - content: "← "; +@media screen and (max-width: 720px) { + .store__nav a { + padding-top: 0; + font-size: var(--fs-small); + } } .section__product .details ul { @@ -1048,122 +1081,7 @@ body.is-fullscreen { .section__product .details ul li { padding-bottom: 0.2em; } - -.product-options__list { - list-style: none; - display: flex; - gap: 2ch; -} -.product-options__list li { - position: relative; -} -.product-options__list li input[type=radio] { - position: fixed; - opacity: 0; - pointer-events: none; -} -.product-options__list li label { - font-family: var(--title); - font-size: var(--fs-normal); - height: 4ch; - width: 4ch; - border-radius: 50%; - border: var(--border); - border-color: transparent; - display: flex; - align-items: center; - justify-content: center; - padding-top: 0px; - cursor: pointer; -} -.product-options__list li input[type=radio]:checked + label { - border-color: var(--color-txt); -} -.product-options__list li input[type=radio]:not(:checked) + label:hover { - border-color: var(--grey-600); - background-color: var(--grey-800); -} - -.product-gallery { - position: relative; - aspect-ratio: 4/3; -} -.product-gallery .swiper-slide { - width: 100%; -} -.product-gallery .swiper-slide figure { - aspect-ratio: 4/3; - width: 100%; - height: 100%; -} -.product-gallery .swiper-slide figure img { - width: 100%; - height: 100%; - -o-object-fit: contain; - object-fit: contain; -} -.product-gallery .swiper-button-prev, -.product-gallery .swiper-button-next { - color: var(--color-txt); - width: 20px; - height: 20px; -} -.product-gallery .swiper-button-prev:after, -.product-gallery .swiper-button-next:after { - font-size: 20px; - font-weight: bold; -} -.product-gallery .swiper-button-prev:hover, -.product-gallery .swiper-button-next:hover { - opacity: 0.7; -} -.product-gallery .swiper-pagination { - position: relative; - margin-top: calc(var(--spacing) * 0.5); - bottom: 0; -} -.product-gallery .swiper-pagination .swiper-pagination-bullet { - width: 8px; - height: 8px; - background: var(--grey-600); - opacity: 0.5; - transition: opacity 0.3s; -} -.product-gallery .swiper-pagination .swiper-pagination-bullet:hover { - opacity: 0.7; -} -.product-gallery .swiper-pagination .swiper-pagination-bullet-active { - background: var(--color-txt); - opacity: 1; -} - -.hero { - margin-bottom: calc(var(--spacing) * 1); - padding: calc(var(--spacing) * 0.5) 0; - border-top: var(--border-light); - border-bottom: var(--border-light); -} -.hero .p__baseline-big { - margin: 0; - text-align: left; -} - -.add-to-cart { - margin: 0; - border-bottom: var(--border-light); - padding: calc(var(--spacing) * 0.5) 0; -} - -.product-options { - border-bottom: var(--border-light); - padding: calc(var(--spacing) * 0.25) 0; -} - @media screen and (max-width: 720px) { - .store__nav a { - padding-top: 0; - font-size: var(--fs-small); - } .section__product { display: flex; flex-direction: column; @@ -1202,7 +1120,7 @@ body.is-fullscreen { } } @media screen and (min-width: 720px) { - .section__product { + .section__product .product-content { display: grid; grid-template-columns: 1fr 1fr; gap: calc(var(--padding-body) * 2); @@ -1221,10 +1139,123 @@ body.is-fullscreen { display: flex; flex-direction: column; } +} + +.product-options { + border-bottom: var(--border-light); + padding: calc(var(--spacing) * 0.25) 0; +} + +.product-options__list { + list-style: none; + display: flex; + gap: 2ch; +} +.product-options__list li { + position: relative; +} +.product-options__list li input[type=radio] { + position: fixed; + opacity: 0; + pointer-events: none; +} +.product-options__list li input[type=radio]:checked + label { + border-color: var(--color-txt); +} +.product-options__list li input[type=radio]:not(:checked) + label:hover { + border-color: var(--grey-600); + background-color: var(--grey-800); +} +.product-options__list li label { + font-family: var(--title); + font-size: var(--fs-normal); + height: 4ch; + width: 4ch; + border-radius: 50%; + border: var(--border); + border-color: transparent; + display: flex; + align-items: center; + justify-content: center; + padding-top: 0px; + cursor: pointer; +} + +.product-gallery { + position: relative; + aspect-ratio: 4/3; +} +.product-gallery .swiper-slide { + width: 100%; +} +.product-gallery .swiper-slide figure { + aspect-ratio: 4/3; + width: 100%; + height: 100%; +} +.product-gallery .swiper-slide figure img { + width: 100%; + height: 100%; + -o-object-fit: contain; + object-fit: contain; +} +@media screen and (min-width: 720px) { .product-gallery .swiper-slide figure { width: calc(100% - 60px); } } +.product-gallery .swiper-button-prev, +.product-gallery .swiper-button-next { + color: var(--color-txt); + width: 20px; + height: 20px; +} +.product-gallery .swiper-button-prev:after, +.product-gallery .swiper-button-next:after { + font-size: 20px; + font-weight: bold; +} +.product-gallery .swiper-button-prev:hover, +.product-gallery .swiper-button-next:hover { + opacity: 0.7; +} +.product-gallery .swiper-pagination { + position: relative; + margin-top: calc(var(--spacing) * 0.5); + bottom: 0; +} +.product-gallery .swiper-pagination .swiper-pagination-bullet { + width: 8px; + height: 8px; + background: var(--grey-600); + opacity: 0.5; + transition: opacity 0.3s; +} +.product-gallery .swiper-pagination .swiper-pagination-bullet:hover { + opacity: 0.7; +} +.product-gallery .swiper-pagination .swiper-pagination-bullet.swiper-pagination-bullet-active { + background: var(--color-txt); + opacity: 1; +} + +.hero { + margin-bottom: calc(var(--spacing) * 1); + padding: calc(var(--spacing) * 0.5) 0; + border-top: var(--border-light); + border-bottom: var(--border-light); +} +.hero .p__baseline-big { + margin: 0; + text-align: left; +} + +.add-to-cart { + margin: 0; + border-bottom: var(--border-light); + padding: calc(var(--spacing) * 0.5) 0; +} + [data-template=thanks] .thanks-page { min-height: 60vh; display: flex; @@ -1258,8 +1289,296 @@ body.is-fullscreen { margin-top: calc(var(--spacing) * 4); } -.snipcart-modal__container { - z-index: 1000; +.product-purchase { + margin-top: 2rem; +} + +.product-stock-info { + margin-bottom: 1rem; +} + +.stock-status { + font-size: 0.9rem; + font-weight: 600; + margin: 0; +} + +.stock-status.in-stock { + color: #00cc00; +} + +.stock-status.low-stock { + color: #ff9900; +} + +.stock-status.out-of-stock { + color: #ff3333; +} + +.btn-add-to-cart { + font-family: "Open Sans", sans-serif; + font-weight: bold; + font-size: 1rem; + color: #000000; + background-color: #00ff00; + border: none; + border-radius: 40px; + padding: 12px 34px; + cursor: pointer; + transition: background-color 0.3s ease; + width: 100%; + max-width: 300px; +} + +.btn-add-to-cart:hover:not(:disabled) { + background-color: #00e600; +} + +.btn-add-to-cart:focus { + outline: 2px solid #00e600; + outline-offset: 2px; +} + +.btn-add-to-cart:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.btn-add-to-cart.success { + background-color: #00cc00; +} + +.btn-add-to-cart.error { + background-color: #ff3333; + color: #ffffff; +} + +.btn-add-to-cart.out-of-stock { + background-color: #cccccc; + color: #666666; +} + +/* Cart Drawer Styles */ +.cart-drawer { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 9999; + pointer-events: none; + opacity: 0; + transition: opacity 0.3s ease; + color: #000; +} +.cart-drawer.is-open { + pointer-events: auto; + opacity: 1; +} +.cart-drawer.is-open .cart-drawer__panel { + transform: translateX(0); +} +.cart-drawer__overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + cursor: pointer; +} +.cart-drawer__panel { + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 100%; + max-width: 420px; + background-color: #ffffff; + box-shadow: -2px 0 8px rgba(0, 0, 0, 0.15); + display: flex; + flex-direction: column; + transform: translateX(100%); + transition: transform 0.3s ease; +} +@media (max-width: 768px) { + .cart-drawer__panel { + max-width: 100%; + } +} +.cart-drawer__header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1.5rem; + border-bottom: 1px solid #e0e0e0; +} +.cart-drawer__header h3 { + margin: 0; + font-size: 1.5rem; + font-weight: bold; +} +.cart-drawer__close { + background: none; + border: none; + cursor: pointer; + padding: 0.5rem; + display: flex; + align-items: center; + justify-content: center; + transition: opacity 0.2s; +} +.cart-drawer__close:hover { + opacity: 0.7; +} +.cart-drawer__content { + flex: 1; + overflow-y: auto; + padding: 1.5rem; +} +.cart-drawer__content.is-loading { + opacity: 0.5; + pointer-events: none; +} +.cart-drawer__empty { + text-align: center; + padding: 3rem 1rem; + color: #666; +} +.cart-drawer__empty.hidden { + display: none; +} +.cart-drawer__items { + display: flex; + flex-direction: column; + gap: 1rem; +} +.cart-drawer__items.hidden { + display: none; +} +.cart-drawer__footer { + border-top: 1px solid #e0e0e0; + padding: 1.5rem; + display: flex; + flex-direction: column; + gap: 1rem; +} +.cart-drawer__total { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 1.125rem; + font-weight: bold; +} +.cart-drawer__total-label { + color: #000; +} +.cart-drawer__total-amount { + color: #000; + font-size: 1.25rem; +} +.cart-drawer__checkout-btn { + width: 100%; + font-family: "Open Sans", sans-serif; + font-weight: bold; + font-size: 1rem; + color: #000000; + background-color: #00ff00; + border: none; + border-radius: 40px; + padding: 14px 34px; + cursor: pointer; + transition: background-color 0.3s ease; +} +.cart-drawer__checkout-btn:hover:not(:disabled) { + background-color: #00e600; +} +.cart-drawer__checkout-btn:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.cart-item { + display: flex; + gap: 1rem; + padding: 1rem; + border: 1px solid #e0e0e0; + border-radius: 8px; +} +.cart-item__image { + width: 80px; + height: 80px; + -o-object-fit: cover; + object-fit: cover; + border-radius: 4px; + flex-shrink: 0; +} +.cart-item__details { + flex: 1; + display: flex; + flex-direction: column; + gap: 0.5rem; +} +.cart-item__title { + font-weight: 600; + margin: 0; + font-size: 1rem; +} +.cart-item__variant { + font-size: 0.875rem; + color: #666; + margin: 0; +} +.cart-item__price { + font-weight: bold; + color: #000; +} +.cart-item__quantity { + display: flex; + align-items: center; + gap: 0.5rem; + margin-top: auto; +} +.cart-item__qty-btn { + width: 28px; + height: 28px; + border: 1px solid #000; + background: #fff; + color: #000; + border-radius: 4px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 1rem; + font-weight: bold; + transition: all 0.2s; +} +.cart-item__qty-btn:hover:not(:disabled) { + background-color: #000; + color: #fff; +} +.cart-item__qty-btn:disabled { + opacity: 0.4; + cursor: not-allowed; +} +.cart-item__qty-value { + min-width: 30px; + text-align: center; + font-weight: 600; +} +.cart-item__remove { + background: none; + border: none; + color: #ff3333; + cursor: pointer; + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + text-decoration: underline; + align-self: flex-start; +} +.cart-item__remove:hover { + color: #cc0000; } [data-template=subscription-newsletter] main { diff --git a/assets/css/style.css.map b/assets/css/style.css.map index c3b0a2e..8439478 100644 --- a/assets/css/style.css.map +++ b/assets/css/style.css.map @@ -1 +1 @@ -{"version":3,"sources":["style.css","base/_var.scss","base/_body.scss","components/_nav-tabs.scss","components/_btn--default.scss","components/_btn--don.scss","components/_form-newsletter.scss","components/_gauge.scss","components/_text.scss","partials/_site-header.scss","partials/_site-footer.scss","template/support/_layout.scss","template/support/_section--donation.scss","template/support/_section--comments.scss","template/support/_section--questions.scss","template/support/_section--video.scss","template/shop/_layout.scss","template/shop/_section--product.scss","template/shop/_thanks.scss","template/shop/_snipcart.scss","template/subscription-newsletter/_layout.scss"],"names":[],"mappings":"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","file":"style.css"} \ No newline at end of file +{"version":3,"sources":["style.css","base/_var.scss","base/_body.scss","components/_nav-tabs.scss","components/_btn--default.scss","components/_btn--don.scss","components/_form-newsletter.scss","components/_gauge.scss","components/_text.scss","partials/_site-header.scss","partials/_site-footer.scss","template/support/_layout.scss","template/support/_section--donation.scss","template/support/_section--comments.scss","template/support/_section--questions.scss","template/support/_section--video.scss","template/shop/_layout.scss","template/shop/_section--product.scss","template/shop/_thanks.scss","components/_shopify-buy-button.scss","components/_shopify-cart-drawer.scss","template/subscription-newsletter/_layout.scss"],"names":[],"mappings":"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","file":"style.css"} \ No newline at end of file diff --git a/assets/css/style.scss b/assets/css/style.scss index 9687a73..334ba35 100644 --- a/assets/css/style.scss +++ b/assets/css/style.scss @@ -22,6 +22,7 @@ @import "template/shop/layout"; @import "template/shop/section--product"; @import "template/shop/thanks"; -@import "template/shop/snipcart"; +@import "components/shopify-buy-button.scss"; +@import "components/shopify-cart-drawer.scss"; @import "template/subscription-newsletter/layout"; diff --git a/assets/css/template/shop/_section--product.scss b/assets/css/template/shop/_section--product.scss index 82790ac..972dae8 100644 --- a/assets/css/template/shop/_section--product.scss +++ b/assets/css/template/shop/_section--product.scss @@ -1,12 +1,3 @@ -.section__product, -.store__nav{ - max-width: 1200px; - margin-left: auto; - margin-right: auto; -} - - - .section__product, .store__nav { max-width: 1200px; @@ -14,10 +5,6 @@ margin-right: auto; } - - - - .store__nav { padding-top: calc(var(--spacing) * 1); padding-bottom: calc(var(--spacing) * 0.5); @@ -27,174 +14,35 @@ a { text-decoration: none; + &::before { + content: "← "; + } + &:hover { text-decoration: underline; } } - a::before { - content: "← "; - } -} - - - -.section__product .details { - // margin-bottom: calc(var(--spacing) * 2); - - ul{ - margin-left: 2ch; - li{ - padding-bottom: 0.2em; + @media #{$small} { + a { + padding-top: 0; + font-size: var(--fs-small); } } } +.section__product { + .details { + ul { + margin-left: 2ch; -.product-options__list { - list-style: none; - display: flex; - gap: 2ch; - li { - position: relative; - - input[type="radio"] { - position: fixed; - opacity: 0; - pointer-events: none; - } - - label { - font-family: var(--title); - font-size: var(--fs-normal); - height: 4ch; - width: 4ch; - border-radius: 50%; - border: var(--border); - border-color: transparent; - display: flex; - align-items: center; - justify-content: center; - padding-top: 0px; - cursor: pointer; - } - - input[type="radio"]:checked + label { - border-color: var(--color-txt); - } - - input[type="radio"]:not(:checked) + label:hover { - border-color: var(--grey-600); - background-color: var(--grey-800); - } - } - } - - - - - - - - - -.product-gallery { - position: relative; - aspect-ratio: 4 / 3; - - .swiper-slide { - width: 100%; - - figure { - - aspect-ratio: 4 / 3; - width: 100%; - height: 100%; - - img { - width: 100%; - height: 100%; - object-fit: contain; + padding-bottom: 0.2em; } } } - // Swiper navigation arrows - .swiper-button-prev, - .swiper-button-next { - color: var(--color-txt); - width: 20px; - height: 20px; - - &:after { - font-size: 20px; - font-weight: bold; - } - - &:hover { - opacity: 0.7; - } - } - - // Swiper pagination dots - .swiper-pagination { - position: relative; - margin-top: calc(var(--spacing) * 0.5); - bottom: 0; - - .swiper-pagination-bullet { - width: 8px; - height: 8px; - background: var(--grey-600); - opacity: 0.5; - transition: opacity 0.3s; - - &:hover { - opacity: 0.7; - } - } - - .swiper-pagination-bullet-active { - background: var(--color-txt); - opacity: 1; - } - } -} - - - .hero { - margin-bottom: calc(var(--spacing) * 1); - padding: calc(var(--spacing) * 0.5) 0; - border-top: var(--border-light); - border-bottom: var(--border-light); - - .p__baseline-big { - margin: 0; - text-align: left; - } - } - - .add-to-cart { - margin: 0; - border-bottom: var(--border-light); - padding: calc(var(--spacing) * 0.5) 0; - } - - .product-options { - border-bottom: var(--border-light); - padding: calc(var(--spacing) * 0.25) 0; - } - - - -@media #{$small} { - .store__nav a { - padding-top: 0; - font-size: var(--fs-small); - } - - .section__product { + @media #{$small} { display: flex; flex-direction: column; margin-bottom: 10vh; @@ -207,6 +55,7 @@ margin-top: calc(var(--spacing) * 0.5); order: 1; } + figure { order: 2; margin-bottom: calc(var(--spacing) * 1); @@ -226,25 +75,25 @@ order: 5; } - .product-gallery{ + .product-gallery { width: 100vw; position: relative; - left: calc(var(--padding-body)*-1); + left: calc(var(--padding-body) * -1); .swiper-button-prev, - .swiper-button-next{ display: none; } + .swiper-button-next { + display: none; + } } } -} -@media #{$small-up} { - - - .section__product{ - display: grid; - grid-template-columns: 1fr 1fr; - gap: calc(var(--padding-body)*2); - margin-bottom: calc(var(--spacing)*3); + @media #{$small-up} { + .product-content { + display: grid; + grid-template-columns: 1fr 1fr; + gap: calc(var(--padding-body) * 2); + margin-bottom: calc(var(--spacing) * 3); + } .details { margin-bottom: calc(var(--spacing) * 2); @@ -255,17 +104,140 @@ border-top: var(--border-light); } - .col-left{ + .col-left { min-height: 100%; - padding-bottom: 40px; //dots - + padding-bottom: 40px; display: flex; flex-direction: column; } - - } - - .product-gallery .swiper-slide figure{ - width: calc(100% - 60px); } } + +.product-options { + border-bottom: var(--border-light); + padding: calc(var(--spacing) * 0.25) 0; +} + +.product-options__list { + list-style: none; + display: flex; + gap: 2ch; + + li { + position: relative; + + input[type="radio"] { + position: fixed; + opacity: 0; + pointer-events: none; + + &:checked + label { + border-color: var(--color-txt); + } + + &:not(:checked) + label:hover { + border-color: var(--grey-600); + background-color: var(--grey-800); + } + } + + label { + font-family: var(--title); + font-size: var(--fs-normal); + height: 4ch; + width: 4ch; + border-radius: 50%; + border: var(--border); + border-color: transparent; + display: flex; + align-items: center; + justify-content: center; + padding-top: 0px; + cursor: pointer; + } + } +} + +.product-gallery { + position: relative; + aspect-ratio: 4 / 3; + + .swiper-slide { + width: 100%; + + figure { + aspect-ratio: 4 / 3; + width: 100%; + height: 100%; + + img { + width: 100%; + height: 100%; + object-fit: contain; + } + } + + @media #{$small-up} { + figure { + width: calc(100% - 60px); + } + } + } + + .swiper-button-prev, + .swiper-button-next { + color: var(--color-txt); + width: 20px; + height: 20px; + + &:after { + font-size: 20px; + font-weight: bold; + } + + &:hover { + opacity: 0.7; + } + } + + .swiper-pagination { + position: relative; + margin-top: calc(var(--spacing) * 0.5); + bottom: 0; + + .swiper-pagination-bullet { + width: 8px; + height: 8px; + background: var(--grey-600); + opacity: 0.5; + transition: opacity 0.3s; + + &:hover { + opacity: 0.7; + } + + &.swiper-pagination-bullet-active { + background: var(--color-txt); + opacity: 1; + } + } + } +} + +.hero { + margin-bottom: calc(var(--spacing) * 1); + padding: calc(var(--spacing) * 0.5) 0; + border-top: var(--border-light); + border-bottom: var(--border-light); + + .p__baseline-big { + margin: 0; + text-align: left; + } +} + +.add-to-cart { + margin: 0; + border-bottom: var(--border-light); + padding: calc(var(--spacing) * 0.5) 0; +} diff --git a/assets/js/cart-drawer.js b/assets/js/cart-drawer.js new file mode 100644 index 0000000..95972c1 --- /dev/null +++ b/assets/js/cart-drawer.js @@ -0,0 +1,275 @@ +/** + * Cart Drawer Component + * Manages the cart sidebar with add/remove/update functionality + */ +(function() { + const drawer = document.getElementById('cart-drawer'); + const emptyState = document.querySelector('[data-cart-empty]'); + const itemsContainer = document.querySelector('[data-cart-items]'); + const checkoutBtn = document.querySelector('[data-cart-checkout]'); + const closeButtons = document.querySelectorAll('[data-cart-close]'); + const totalDisplay = document.querySelector('[data-cart-total]'); + const headerCartBtn = document.querySelector('[data-cart-open]'); + const headerCartCount = document.querySelector('[data-cart-count]'); + + // Get translated text + const removeText = drawer.dataset.textRemove || 'Remove'; + + let currentCart = null; + let cartInstance = null; + + // Wait for ShopifyCart to be available + function initCartDrawer() { + if (typeof ShopifyCart === 'undefined') { + setTimeout(initCartDrawer, 100); + return; + } + + cartInstance = new ShopifyCart({ + domain: 'nv7cqv-bu.myshopify.com', + storefrontAccessToken: 'dec3d35a2554384d149c72927d1cfd1b' + }); + + // Initialize event listeners + setupEventListeners(); + } + + function setupEventListeners() { + // Close drawer + closeButtons.forEach(btn => { + btn.addEventListener('click', closeDrawer); + }); + + // Open drawer from header button + if (headerCartBtn) { + headerCartBtn.addEventListener('click', openDrawer); + } + + // Checkout button + checkoutBtn.addEventListener('click', () => { + if (currentCart?.checkoutUrl) { + window.location.href = currentCart.checkoutUrl; + } + }); + + // Listen for custom cart update events + document.addEventListener('cart:updated', (e) => { + currentCart = e.detail.cart; + renderCart(); + openDrawer(); + }); + } + + function openDrawer() { + drawer.classList.add('is-open'); + document.body.style.overflow = 'hidden'; + } + + function closeDrawer() { + drawer.classList.remove('is-open'); + document.body.style.overflow = ''; + } + + function calculateTotal() { + if (!currentCart || !currentCart.lines) return 0; + + return currentCart.lines.edges.reduce((total, edge) => { + const item = edge.node; + const price = parseFloat(item.merchandise.price.amount); + const quantity = item.quantity; + return total + (price * quantity); + }, 0); + } + + function formatPrice(amount, currency = 'EUR') { + return new Intl.NumberFormat('fr-FR', { + style: 'currency', + currency: currency + }).format(amount); + } + + function updateCartCount() { + if (!currentCart || !currentCart.lines || currentCart.lines.edges.length === 0) { + if (headerCartCount) { + headerCartCount.textContent = ''; + } + return; + } + + // Calculate total quantity + const totalQty = currentCart.lines.edges.reduce((sum, edge) => { + return sum + edge.node.quantity; + }, 0); + + if (headerCartCount) { + headerCartCount.textContent = totalQty > 0 ? totalQty : ''; + } + } + + function renderCart() { + if (!currentCart || !currentCart.lines || currentCart.lines.edges.length === 0) { + emptyState.classList.remove('hidden'); + itemsContainer.classList.add('hidden'); + checkoutBtn.disabled = true; + if (totalDisplay) { + totalDisplay.textContent = '0,00 €'; + } + updateCartCount(); + return; + } + + emptyState.classList.add('hidden'); + itemsContainer.classList.remove('hidden'); + checkoutBtn.disabled = false; + + // Calculate and display total + const total = calculateTotal(); + const currency = currentCart.lines.edges[0]?.node.merchandise.price.currencyCode || 'EUR'; + if (totalDisplay) { + totalDisplay.textContent = formatPrice(total, currency); + } + + // Update header cart count + updateCartCount(); + + // Render cart items + itemsContainer.innerHTML = currentCart.lines.edges.map(edge => { + const item = edge.node; + const merchandise = item.merchandise; + + return ` +
+
+

${merchandise.product.title}

+ ${merchandise.title !== 'Default Title' ? `

${merchandise.title}

` : ''} +

${formatPrice(parseFloat(merchandise.price.amount), merchandise.price.currencyCode)}

+ +
+ + ${item.quantity} + +
+ + +
+
+ `; + }).join(''); + + // Attach event listeners to quantity buttons + attachQuantityListeners(); + } + + function attachQuantityListeners() { + const buttons = itemsContainer.querySelectorAll('[data-action]'); + + buttons.forEach(btn => { + btn.addEventListener('click', async (e) => { + const action = e.target.dataset.action; + const lineId = e.target.dataset.lineId; + + await handleQuantityChange(action, lineId); + }); + }); + } + + async function handleQuantityChange(action, lineId) { + if (!cartInstance || !currentCart) return; + + // Find the line item + const line = currentCart.lines.edges.find(edge => edge.node.id === lineId); + if (!line) return; + + const currentQty = line.node.quantity; + let newQty = currentQty; + + if (action === 'increase') { + newQty = currentQty + 1; + } else if (action === 'decrease') { + newQty = Math.max(0, currentQty - 1); + } else if (action === 'remove') { + newQty = 0; + } + + // Update cart via API + try { + itemsContainer.classList.add('is-loading'); + + const query = ` + mutation cartLinesUpdate($cartId: ID!, $lines: [CartLineUpdateInput!]!) { + cartLinesUpdate(cartId: $cartId, lines: $lines) { + cart { + id + checkoutUrl + lines(first: 10) { + edges { + node { + id + quantity + merchandise { + ... on ProductVariant { + id + title + price { + amount + currencyCode + } + product { + title + } + } + } + } + } + } + } + userErrors { + field + message + } + } + } + `; + + const data = await cartInstance.query(query, { + cartId: currentCart.id, + lines: [{ + id: lineId, + quantity: newQty + }] + }); + + if (data.cartLinesUpdate.userErrors.length > 0) { + throw new Error(data.cartLinesUpdate.userErrors[0].message); + } + + currentCart = data.cartLinesUpdate.cart; + renderCart(); + + } catch (error) { + console.error('Error updating cart:', error); + alert('Erreur lors de la mise à jour du panier'); + } finally { + itemsContainer.classList.remove('is-loading'); + } + } + + // Public API + window.CartDrawer = { + open: openDrawer, + close: closeDrawer, + updateCart: (cart) => { + currentCart = cart; + renderCart(); + } + }; + + // Initialize when DOM is ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initCartDrawer); + } else { + initCartDrawer(); + } +})(); diff --git a/assets/js/product-add-to-cart.js b/assets/js/product-add-to-cart.js new file mode 100644 index 0000000..51ee83c --- /dev/null +++ b/assets/js/product-add-to-cart.js @@ -0,0 +1,63 @@ +(function() { + const cart = new ShopifyCart({ + domain: 'nv7cqv-bu.myshopify.com', + storefrontAccessToken: 'dec3d35a2554384d149c72927d1cfd1b' + }); + + const addToCartBtn = document.querySelector('[data-shopify-add-to-cart]'); + + if (!addToCartBtn) { + return; + } + + const texts = { + add: addToCartBtn.dataset.textAdd || 'Add to cart', + adding: addToCartBtn.dataset.textAdding || 'Adding...', + added: addToCartBtn.dataset.textAdded || 'Added! ✓', + error: addToCartBtn.dataset.textError || 'Error - Try again' + }; + + addToCartBtn.addEventListener('click', async function(e) { + e.preventDefault(); + + const variantId = this.dataset.variantId; + + if (!variantId) { + console.error('No variant ID found'); + return; + } + + addToCartBtn.disabled = true; + const originalText = addToCartBtn.textContent; + addToCartBtn.textContent = texts.adding; + + try { + const cartResult = await cart.addToCart(variantId, 1); + + addToCartBtn.textContent = texts.added; + addToCartBtn.classList.add('success'); + + document.dispatchEvent(new CustomEvent('cart:updated', { + detail: { cart: cartResult } + })); + + setTimeout(() => { + addToCartBtn.disabled = false; + addToCartBtn.textContent = originalText; + addToCartBtn.classList.remove('success'); + }, 1500); + + } catch (error) { + console.error('Error adding to cart:', error); + + addToCartBtn.textContent = texts.error; + addToCartBtn.classList.add('error'); + + setTimeout(() => { + addToCartBtn.disabled = false; + addToCartBtn.textContent = originalText; + addToCartBtn.classList.remove('error'); + }, 2000); + } + }); +})(); diff --git a/assets/js/product-loader.js b/assets/js/product-loader.js new file mode 100644 index 0000000..142e4ad --- /dev/null +++ b/assets/js/product-loader.js @@ -0,0 +1,188 @@ +(async function () { + const container = document.querySelector("[data-product-loader]"); + if (!container) return; + + const handle = container.dataset.shopifyHandle; + const language = container.dataset.language || 'fr'; + const isEnglish = language === 'en'; + const loadingState = container.querySelector(".product-loading"); + const contentState = container.querySelector(".product-content"); + const errorState = container.querySelector(".product-error"); + + try { + const cart = new ShopifyCart({ + domain: "nv7cqv-bu.myshopify.com", + storefrontAccessToken: "dec3d35a2554384d149c72927d1cfd1b", + }); + + const product = await cart.getProductByHandle(handle); + + if (!product) { + throw new Error("Product not found"); + } + + renderProduct(product, isEnglish); + + loadingState.style.display = "none"; + contentState.removeAttribute("style"); + + setTimeout(() => { + if (typeof Swiper !== "undefined" && product.images.edges.length > 0) { + new Swiper(".product-gallery", { + loop: product.images.edges.length > 1, + navigation: { + nextEl: ".swiper-button-next", + prevEl: ".swiper-button-prev", + }, + pagination: { + el: ".swiper-pagination", + clickable: true, + }, + keyboard: { + enabled: true, + }, + }); + } + }, 100); + } catch (error) { + console.error("Error loading product:", error); + loadingState.style.display = "none"; + errorState.style.display = "block"; + } + + function renderProduct(product, isEnglish) { + renderTitle(product, isEnglish); + renderPrice(product); + renderDetails(product, isEnglish); + renderImages(product, isEnglish); + renderVariants(product); + setupAddToCart(product); + renderStock(product); + } + + function renderTitle(product, isEnglish) { + const titleEl = document.querySelector("[data-product-title]"); + if (titleEl) { + const title = isEnglish && product.titleEn?.value + ? product.titleEn.value + : product.title; + titleEl.textContent = title; + } + } + + function renderPrice(product) { + const priceEl = document.querySelector("[data-product-price]"); + if (priceEl) { + const price = parseFloat(product.priceRange.minVariantPrice.amount); + priceEl.textContent = price.toFixed(2) + "€"; + } + } + + function renderDetails(product, isEnglish) { + const detailsEl = document.querySelector("[data-product-details]"); + if (detailsEl) { + const description = isEnglish && product.descriptionEn?.value + ? product.descriptionEn.value + : product.descriptionHtml || ""; + detailsEl.innerHTML = description; + } + } + + function renderImages(product, isEnglish) { + const imagesContainer = document.querySelector("[data-product-images]"); + + if (imagesContainer && product.images.edges.length > 0) { + const productTitle = isEnglish && product.titleEn?.value + ? product.titleEn.value + : product.title; + + imagesContainer.innerHTML = product.images.edges + .map((edge) => { + const img = edge.node; + return ` +
+
+ ${img.altText || productTitle} +
+
+ `; + }) + .join(""); + } + } + + function renderVariants(product) { + if (product.variants.edges.length <= 1) return; + + const variantsContainer = document.querySelector("[data-product-variants]"); + const variantSelector = document.querySelector("[data-variant-selector]"); + + if (!variantsContainer || !variantSelector) return; + + variantsContainer.style.display = "block"; + + variantSelector.innerHTML = product.variants.edges + .map((edge) => { + const variant = edge.node; + const variantId = variant.id.replace( + "gid://shopify/ProductVariant/", + "" + ); + const price = parseFloat(variant.price.amount).toFixed(2) + "€"; + const availability = variant.availableForSale + ? "" + : " (Rupture de stock)"; + + return ``; + }) + .join(""); + + variantSelector.addEventListener("change", (e) => { + const addToCartBtn = document.querySelector("[data-shopify-add-to-cart]"); + if (addToCartBtn) { + addToCartBtn.dataset.variantId = e.target.value; + } + }); + } + + function setupAddToCart(product) { + const addToCartBtn = document.querySelector("[data-shopify-add-to-cart]"); + if (!addToCartBtn) return; + + const productId = product.id.replace("gid://shopify/Product/", ""); + addToCartBtn.dataset.productId = productId; + + const firstAvailableVariant = product.variants.edges.find( + (e) => e.node.availableForSale + ); + if (firstAvailableVariant) { + const variantId = firstAvailableVariant.node.id.replace( + "gid://shopify/ProductVariant/", + "" + ); + addToCartBtn.dataset.variantId = variantId; + } + } + + function renderStock(product) { + const stockEl = document.querySelector("[data-product-stock]"); + if (!stockEl) return; + + const addToCartBtn = document.querySelector("[data-shopify-add-to-cart]"); + + if (product.availableForSale) { + stockEl.textContent = addToCartBtn?.dataset.textInStock || "En stock"; + stockEl.classList.add("in-stock"); + } else { + stockEl.textContent = + addToCartBtn?.dataset.textOutOfStock || "Rupture de stock"; + stockEl.classList.add("out-of-stock"); + } + } +})(); diff --git a/assets/js/products-list-loader.js b/assets/js/products-list-loader.js new file mode 100644 index 0000000..be32f4a --- /dev/null +++ b/assets/js/products-list-loader.js @@ -0,0 +1,47 @@ +(async function() { + const container = document.querySelector('[data-products-loader]'); + if (!container) return; + + const language = (container.dataset.language || 'FR').toLowerCase(); + const isEnglish = language === 'en'; + + try { + const cart = new ShopifyCart({ + domain: 'nv7cqv-bu.myshopify.com', + storefrontAccessToken: 'dec3d35a2554384d149c72927d1cfd1b' + }); + + const productsData = await cart.getAllProducts(); + const products = productsData.edges; + + const productsHtml = products.map(edge => { + const product = edge.node; + const image = product.images.edges[0]?.node; + const price = parseFloat(product.priceRange.minVariantPrice.amount).toFixed(2); + const slug = product.handle; + const productUrl = isEnglish ? `/en/${slug}` : `/${slug}`; + const productTitle = isEnglish && product.titleEn?.value + ? product.titleEn.value + : product.title; + + return ` +
+
+ ${image ? `${image.altText || productTitle}` : ''} +
+

+ ${productTitle} +

+

${price}€

+ +
+ `; + }).join(''); + + container.innerHTML = productsHtml; + + } catch (error) { + console.error('Error loading products:', error); + container.innerHTML = '

Erreur lors du chargement des produits

'; + } +})(); diff --git a/assets/js/shopify-cart.js b/assets/js/shopify-cart.js new file mode 100644 index 0000000..18b1338 --- /dev/null +++ b/assets/js/shopify-cart.js @@ -0,0 +1,343 @@ +/** + * Shopify Storefront API Client + * Custom implementation using Cart API (2026-01) + */ +class ShopifyCart { + constructor(config) { + this.domain = config.domain; + this.storefrontAccessToken = config.storefrontAccessToken; + this.apiVersion = '2026-01'; + this.endpoint = `https://${this.domain}/api/${this.apiVersion}/graphql.json`; + this.cartId = null; + this.cartItems = []; + + // Load existing cart from localStorage + this.loadCart(); + } + + /** + * Make GraphQL request to Shopify Storefront API + */ + async query(query, variables = {}) { + const response = await fetch(this.endpoint, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Shopify-Storefront-Access-Token': this.storefrontAccessToken, + }, + body: JSON.stringify({ query, variables }), + }); + + const result = await response.json(); + + if (result.errors) { + console.error('Shopify API Error:', result.errors); + throw new Error(result.errors[0].message); + } + + return result.data; + } + + /** + * Get product information by ID + */ + async getProduct(productId) { + const query = ` + query getProduct($id: ID!) { + product(id: $id) { + id + title + description + availableForSale + variants(first: 10) { + edges { + node { + id + title + price { + amount + currencyCode + } + availableForSale + } + } + } + } + } + `; + + const data = await this.query(query, { + id: `gid://shopify/Product/${productId}` + }); + + return data.product; + } + + /** + * Get product by handle + * @param {string} handle - Product handle (slug) + */ + async getProductByHandle(handle) { + const query = ` + query getProductByHandle($handle: String!) { + product(handle: $handle) { + id + handle + title + description + descriptionHtml + availableForSale + tags + titleEn: metafield(namespace: "custom", key: "title_en") { + value + } + descriptionEn: metafield(namespace: "custom", key: "description_en") { + value + } + priceRange { + minVariantPrice { + amount + currencyCode + } + } + images(first: 10) { + edges { + node { + id + url + altText + width + height + } + } + } + variants(first: 20) { + edges { + node { + id + title + sku + availableForSale + price { + amount + currencyCode + } + selectedOptions { + name + value + } + } + } + } + } + } + `; + + const data = await this.query(query, { handle }); + return data.product || null; + } + + /** + * Get all products for listing page + * @param {number} first - Number of products to fetch + */ + async getAllProducts(first = 20) { + const query = ` + query getAllProducts($first: Int!) { + products(first: $first, sortKey: TITLE) { + edges { + node { + id + handle + title + description + availableForSale + titleEn: metafield(namespace: "custom", key: "title_en") { + value + } + priceRange { + minVariantPrice { + amount + currencyCode + } + } + images(first: 1) { + edges { + node { + id + url + altText + } + } + } + } + } + pageInfo { + hasNextPage + endCursor + } + } + } + `; + + const data = await this.query(query, { first }); + return data.products; + } + + /** + * Create a new cart + */ + async createCart(lines = []) { + const query = ` + mutation cartCreate($input: CartInput!) { + cartCreate(input: $input) { + cart { + id + checkoutUrl + lines(first: 10) { + edges { + node { + id + quantity + merchandise { + ... on ProductVariant { + id + title + price { + amount + currencyCode + } + product { + title + } + } + } + } + } + } + } + userErrors { + field + message + } + } + } + `; + + const data = await this.query(query, { + input: { lines } + }); + + if (data.cartCreate.userErrors.length > 0) { + throw new Error(data.cartCreate.userErrors[0].message); + } + + this.cartId = data.cartCreate.cart.id; + this.saveCart(); + + return data.cartCreate.cart; + } + + /** + * Add item to cart + */ + async addToCart(variantId, quantity = 1) { + const lines = [{ + merchandiseId: `gid://shopify/ProductVariant/${variantId}`, + quantity: quantity + }]; + + let cart; + + if (this.cartId) { + // Add to existing cart + const query = ` + mutation cartLinesAdd($cartId: ID!, $lines: [CartLineInput!]!) { + cartLinesAdd(cartId: $cartId, lines: $lines) { + cart { + id + checkoutUrl + lines(first: 10) { + edges { + node { + id + quantity + merchandise { + ... on ProductVariant { + id + title + price { + amount + currencyCode + } + product { + title + } + } + } + } + } + } + } + userErrors { + field + message + } + } + } + `; + + const data = await this.query(query, { + cartId: this.cartId, + lines + }); + + if (data.cartLinesAdd.userErrors.length > 0) { + throw new Error(data.cartLinesAdd.userErrors[0].message); + } + + cart = data.cartLinesAdd.cart; + } else { + // Create new cart + cart = await this.createCart(lines); + } + + this.cartItems = cart.lines.edges; + return cart; + } + + /** + * Get checkout URL to redirect user + */ + getCheckoutUrl(cart) { + return cart?.checkoutUrl || null; + } + + /** + * Save cart ID to localStorage + */ + saveCart() { + if (this.cartId) { + localStorage.setItem('shopify_cart_id', this.cartId); + } + } + + /** + * Load cart ID from localStorage + */ + loadCart() { + this.cartId = localStorage.getItem('shopify_cart_id'); + } + + /** + * Clear cart + */ + clearCart() { + this.cartId = null; + this.cartItems = []; + localStorage.removeItem('shopify_cart_id'); + } +} + +// Export for use in other scripts +window.ShopifyCart = ShopifyCart; diff --git a/assets/snipcart-archive/README.md b/assets/snipcart-archive/README.md new file mode 100644 index 0000000..3b1c388 --- /dev/null +++ b/assets/snipcart-archive/README.md @@ -0,0 +1,164 @@ +# Archive Snipcart + +Cette archive contient tous les fichiers et le code nécessaires pour réactiver l'intégration Snipcart si besoin. + +## Date d'archivage +13 janvier 2026 + +## Raison de l'archivage +Remplacement par l'intégration Shopify Buy Button + +--- + +## Fichiers archivés + +### Fichiers JavaScript +- `snipcart.js` - Loader Snipcart avec configuration de la clé API +- `product-size.js` - Gestion des options produit (tailles, etc.) pour Snipcart + +### Fichiers SCSS +- `_snipcart.scss` - Styles pour le modal Snipcart + +--- + +## Comment restaurer l'intégration Snipcart + +### 1. Restaurer les fichiers JavaScript + +#### Fichier: `assets/js/snipcart.js` +Copier le fichier depuis l'archive: +```bash +cp assets/snipcart-archive/snipcart.js assets/js/ +``` + +#### Fichier: `assets/js/product-size.js` +Copier le fichier depuis l'archive: +```bash +cp assets/snipcart-archive/product-size.js assets/js/ +``` + +### 2. Restaurer les styles SCSS + +#### Fichier: `assets/css/template/shop/_snipcart.scss` +Copier le fichier depuis l'archive: +```bash +cp assets/snipcart-archive/_snipcart.scss assets/css/template/shop/ +``` + +Puis décommenter l'import dans `assets/css/style.scss`: +```scss +// Décommenter cette ligne: +@import 'template/shop/snipcart'; +``` + +### 3. Restaurer le template produit + +#### Fichier: `site/templates/product.php` + +1. **Restaurer le bouton "Ajouter au panier" avec les attributs Snipcart** (ligne ~40-78): + - Décommenter tous les attributs `data-item-*` du bouton + - Ajouter la classe `snipcart-add-item` au bouton + +2. **Restaurer les scripts dans le footer** (ligne 114): + ```php + ['assets/js/product-size.js', 'assets/js/snipcart.js', 'assets/js/product-gallery.js']]) ?> + ``` + +### 4. Restaurer les routes et webhooks + +#### Fichier: `site/config/config.php` + +Décommenter les routes Snipcart (lignes 39-147): + +1. **Route de validation produit** (`validate.json`): + - Permet à Snipcart de valider les prix et stock + - Route: `(:any)/validate.json` + +2. **Webhook Snipcart**: + - Gère les événements de commande (décrémente le stock) + - Route: `snipcart-webhook` + +### 5. Configuration Snipcart + +#### Clé API publique +La clé API publique Snipcart est dans `snipcart.js`: +```javascript +publicApiKey: 'NGU4ODQ3MjAtY2MzMC00MWEyLWI2YTMtNjBmNGYzMTBlOTZkNjM4OTY1NDY4OTE5MTQyMTI3' +``` + +#### Configuration du webhook +Pour que le webhook fonctionne, il faut: +1. Configurer l'URL du webhook dans le dashboard Snipcart +2. URL: `https://votre-domaine.com/snipcart-webhook` +3. Événements à écouter: `order.completed` + +### 6. Vérifications après restauration + +- [ ] Les fichiers JS sont présents dans `assets/js/` +- [ ] Le fichier SCSS est présent et importé +- [ ] Les boutons "Ajouter au panier" ont la classe `snipcart-add-item` +- [ ] Les attributs `data-item-*` sont présents sur les boutons +- [ ] Les routes sont décommentées dans `config.php` +- [ ] Le CSS de Snipcart est compilé +- [ ] Le webhook est configuré dans le dashboard Snipcart +- [ ] Les traductions sont restaurées dans `site/languages/en.php` et `fr.php` + +--- + +## Fonctionnalités Snipcart implémentées + +### Gestion des produits +- Affichage du prix +- Options de produit (tailles, couleurs, etc.) +- Validation des options obligatoires +- Images produit + +### Gestion du panier +- Ajout au panier +- Gestion du stock +- Calcul des frais de port (basé sur poids/dimensions) +- Validation des prix côté serveur + +### Gestion des commandes +- Webhook pour décrémenter le stock automatiquement +- Redirection vers page de remerciement après paiement +- Token de commande dans l'URL + +### Multi-langue +- Support FR/EN +- Redirection post-paiement avec détection de la langue + +--- + +## Dépendances externes + +### CDN Snipcart +Snipcart est chargé depuis le CDN officiel: +- Version: 3.0 +- JS: `https://cdn.snipcart.com/themes/v3.0/default/snipcart.js` +- CSS: `https://cdn.snipcart.com/themes/v3.0/default/snipcart.css` + +### Stratégie de chargement +- `loadStrategy: 'on-user-interaction'` +- Chargement différé pour optimiser les performances +- Timeout: 2750ms + +--- + +## Notes importantes + +1. **Sécurité**: Le webhook devrait valider la signature Snipcart en production (voir commentaire dans `config.php`) + +2. **Stock**: Le système décrémente automatiquement le stock via le webhook `order.completed` + +3. **Validation**: Chaque produit expose une route `validate.json` pour que Snipcart puisse vérifier les prix + +4. **Multi-langue**: La redirection post-paiement détecte automatiquement la langue depuis l'URL + +--- + +## Support + +Pour toute question sur Snipcart: +- Documentation: https://docs.snipcart.com/ +- Support: https://snipcart.com/support diff --git a/assets/css/template/shop/_snipcart.scss b/assets/snipcart-archive/_snipcart.scss similarity index 100% rename from assets/css/template/shop/_snipcart.scss rename to assets/snipcart-archive/_snipcart.scss diff --git a/assets/snipcart-archive/product-size.js b/assets/snipcart-archive/product-size.js new file mode 100644 index 0000000..399ffce --- /dev/null +++ b/assets/snipcart-archive/product-size.js @@ -0,0 +1,66 @@ +/** + * Gestion de la sélection des options produit + * Met à jour les attributs Snipcart et gère les classes CSS + */ + +(function() { + 'use strict'; + + /** + * Initialise la gestion des options + */ + function initOptionSelector() { + const optionsContainer = document.querySelector('.product-options'); + const addToCartButton = document.querySelector('.snipcart-add-item'); + + if (!addToCartButton) { + return; + } + + // Si pas d'options, le bouton est déjà actif + if (!optionsContainer) { + return; + } + + const radios = optionsContainer.querySelectorAll('input[type="radio"]'); + + // Réinitialiser toutes les options (important pour le cache navigateur) + radios.forEach(radio => { + radio.checked = false; + }); + + // Retirer la classe is-selected de tous les li + const allLi = optionsContainer.querySelectorAll('li'); + allLi.forEach(li => li.classList.remove('is-selected')); + + // S'assurer que le bouton est désactivé au départ + addToCartButton.setAttribute('disabled', 'disabled'); + + // Écouter les changements de sélection + radios.forEach(radio => { + radio.addEventListener('change', function() { + // Mettre à jour l'attribut Snipcart + addToCartButton.setAttribute('data-item-custom1-value', this.value); + + // Activer le bouton + addToCartButton.removeAttribute('disabled'); + + // Changer le texte du bouton + const buttonText = addToCartButton.querySelector('.txt'); + if (buttonText) { + buttonText.textContent = buttonText.getAttribute('data-default-text') || 'Ajouter au panier'; + } + + // Gérer la classe is-selected sur les li parents + allLi.forEach(li => li.classList.remove('is-selected')); + this.closest('li').classList.add('is-selected'); + }); + }); + } + + /** + * Initialisation au chargement de la page + */ + document.addEventListener('DOMContentLoaded', initOptionSelector); + +})(); diff --git a/assets/snipcart-archive/snipcart.js b/assets/snipcart-archive/snipcart.js new file mode 100644 index 0000000..13eef65 --- /dev/null +++ b/assets/snipcart-archive/snipcart.js @@ -0,0 +1,94 @@ +window.SnipcartSettings = { + publicApiKey: + 'NGU4ODQ3MjAtY2MzMC00MWEyLWI2YTMtNjBmNGYzMTBlOTZkNjM4OTY1NDY4OTE5MTQyMTI3', + loadStrategy: 'on-user-interaction', +}; + +// Redirection après paiement réussi +document.addEventListener('snipcart.ready', function() { + Snipcart.events.on('cart.confirmed', function(cartState) { + // Détecter la langue actuelle depuis l'URL + const currentPath = window.location.pathname; + const langMatch = currentPath.match(/^\/([a-z]{2})(\/|$)/); + const langPrefix = langMatch ? '/' + langMatch[1] : ''; + + window.location.href = langPrefix + '/thanks?order=' + cartState.token; + }); +}); + +(() => { + var c, d; + (d = (c = window.SnipcartSettings).version) != null || (c.version = '3.0'); + var s, S; + (S = (s = window.SnipcartSettings).timeoutDuration) != null || + (s.timeoutDuration = 2750); + var l, p; + (p = (l = window.SnipcartSettings).domain) != null || + (l.domain = 'cdn.snipcart.com'); + var w, u; + (u = (w = window.SnipcartSettings).protocol) != null || + (w.protocol = 'https'); + var f = + window.SnipcartSettings.version.includes('v3.0.0-ci') || + (window.SnipcartSettings.version != '3.0' && + window.SnipcartSettings.version.localeCompare('3.4.0', void 0, { + numeric: !0, + sensitivity: 'base', + }) === -1), + m = ['focus', 'mouseover', 'touchmove', 'scroll', 'keydown']; + window.LoadSnipcart = o; + document.readyState === 'loading' + ? document.addEventListener('DOMContentLoaded', r) + : r(); + function r() { + window.SnipcartSettings.loadStrategy + ? window.SnipcartSettings.loadStrategy === 'on-user-interaction' && + (m.forEach((t) => document.addEventListener(t, o)), + setTimeout(o, window.SnipcartSettings.timeoutDuration)) + : o(); + } + var a = !1; + function o() { + if (a) return; + a = !0; + let t = document.getElementsByTagName('head')[0], + e = document.querySelector('#snipcart'), + i = document.querySelector( + `src[src^="${window.SnipcartSettings.protocol}://${window.SnipcartSettings.domain}"][src$="snipcart.js"]` + ), + n = document.querySelector( + `link[href^="${window.SnipcartSettings.protocol}://${window.SnipcartSettings.domain}"][href$="snipcart.css"]` + ); + e || + ((e = document.createElement('div')), + (e.id = 'snipcart'), + e.setAttribute('hidden', 'true'), + document.body.appendChild(e)), + v(e), + i || + ((i = document.createElement('script')), + (i.src = `${window.SnipcartSettings.protocol}://${window.SnipcartSettings.domain}/themes/v${window.SnipcartSettings.version}/default/snipcart.js`), + (i.async = !0), + t.appendChild(i)), + n || + ((n = document.createElement('link')), + (n.rel = 'stylesheet'), + (n.type = 'text/css'), + (n.href = `${window.SnipcartSettings.protocol}://${window.SnipcartSettings.domain}/themes/v${window.SnipcartSettings.version}/default/snipcart.css`), + t.prepend(n)), + m.forEach((g) => document.removeEventListener(g, o)); + } + function v(t) { + !f || + ((t.dataset.apiKey = window.SnipcartSettings.publicApiKey), + window.SnipcartSettings.addProductBehavior && + (t.dataset.configAddProductBehavior = + window.SnipcartSettings.addProductBehavior), + window.SnipcartSettings.modalStyle && + (t.dataset.configModalStyle = window.SnipcartSettings.modalStyle), + window.SnipcartSettings.currency && + (t.dataset.currency = window.SnipcartSettings.currency), + window.SnipcartSettings.templatesUrl && + (t.dataset.templatesUrl = window.SnipcartSettings.templatesUrl)); + } +})(); diff --git a/content/1_eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat/product.en.txt b/content/1_eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat/product.en.txt new file mode 100644 index 0000000..6bbc828 --- /dev/null +++ b/content/1_eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat/product.en.txt @@ -0,0 +1,5 @@ +Title: Éclairages : 12 entretiens et analyses sur les violences d'État + +---- + +Uuid: gzshayl6xoefrnsz diff --git a/content/1_eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat/product.fr.txt b/content/1_eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat/product.fr.txt new file mode 100644 index 0000000..f26cd4f --- /dev/null +++ b/content/1_eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat/product.fr.txt @@ -0,0 +1,9 @@ +Title: Éclairages : 12 entretiens et analyses sur les violences d’État + +---- + +Shopifyhandle: eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat + +---- + +Uuid: gzshayl6xoefrnsz \ No newline at end of file diff --git a/content/1_tshirt-index-01/product.en.txt b/content/1_tshirt-index-01/product.en.txt deleted file mode 100644 index 0541df2..0000000 --- a/content/1_tshirt-index-01/product.en.txt +++ /dev/null @@ -1,52 +0,0 @@ -Title: T-shirt Index 01 - ----- - -Price: 35 - ----- - -Description:

T-shirt de soutien à Index, 100% coton

- ----- - -Details: - -[ - { - "content": { - "text": "

100% cotton

" - }, - "id": "detail1", - "isHidden": false, - "type": "text" - }, - { - "content": { - "text": "

Lorem ipsum dolor sit amet

" - }, - "id": "detail2", - "isHidden": false, - "type": "text" - } -] - ----- - -Options: - -- - label: Size - values: XS, S, M, L, XL - ----- - -Snipcartid: tshirt-01 - ----- - -Backgroundcolor: #ffffff - ----- - -Template: product \ No newline at end of file diff --git a/content/1_tshirt-index-01/product.fr.txt b/content/1_tshirt-index-01/product.fr.txt deleted file mode 100644 index 2226ab3..0000000 --- a/content/1_tshirt-index-01/product.fr.txt +++ /dev/null @@ -1,56 +0,0 @@ -Title: T-shirt Index 01 - ----- - -Price: 35 - ----- - -Stock: 10 - ----- - -Description: T-shirt de soutien à Index, 100% coton - ----- - -Details:

T-shirt en coton organique avec impression sérigraphique.
Marquage sur la face avant : logo « INDEX » de 10 cm de large.

Envoi uniquement via Mondial Relay vers la France, la Belgique et la Suisse.

- ----- - -Hasoptions: true - ----- - -Optionlabel: Taille - ----- - -Optionvalues: XS, S, M, L, XL - ----- - -Options: - -- - label: Taille - values: XS, S, M, L, XL -- - label: Couleur - values: Rouge, Vert - ----- - -Snipcartid: tshirt-01 - ----- - -Backgroundcolor: #ffffff - ----- - -Template: product - ----- - -Uuid: udrrfizhayqixfoo \ No newline at end of file diff --git a/content/1_tshirt-index-01/test.png b/content/1_tshirt-index-01/test.png deleted file mode 100644 index f05f4a3..0000000 Binary files a/content/1_tshirt-index-01/test.png and /dev/null differ diff --git a/content/1_tshirt-index-01/test.png.fr.txt b/content/1_tshirt-index-01/test.png.fr.txt deleted file mode 100644 index cd5255a..0000000 --- a/content/1_tshirt-index-01/test.png.fr.txt +++ /dev/null @@ -1,9 +0,0 @@ -Sort: 1 - ----- - -Uuid: elxkhcta8dkjhr60 - ----- - -Template: image \ No newline at end of file diff --git a/content/1_tshirt-index-01/tshirt-01.png b/content/1_tshirt-index-01/tshirt-01.png deleted file mode 100644 index 99899b8..0000000 Binary files a/content/1_tshirt-index-01/tshirt-01.png and /dev/null differ diff --git a/content/1_tshirt-index-01/tshirt-01.png.fr.txt b/content/1_tshirt-index-01/tshirt-01.png.fr.txt deleted file mode 100644 index c9a1f27..0000000 --- a/content/1_tshirt-index-01/tshirt-01.png.fr.txt +++ /dev/null @@ -1,9 +0,0 @@ -Sort: 2 - ----- - -Uuid: deupkqq83jvloz0r - ----- - -Template: image \ No newline at end of file diff --git a/content/2_t-shirt-index/product.en.txt b/content/2_t-shirt-index/product.en.txt new file mode 100644 index 0000000..7aa8f14 --- /dev/null +++ b/content/2_t-shirt-index/product.en.txt @@ -0,0 +1,5 @@ +Title: T-shirt Index + +---- + +Uuid: qq27mjjpethsvnwp diff --git a/content/2_t-shirt-index/product.fr.txt b/content/2_t-shirt-index/product.fr.txt new file mode 100644 index 0000000..395184c --- /dev/null +++ b/content/2_t-shirt-index/product.fr.txt @@ -0,0 +1,9 @@ +Title: T-shirt Index + +---- + +Shopifyhandle: t-shirt-index-01 + +---- + +Uuid: qq27mjjpethsvnwp \ No newline at end of file diff --git a/site/blueprints/pages/product.yml b/site/blueprints/pages/product.yml index 52fde12..978bcde 100644 --- a/site/blueprints/pages/product.yml +++ b/site/blueprints/pages/product.yml @@ -1,134 +1,21 @@ -title: - en: Product - fr: Produit +title: Product icon: cart -tabs: - content: - label: - en: Content - fr: Contenu - columns: - - width: 2/3 - sections: - main: - type: fields - fields: - price: - label: - en: Price (€) - fr: Prix (€) - type: number - min: 0 - step: 0.01 - required: true - translate: false - width: 1/4 - stock: - label: Stock - type: number - min: 0 - default: 0 - help: - en: Edit through french version - fr: Partagé entre les versions FR et EN - translate: false - width: 1/4 - space: - type: gap - width: 2/4 - weight: - label: - en: Weight (g) - fr: Poids (g) - type: number - min: 0 - default: 0 - help: - en: Weight in grams for shipping calculation - fr: Poids en grammes pour le calcul de la livraison - translate: false - width: 1/4 - length: - label: - en: Length (cm) - fr: Longueur (cm) - type: number - min: 0 - default: 0 - help: - en: Package length in centimeters - fr: Longueur du colis en centimètres - translate: false - width: 1/4 - width: - label: - en: Width (cm) - fr: Largeur (cm) - type: number - min: 0 - default: 0 - help: - en: Package width in centimeters - fr: Largeur du colis en centimètres - translate: false - width: 1/4 - height: - label: - en: Height (cm) - fr: Hauteur (cm) - type: number - min: 0 - default: 0 - help: - en: Package height in centimeters - fr: Hauteur du colis en centimètres - translate: false - width: 1/4 - description: - label: Description panier - type: writer - help: Visible dans le panier seulement. - details: - label: - en: Details - fr: Détails - type: writer - hasOptions: - label: - en: Options - fr: Options - type: toggle - default: false - translate: false - width: 1/7 - optionLabel: - label: - en: Option label - fr: Libellé de l'option - type: text - width: 3/7 - when: - hasOptions: true - optionValues: - label: - en: Option values - fr: Valeurs de l'option - type: tags - help: - en: "Comma-separated values (e.g.: XS, S, M, L, XL)" - fr: "Valeurs séparées par des virgules (ex: XS, S, M, L, XL)" - translate: false - when: - hasOptions: true - width: 3/7 +columns: + - width: 1/1 + fields: + info: + type: info + text: + en: "Product data (title, description, images, price) is managed in Shopify Admin. This Kirby page only serves for routing." + fr: "Les données produit (titre, description, images, prix) sont gérées dans Shopify Admin. Cette page Kirby sert uniquement au routing." - - width: 1/3 - sections: - images: - type: files - headline: - en: Product Images - fr: Images du produit - template: image - layout: cards + shopifyHandle: + label: + en: Shopify Handle + fr: Shopify Handle + type: text + help: + en: "Product handle from Shopify (e.g. tshirt-index-01). If empty, uses the page slug." + fr: "Handle du produit Shopify (ex: tshirt-index-01). Si vide, utilise le slug de la page Kirby." + placeholder: tshirt-index-01 diff --git a/site/config/config.php b/site/config/config.php index 55d96fb..427755b 100644 --- a/site/config/config.php +++ b/site/config/config.php @@ -37,6 +37,8 @@ return [ ], 'routes' => [ + // SNIPCART ROUTES - Désactivées, voir assets/snipcart-archive/README.md pour restauration + /* [ 'pattern' => '(:any)/validate.json', 'method' => 'GET', @@ -144,5 +146,6 @@ return [ return Response::json(['status' => 'success'], 200); } ] + */ ] ]; diff --git a/site/languages/en.php b/site/languages/en.php index 55c6d63..19e9aec 100644 --- a/site/languages/en.php +++ b/site/languages/en.php @@ -13,7 +13,23 @@ return [ 'backToShop' => 'Back to shop', 'supportText' => 'To support us, you can also', 'makeDonation' => 'make a donation', + + // Shop / Cart 'addToCart' => 'Add to cart', + 'cart' => 'Cart', + 'cartEmpty' => 'Your cart is empty', + 'total' => 'Total', + 'checkout' => 'Checkout', + 'remove' => 'Remove', + 'inStock' => 'In stock', + 'outOfStock' => 'Out of stock', + 'addingToCart' => 'Adding...', + 'addedToCart' => 'Added! ✓', + 'errorAddToCart' => 'Error - Try again', + 'closeCart' => 'Close cart', + 'loading' => 'Loading...', + 'productNotFound' => 'Product not found', + 'selectVariant' => 'Select', // Blueprints - Home 'home.title' => 'Home', diff --git a/site/languages/fr.php b/site/languages/fr.php index 64f3f5e..249bb4d 100644 --- a/site/languages/fr.php +++ b/site/languages/fr.php @@ -13,7 +13,23 @@ return [ 'backToShop' => 'Retour à la boutique', 'supportText' => 'Pour nous soutenir, vous pouvez aussi', 'makeDonation' => 'faire un don', + + // Shop / Cart 'addToCart' => 'Ajouter au panier', + 'cart' => 'Panier', + 'cartEmpty' => 'Votre panier est vide', + 'total' => 'Total', + 'checkout' => 'Passer commande', + 'remove' => 'Retirer', + 'inStock' => 'En stock', + 'outOfStock' => 'Rupture de stock', + 'addingToCart' => 'Ajout en cours...', + 'addedToCart' => 'Ajouté ! ✓', + 'errorAddToCart' => 'Erreur - Réessayer', + 'closeCart' => 'Fermer le panier', + 'loading' => 'Chargement...', + 'productNotFound' => 'Produit non trouvé', + 'selectVariant' => 'Choisir', // Blueprints - Home 'home.title' => 'Accueil', diff --git a/site/snippets/buy-button--t-shirt.php b/site/snippets/buy-button--t-shirt.php new file mode 100644 index 0000000..489b08d --- /dev/null +++ b/site/snippets/buy-button--t-shirt.php @@ -0,0 +1,20 @@ +
+
+

+
+ + +
\ No newline at end of file diff --git a/site/snippets/buy-button.php b/site/snippets/buy-button.php new file mode 100644 index 0000000..7769f2e --- /dev/null +++ b/site/snippets/buy-button.php @@ -0,0 +1,25 @@ +
+
+

+
+ + + + +
diff --git a/site/snippets/cart-drawer.php b/site/snippets/cart-drawer.php new file mode 100644 index 0000000..8ba5459 --- /dev/null +++ b/site/snippets/cart-drawer.php @@ -0,0 +1,32 @@ +
+
+
+
+

+ +
+ +
+
+

+
+ +
+
+ + +
+
\ No newline at end of file diff --git a/site/snippets/footer.php b/site/snippets/footer.php index 6acee68..91cbf60 100644 --- a/site/snippets/footer.php +++ b/site/snippets/footer.php @@ -1,3 +1,5 @@ + + - - - - + + + + + + + + + + + diff --git a/site/snippets/header.php b/site/snippets/header.php index 3582006..57257c8 100644 --- a/site/snippets/header.php +++ b/site/snippets/header.php @@ -12,6 +12,7 @@ + diff --git a/site/templates/home.php b/site/templates/home.php index 93bfc37..dcb47e5 100644 --- a/site/templates/home.php +++ b/site/templates/home.php @@ -1,35 +1,24 @@ $site->title(), 'template' => 'store']) ?> -
-

- baseline()->or('Bienvenue sur la boutique de soutien à Index') ?> -

+
+

+ baseline()->or('Bienvenue sur la boutique de soutien à Index') ?> +

-
- children()->listed() as $product): ?> -
-
- files()->sortBy('sort', 'asc')->first()): ?> - $cover, - 'alt' => $product->title()->html(), - 'preset' => 'product-card', - 'size' => 25, - 'lazy' => true - ]) ?> - -
-

title()->html() ?>

-

price() ?>€

- -
- -
+
-

- - -

-
+
+

+
+ + + +

+ + +

+
diff --git a/site/templates/product.php b/site/templates/product.php index d836f63..46d2487 100644 --- a/site/templates/product.php +++ b/site/templates/product.php @@ -1,114 +1,47 @@ - $page->title(), 'template' => 'shop']) ?> +shopifyHandle()->or($page->slug()); -
- +snippet('header', ['title' => $page->title(), 'template' => 'shop']); +?> -
+
+ + +
+ +
+

+
+ +
-
+ - ['assets/js/product-size.js', 'assets/js/snipcart.js', 'assets/js/product-gallery.js']]) ?> + +
+
+ + ['product']]) ?>