wip avec résolution de conflits

This commit is contained in:
gcch 2026-02-27 14:38:50 +01:00
commit ef19ba2b72
208 changed files with 178625 additions and 192002 deletions

View file

@ -1,32 +1,32 @@
<?php
declare(strict_types=1);
/**
* Le modèle de la Page 404.
*/
declare(strict_types=1);
use HaikuAtelier\WP\Resource;
use Timber\Timber;
// Contexte et modèles
$contexte = Timber::context();
$modeles = ['404.twig'];
$context = Timber::context();
$templates = ['404.twig'];
// Charge les scripts et styles de la page
/**
* Charge les scripts et styles de la page.
*
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
*/
function charge_scripts_styles_page_404(): void {
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-a-propos',
src: get_template_directory_uri() . '/assets/css/pages/page-modele-simple.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-modele-simple.css'),
media: 'all',
);
Resource::enqueue_style_file(
handle: 'haiku-atelier-2024-styles-page-a-propos',
path: '/assets/css/pages/page-modele-simple.css'
);
}
add_action('wp_enqueue_scripts', 'charge_scripts_styles_page_404');
// Rendu
Timber::render(
filenames: $modeles,
data: $contexte,
data: $context,
filenames: $templates
);

View file

@ -1,63 +1,55 @@
<?php
declare(strict_types=1);
/**
* Le modèle de la Page Boutique (« E-Shop »).
*/
declare(strict_types=1);
use HaikuAtelier\Data\Product;
use HaikuAtelier\WP\Resource;
use Timber\Timber;
require_once __DIR__ . '/src/inc/TraitementInformations.php';
// Contexte et modèles
$contexte = Timber::context();
$modeles = ['boutique.twig'];
$context = Timber::context();
$templates = ['boutique.twig'];
/** @var list<WC_Product> $informations_produits Les informations brutes des Produits. */
$informations_produits = wc_get_products([
'limit' => 12,
'order' => 'DESC',
'orderby' => 'date',
'status' => 'publish',
]);
/** @var list<WC_Product> $wc_products Les informations brutes des Produits. */
$wc_products = wc_get_products(['limit' => 12, 'order' => 'DESC', 'orderby' => 'date', 'status' => 'publish']);
/** @var mixed $produits Les informations strictement nécessaires pour la grille des Produits. */
$produits = array_map(
callback: recupere_informations_produit_shop(...),
array: $informations_produits,
$products = array_map(
callback: Product::new(...),
array: $wc_products
);
$contexte['produits'] = $produits;
$context['products'] = $products;
/**
* Charge les Scripts nécessaires pour la page Boutique.
* Charge les scripts et styles de la page.
*
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
*/
function charge_scripts_page_boutique(): void {
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-boutique',
src: get_template_directory_uri() . '/assets/css/pages/page-boutique.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-boutique.css'),
media: 'all',
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-scripts-page-boutique',
src: get_template_directory_uri() . '/assets/js/scripts-page-boutique.js',
deps: [],
version: filemtime(get_template_directory() . '/assets/js/scripts-page-boutique.js'),
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-scripts-menu-categories',
src: get_template_directory_uri() . '/assets/js/scripts-menu-categories.js',
deps: [],
version: filemtime(get_template_directory() . '/assets/js/scripts-menu-categories.js'),
);
Resource::enqueue_style_file(
handle: 'haiku-atelier-2024-styles-page-boutique',
path: '/assets/css/pages/page-boutique.css'
);
Resource::enqueue_script_module_file(
id: 'haiku-atelier-2024-scripts-page-boutique',
path: '/assets/js/scripts-page-boutique.js'
);
Resource::enqueue_script_module_file(
id: 'haiku-atelier-2024-scripts-menu-categories',
path: '/assets/js/scripts-menu-categories.js'
);
}
add_action('wp_enqueue_scripts', 'charge_scripts_page_boutique');
// Rendu
// $lal = wp_json_encode($context);
// echo "<script>console.debug({$lal});</script>";
Timber::render(
filenames: $modeles,
data: $contexte,
data: $context,
filenames: $templates
);

View file

@ -4,16 +4,66 @@
font-weight: 100 900;
font-style: normal;
font-display: swap;
src: url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2") format(woff2) tech(variations), url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2") format("woff2-variations"), url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2") format("woff2"), url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.ttf") format("truetype");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
src:
url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2")
format(woff2) tech(variations),
url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2")
format("woff2-variations"),
url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2")
format("woff2"),
url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.ttf")
format("truetype");
unicode-range:
U+0000-00FF,
U+0131,
U+0152-0153,
U+02BB-02BC,
U+02C6,
U+02DA,
U+02DC,
U+2000-206F,
U+2074,
U+20AC,
U+2122,
U+2191,
U+2193,
U+2212,
U+2215,
U+FEFF,
U+FFFD;
}
@font-face {
font-family: Lato;
font-weight: 100 900;
font-style: italic;
font-display: swap;
src: url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2") format(woff2) tech(variations), url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2") format("woff2-variations"), url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2") format("woff2"), url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.ttf") format("truetype");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
src:
url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2")
format(woff2) tech(variations),
url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2")
format("woff2-variations"),
url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2")
format("woff2"),
url("/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.ttf")
format("truetype");
unicode-range:
U+0000-00FF,
U+0131,
U+0152-0153,
U+02BB-02BC,
U+02C6,
U+02DA,
U+02DC,
U+2000-206F,
U+2074,
U+20AC,
U+2122,
U+2191,
U+2193,
U+2212,
U+2215,
U+FEFF,
U+FFFD;
}
@font-face {
font-family: Myriad;
@ -21,7 +71,10 @@
font-style: normal;
font-display: swap;
font-stretch: 70% 110%;
src: url("/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable.woff2") format("woff2"), url("/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable.ttf") format("truetype");
src:
url("/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable.woff2") format("woff2"),
url("/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable.ttf")
format("truetype");
}
@font-face {
font-family: Myriad;
@ -29,11 +82,15 @@
font-style: italic;
font-display: swap;
font-stretch: 70% 110%;
src: url("/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable-italic.woff2") format("woff2"), url("/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable-italic.ttf") format("truetype");
src:
url("/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable-italic.woff2")
format("woff2"),
url("/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable-italic.ttf")
format("truetype");
}
:root {
/* Couleurs */
--couleur-blanc: #fff;
--couleur-blanc: #ffffff;
--couleur-blanc-fond: rgb(255 255 255 / 90%);
--couleur-gris: #eceaeb;
--couleur-gris-fonce: #808080;
@ -176,14 +233,15 @@ button, input, select, textarea {
html {
font: 1rem/var(--hauteur-ligne-classique) Lato;
font-optical-sizing: auto;
font-variant-ligatures: common-ligatures no-discretionary-ligatures no-historical-ligatures
contextual;
font-kerning: normal;
font-variant-ligatures: common-ligatures no-discretionary-ligatures no-historical-ligatures contextual;
-webkit-font-smoothing: antialiased; /* 2 */
color: var(--couleur-noir);
text-decoration-skip-ink: auto;
text-size-adjust: none; /* 2 */
text-rendering: geometricprecision; /* 3 */
letter-spacing: var(--espacement-inter-lettres-etendu-s);
-webkit-font-smoothing: antialiased; /* 2 */
}
strong {
@ -224,7 +282,8 @@ button:not[disabled]:active {
}
}
button:disabled, button[disabled] {
background: repeating-conic-gradient(var(--couleur-noir) 0% 25%, transparent 0% 100%) 1px 0.5px/2px 2px;
background: repeating-conic-gradient(var(--couleur-noir) 0% 25%, transparent 0% 100%) 1px
0.5px/2px 2px;
outline-color: transparent;
}
button.bouton-case-pleine {
@ -294,27 +353,41 @@ input, select, textarea {
background: var(--couleur-gris);
transition: 0.2s background;
}
input:focus-visible, input:focus-within, input:active, select:focus-visible, select:focus-within, select:active, textarea:focus-visible, textarea:focus-within, textarea:active {
input:focus-visible,
input:focus-within,
input:active,
select:focus-visible,
select:focus-within,
select:active,
textarea:focus-visible,
textarea:focus-within,
textarea:active {
z-index: 10;
outline: 2px dashed var(--couleur-noir);
}
input:disabled, input[disabled], select:disabled, select[disabled], textarea:disabled, textarea[disabled] {
background: repeating-conic-gradient(var(--couleur-noir) 0% 25%, transparent 0% 100%) 1px 0.5px/2px 2px;
input:disabled,
input[disabled],
select:disabled,
select[disabled],
textarea:disabled,
textarea[disabled] {
background: repeating-conic-gradient(var(--couleur-noir) 0% 25%, transparent 0% 100%) 1px
0.5px/2px 2px;
outline-color: transparent;
}
input:is([type=email], [type=text], [type=tel])::placeholder, textarea::placeholder {
input:is([type="email"], [type="text"], [type="tel"])::placeholder, textarea::placeholder {
text-transform: lowercase;
letter-spacing: var(--espacement-inter-lettres-etendu-s);
}
input:is([type=email], [type=text], [type=tel])::selection, textarea::selection {
input:is([type="email"], [type="text"], [type="tel"])::selection, textarea::selection {
color: var(--couleur-blanc);
background: var(--couleur-noir);
}
input:is([type=email], [type=text], [type=tel]):user-valid, textarea:user-valid {
input:is([type="email"], [type="text"], [type="tel"]):user-valid, textarea:user-valid {
background: var(--couleur-jaune);
}
input:is([type=email], [type=text], [type=tel]):user-invalid, textarea:user-invalid {
input:is([type="email"], [type="text"], [type="tel"]):user-invalid, textarea:user-invalid {
background: var(--couleur-gris);
}
@ -322,7 +395,7 @@ input, label, select, textarea {
cursor: pointer;
}
input[type=checkbox], input[type=radio] {
input[type="checkbox"], input[type="radio"] {
width: var(--espace-l);
height: var(--espace-l);
padding: initial;
@ -330,48 +403,50 @@ input[type=checkbox], input[type=radio] {
appearance: none;
transition: 0.2s background;
}
input[type=checkbox]:checked, input[type=radio]:checked {
input[type="checkbox"]:checked, input[type="radio"]:checked {
background: var(--couleur-jaune);
}
input[type=checkbox]:checked::before, input[type=radio]:checked::before {
input[type="checkbox"]:checked::before, input[type="radio"]:checked::before {
content: "x";
position: relative;
bottom: 0.1rem;
left: 0.35rem;
}
@media (hover: hover) {
input[type=checkbox]:checked:hover, input[type=radio]:checked:hover {
input[type="checkbox"]:checked:hover, input[type="radio"]:checked:hover {
color: var(--couleur-noir);
}
}
input[type=checkbox]:not(:checked):user-valid, input[type=radio]:not(:checked):user-valid {
input[type="checkbox"]:not(:checked):user-valid, input[type="radio"]:not(:checked):user-valid {
background: initial;
}
input[type=checkbox], input[type=radio] {
input[type="checkbox"], input[type="radio"] {
/*
* 1. Pour un alignement parfait du label avec la case à cocher.
*/
}
label:has(~ input[type=checkbox], ~ input[type=radio]), input[type=checkbox] + label, input[type=radio] + label {
label:has(~ input[type="checkbox"], ~ input[type="radio"]),
input[type="checkbox"] + label,
input[type="radio"] + label {
padding-top: 1px; /* 1 */
font-size: 0.9rem;
}
@media (hover: hover) {
input[type=checkbox]:hover, input[type=radio]:hover {
input[type="checkbox"]:hover, input[type="radio"]:hover {
background: var(--couleur-jaune);
}
}
input[type=radio] {
input[type="radio"] {
border-radius: 100%;
appearance: initial;
}
input[type=radio]:checked {
input[type="radio"]:checked {
display: inline-flex;
place-content: center;
place-items: center;
}
input[type=radio]:checked::before {
input[type="radio"]:checked::before {
content: " ";
inset: initial;
display: inline-block;
@ -413,7 +488,14 @@ a {
text-decoration: underline; /* 1 */
text-decoration-color: transparent; /* 1 */
text-decoration-skip-ink: auto; /* 1 */
transition: 0.2s background, 0.2s border-color, 0.2s color, 0.2s font-weight, 0.2s outline-color, 0.2s letter-spacing, 0.2s text-decoration-color; /* 3 */
transition:
0.2s background,
0.2s border-color,
0.2s color,
0.2s font-weight,
0.2s outline-color,
0.2s letter-spacing,
0.2s text-decoration-color; /* 3 */
text-decoration-skip: edges; /* 1 */
/* Change les couleurs de l'arrière-plan et du contour pour marquer le focus. */
}
@ -499,7 +581,9 @@ ul.avec-puce-cercle {
}
ul.avec-puce-cercle a {
padding-left: var(--liste-puce-cercle-lien-marges-internes-ligne-debut); /* 1 */
background: no-repeat var(--liste-puce-cercle-puce-position-horizontale) center/var(--liste-puce-cercle-puce-taille) url("/app/themes/haiku-atelier-2024/assets/img/icons/dot.svg"); /* 2 */
background: no-repeat var(--liste-puce-cercle-puce-position-horizontale) center/var(
--liste-puce-cercle-puce-taille
) url("/app/themes/haiku-atelier-2024/assets/img/icons/dot.svg"); /* 2 */
}
/* * Styles pour un bandeau défilant. */
@ -546,7 +630,7 @@ ul.avec-puce-cercle a {
transform: translateX(-100%);
}
}
body:has(#menu-mobile:not([aria-hidden=true])) {
body:has(#menu-mobile:not([aria-hidden="true"])) {
touch-action: none;
overflow: hidden;
}
@ -566,11 +650,11 @@ body:has(#menu-mobile:not([aria-hidden=true])) {
transition: display 400ms allow-discrete;
-webkit-overflow-scrolling: none;
}
#menu-mobile[aria-hidden=true] {
#menu-mobile[aria-hidden="true"] {
display: none;
animation: fade-out 400ms both;
}
#menu-mobile[aria-hidden=true] .menu-modale__fond {
#menu-mobile[aria-hidden="true"] .menu-modale__fond {
animation: fade-out 400ms both;
}
#menu-mobile .menu-modale__fond {
@ -702,11 +786,13 @@ body:has(#menu-mobile:not([aria-hidden=true])) {
/* Dispositions */
--liste-puce-cercle-puce-position-horizontale: 3.5ch; /* 3 */
}
#en-tete .menu-navigation__entree:has(a[aria-current=page]) {
background: url("/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche.svg") center/auto 90% no-repeat;
#en-tete .menu-navigation__entree:has(a[aria-current="page"]) {
background: url("/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche.svg") center/auto
90% no-repeat;
}
#en-tete .menu-navigation__entree--courante {
background: url("/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche.svg") center/auto 90% no-repeat;
background: url("/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche.svg") center/auto
90% no-repeat;
}
#en-tete .menu-navigation__entree a {
display: inline-block; /* 1 */
@ -715,7 +801,8 @@ body:has(#menu-mobile:not([aria-hidden=true])) {
}
@media (hover: hover) {
#en-tete .menu-navigation__entree:hover {
background: url("/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche.svg") center/auto 90% no-repeat;
background: url("/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche.svg") center/auto
90% no-repeat;
}
}
@media (width <= 1000px) {
@ -731,21 +818,24 @@ body:has(#menu-mobile:not([aria-hidden=true])) {
text-align: center;
}
#en-tete .compte-panier[disabled] {
background: repeating-conic-gradient(var(--couleur-noir) 0% 25%, transparent 0% 100%) 1px 0.5px/2px 2px;
background: repeating-conic-gradient(var(--couleur-noir) 0% 25%, transparent 0% 100%) 1px
0.5px/2px 2px;
}
#en-tete .compte-panier[disabled] a:hover, #en-tete .compte-panier[disabled] a:active, #en-tete .compte-panier[disabled] a:focus-within {
#en-tete .compte-panier[disabled] a:hover,
#en-tete .compte-panier[disabled] a:active,
#en-tete .compte-panier[disabled] a:focus-within {
border: 1px solid var(--couleur-noir);
background: initial;
}
#en-tete .compte-panier a {
text-transform: lowercase;
padding-block: var(--espace-2xs);
padding-inline: var(--espace-s);
text-transform: lowercase;
}
#en-tete .compte-panier a.lien-compte {
border-color: transparent;
}
#en-tete .compte-panier a[data-contient-articles=true] {
#en-tete .compte-panier a[data-contient-articles="true"] {
background: var(--couleur-jaune);
}
#en-tete .conteneur {
@ -827,7 +917,8 @@ body:has(#menu-mobile:not([aria-hidden=true])) {
}
#menu-categories-produits ul {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(var(--menu-entree-longueur-minimale), 1fr)); /* 1 */
grid-template-columns:
repeat(auto-fit, minmax(var(--menu-entree-longueur-minimale), 1fr)); /* 1 */
gap: 1px;
place-items: center;
/*
@ -938,7 +1029,9 @@ body:has(#menu-mobile:not([aria-hidden=true])) {
top: var(--colonne-gauche-position-haut);
height: var(--colonne-gauche-photo-hauteur);
}
.photos-produit .colonne.colonne-gauche figure, .photos-produit .colonne.colonne-gauche picture, .photos-produit .colonne.colonne-gauche img {
.photos-produit .colonne.colonne-gauche figure,
.photos-produit .colonne.colonne-gauche picture,
.photos-produit .colonne.colonne-gauche img {
height: 100%;
}
.photos-produit .colonne.colonne-droite img {
@ -1013,7 +1106,8 @@ body:has(#menu-mobile:not([aria-hidden=true])) {
--carte-produit-longueur-maximale: 1000px;
display: grid;
grid-auto-rows: 1fr;
grid-template-columns: repeat(auto-fit, minmax(var(--carte-produit-longueur-minimale), 1fr)); /* 1 */
grid-template-columns:
repeat(auto-fit, minmax(var(--carte-produit-longueur-minimale), 1fr)); /* 1 */
gap: 1px; /* 2 */
min-height: var(--grille-produits-hauteur-minimale);
}
@ -1278,7 +1372,9 @@ body:has(#menu-mobile:not([aria-hidden=true])) {
.details-produit__textes .section-textuelle:not(:last-of-type) {
border-block-end: 1px solid var(--couleur-noir);
}
.details-produit__textes .section-textuelle:has(button[aria-expanded=false]) .section-textuelle__contenu {
.details-produit__textes
.section-textuelle:has(button[aria-expanded="false"])
.section-textuelle__contenu {
display: none;
}
.details-produit__textes .section-textuelle h3 {
@ -1378,7 +1474,10 @@ body:has(#menu-mobile:not([aria-hidden=true])) {
position: relative;
}
@media (hover: hover) {
.produits-similaires .grille-produits-similaires article figure a:hover .produit__illustration__survol {
.produits-similaires
.grille-produits-similaires
article figure a:hover
.produit__illustration__survol {
visibility: visible;
opacity: 1;
transition: 0.3s opacity, 0.3s visibility;
@ -1452,4 +1551,4 @@ body:has(#menu-mobile:not([aria-hidden=true])) {
text-align: right;
}
/*# sourceMappingURL=main.css.map */
/* # sourceMappingURL=main.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -156,4 +156,4 @@
}
}
/*# sourceMappingURL=page-a-propos.css.map */
/* # sourceMappingURL=page-a-propos.css.map */

View file

@ -41,8 +41,14 @@
margin: auto;
visibility: visible;
opacity: 1;
mask-image: linear-gradient(
var(--mask-direction, to right),
hsla(0, 0%, 0%, 0),
hsl(0, 0%, 0%) 20%,
hsl(0, 0%, 0%) 80%,
hsla(0, 0%, 0%, 0)
);
transition: 1s opacity ease-in-out, 1s visibility ease-in-out;
mask-image: linear-gradient(var(--mask-direction, to right), hsla(0, 0%, 0%, 0), hsl(0, 0%, 0%) 20%, hsl(0, 0%, 0%) 80%, hsla(0, 0%, 0%, 0));
}
#page-accueil .storytelling__animation[hidden] {
display: grid !important;
@ -112,4 +118,4 @@
}
}
/*# sourceMappingURL=page-accueil.css.map */
/* # sourceMappingURL=page-accueil.css.map */

View file

@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../../src/sass/pages/page-accueil.scss"],"names":[],"mappings":";AAEA;EAEE;EAGA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;AAIF;EACE;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAQA;EACE;EACA;EACA;EACA;;AAIF;EACE;EACA;EACA;;AAGF;EACE;EAIA;EACA;;AAGF;EACE;EAGA;EACA;EAGA;EACA;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAMN;EACE;IACE;;;AAIJ;EAjIF;IAkII;;;AAGF;EArIF;IAsII;;;;AAKJ;EACE;IACE","file":"page-accueil.css"}
{"version":3,"sourceRoot":"","sources":["../../../src/sass/pages/page-accueil.scss"],"names":[],"mappings":";AAEA;EAEE;EAGA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;AAIF;EACE;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAOA;;AAEA;EACE;EACA;EACA;EACA;;AAIF;EACE;EACA;EACA;;AAGF;EACE;EAIA;EACA;;AAGF;EACE;EAGA;EACA;EAGA;EACA;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAMN;EACE;IACE;;;AAIJ;EAjIF;IAkII;;;AAGF;EArIF;IAsII;;;;AAKJ;EACE;IACE","file":"page-accueil.css"}

View file

@ -9,4 +9,4 @@
padding: var(--espace-xl) 0;
}
/*# sourceMappingURL=page-boutique.css.map */
/* # sourceMappingURL=page-boutique.css.map */

View file

@ -1 +1,54 @@
#page-contact{--page-hauteur-minimale:calc(100svh - var(--en-tete-hauteur) - var(--pied-de-page-hauteur) - var(--espace-xl) - 1px);--page-marges-bloc-debut:var(--en-tete-hauteur);margin-top:var(--page-marges-bloc-debut);margin-bottom:var(--espace-xl);border-bottom:1px solid var(--couleur-noir);flex-flow:column;display:flex}#page-contact .contenu{width:min(50rem,100%);min-height:var(--page-hauteur-minimale);border:1px solid var(--couleur-noir);border-bottom:initial;flex-flow:column;place-items:center;margin:auto;font-style:italic;font-weight:500;display:flex}#page-contact .contenu__en-tete{width:100%;padding:var(--espace-m)var(--espace-xl);color:var(--couleur-blanc);background:var(--couleur-noir)}#page-contact .contenu__en-tete h2{text-transform:uppercase;width:fit-content;letter-spacing:var(--espacement-inter-lettres-etendu-l);margin:auto}#page-contact .contenu__textuel{max-width:34rem;height:100%;padding:0 var(--espace-xl);text-wrap:pretty;flex-flow:column;flex:1;place-content:center;display:flex}#page-contact .contenu__textuel p+p{margin-top:var(--espace-m)}@media (width<=50rem){#page-contact .contenu{border-right:initial;border-left:initial}}
#page-contact {
--page-hauteur-minimale: calc(
100svh - var(--en-tete-hauteur) - var(--pied-de-page-hauteur) - var(--espace-xl) - 1px
);
--page-marges-bloc-debut: var(--en-tete-hauteur);
margin-top: var(--page-marges-bloc-debut);
margin-bottom: var(--espace-xl);
border-bottom: 1px solid var(--couleur-noir);
flex-flow: column;
display: flex;
}
#page-contact .contenu {
width: min(50rem, 100%);
min-height: var(--page-hauteur-minimale);
border: 1px solid var(--couleur-noir);
border-bottom: initial;
flex-flow: column;
place-items: center;
margin: auto;
font-style: italic;
font-weight: 500;
display: flex;
}
#page-contact .contenu__en-tete {
width: 100%;
padding: var(--espace-m) var(--espace-xl);
color: var(--couleur-blanc);
background: var(--couleur-noir);
}
#page-contact .contenu__en-tete h2 {
text-transform: uppercase;
width: fit-content;
letter-spacing: var(--espacement-inter-lettres-etendu-l);
margin: auto;
}
#page-contact .contenu__textuel {
max-width: 34rem;
height: 100%;
padding: 0 var(--espace-xl);
text-wrap: pretty;
flex-flow: column;
flex: 1;
place-content: center;
display: flex;
}
#page-contact .contenu__textuel p + p {
margin-top: var(--espace-m);
}
@media (width <= 50rem) {
#page-contact .contenu {
border-right: initial;
border-left: initial;
}
}

View file

@ -94,4 +94,4 @@
}
}
/*# sourceMappingURL=page-modele-simple.css.map */
/* # sourceMappingURL=page-modele-simple.css.map */

View file

@ -74,7 +74,7 @@
* 2. Cache les flèches d'augmentation/diminution sur Chrome/Edge/Safari.
*/
}
#panneau-panier .panneau__grille-produits .detail-produit__actions input[type=number] {
#panneau-panier .panneau__grille-produits .detail-produit__actions input[type="number"] {
grid-column: 2;
width: 100%;
border: initial;
@ -82,7 +82,14 @@
text-align: center;
appearance: textfield; /* 1 */
}
#panneau-panier .panneau__grille-produits .detail-produit__actions input[type=number]::-webkit-outer-spin-button, #panneau-panier .panneau__grille-produits .detail-produit__actions input[type=number]::-webkit-inner-spin-button {
#panneau-panier
.panneau__grille-produits
.detail-produit__actions
input[type="number"]::-webkit-outer-spin-button,
#panneau-panier
.panneau__grille-produits
.detail-produit__actions
input[type="number"]::-webkit-inner-spin-button {
margin: 0; /* 2 */
appearance: none; /* 2 */
}
@ -227,7 +234,14 @@
#panneau-panier .panneau__instructions-code-promo {
padding: var(--espace-xl) var(--espace-l);
}
#panneau-panier .panneau__instructions-code-promo .panneau__instructions-code-promo__code-promo input, #panneau-panier .panneau__instructions-code-promo .panneau__instructions-code-promo__code-promo button {
#panneau-panier
.panneau__instructions-code-promo
.panneau__instructions-code-promo__code-promo
input,
#panneau-panier
.panneau__instructions-code-promo
.panneau__instructions-code-promo__code-promo
button {
flex: 1;
}
#panneau-panier .panneau__sous-totaux {
@ -289,10 +303,16 @@
font-size: 0.8rem;
font-style: italic;
}
#panneau-informations-client .panneau__formulaires .panneau__formulaires__separation-adresses label {
#panneau-informations-client
.panneau__formulaires
.panneau__formulaires__separation-adresses
label {
text-transform: lowercase;
}
#panneau-informations-client .panneau__formulaires .panneau__formulaires__paiement .formulaire__paiement__attente-renseignement-formulaires {
#panneau-informations-client
.panneau__formulaires
.panneau__formulaires__paiement
.formulaire__paiement__attente-renseignement-formulaires {
align-content: center;
width: 100%;
padding: 0;
@ -301,7 +321,11 @@
color: grey;
text-align: center;
}
#panneau-informations-client .panneau__formulaires .panneau__formulaires__paiement .formulaire__paiement__attente-renseignement-formulaires p + p {
#panneau-informations-client
.panneau__formulaires
.panneau__formulaires__paiement
.formulaire__paiement__attente-renseignement-formulaires
p + p {
margin-top: 1lh;
}
#panneau-informations-client .panneau__formulaires .panneau__formulaires__message {
@ -335,7 +359,11 @@
place-items: center;
justify-content: space-between;
}
#panneau-informations-client .formulaire .formulaire__champs .formulaire__champs__champ + .formulaire__champs__champ {
#panneau-informations-client
.formulaire
.formulaire__champs
.formulaire__champs__champ
+ .formulaire__champs__champ {
margin-top: var(--espace-l);
}
#panneau-informations-client .formulaire label {
@ -426,11 +454,11 @@
margin-top: var(--espace-m);
font-size: initial;
}
#page-panier[data-contient-articles=false] .panneau {
#page-panier[data-contient-articles="false"] .panneau {
display: none;
}
#page-panier[data-contient-articles=false] .panier-vide {
#page-panier[data-contient-articles="false"] .panier-vide {
display: block;
}
/*# sourceMappingURL=page-panier.css.map */
/* # sourceMappingURL=page-panier.css.map */

View file

@ -57,7 +57,8 @@
grid-template-rows: 1fr;
border-bottom: 1px solid var(--couleur-noir);
}
#page-succes-commande .contenu__rappel-commande__produit:only-child, #page-succes-commande .contenu__rappel-commande__produit:last-of-type {
#page-succes-commande .contenu__rappel-commande__produit:only-child,
#page-succes-commande .contenu__rappel-commande__produit:last-of-type {
border-bottom: initial;
}
#page-succes-commande .contenu__rappel-commande__produit__illustratif {
@ -105,4 +106,4 @@
}
}
/*# sourceMappingURL=page-succes-commande.css.map */
/* # sourceMappingURL=page-succes-commande.css.map */

View file

@ -1 +1,9 @@
<svg viewBox="0 0 90 90" xmlns="http://www.w3.org/2000/svg"><path fill="#E7FFB4" d="M85.241 48.817c-1.365-3.553-4.989-5.856-9.771-6.737 7.718-5.116 11.871-12.229 9.706-17.868-2.79-7.268-15.031-9.329-27.335-4.602-3.173 1.218-6.032 2.768-8.491 4.521l-.024-.068c-2.791-7.269-15.035-9.329-27.338-4.601C9.681 24.19 1.969 33.914 4.76 41.184c1.262 3.283 4.458 5.501 8.712 6.514C6.419 52.746 2.721 59.473 4.79 64.857c2.791 7.27 15.033 9.329 27.337 4.602 3.077-1.183 5.866-2.676 8.278-4.366.076.284.162.565.269.843 2.791 7.271 15.032 9.33 27.336 4.604 12.31-4.73 20.022-14.456 17.231-21.723"/></svg>
<svg
viewBox="0 0 90 90"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill="#E7FFB4"
d="M85.241 48.817c-1.365-3.553-4.989-5.856-9.771-6.737 7.718-5.116 11.871-12.229 9.706-17.868-2.79-7.268-15.031-9.329-27.335-4.602-3.173 1.218-6.032 2.768-8.491 4.521l-.024-.068c-2.791-7.269-15.035-9.329-27.338-4.601C9.681 24.19 1.969 33.914 4.76 41.184c1.262 3.283 4.458 5.501 8.712 6.514C6.419 52.746 2.721 59.473 4.79 64.857c2.791 7.27 15.033 9.329 27.337 4.602 3.077-1.183 5.866-2.676 8.278-4.366.076.284.162.565.269.843 2.791 7.271 15.032 9.33 27.336 4.604 12.31-4.73 20.022-14.456 17.231-21.723"
/>
</svg>

Before

Width:  |  Height:  |  Size: 590 B

After

Width:  |  Height:  |  Size: 611 B

Before After
Before After

View file

@ -1 +1,17 @@
<svg viewBox="43.801 35.326 186.516 130.185" xmlns="http://www.w3.org/2000/svg"><path opacity=".5" fill="#DFDEDE" d="M226.058 108.87c-3.021-7.855-11.031-12.949-21.609-14.896 17.068-11.315 26.261-27.05 21.471-39.518-6.177-16.074-33.244-20.635-60.461-10.179-7.015 2.694-13.343 6.124-18.778 10.001-.018-.05-.032-.102-.052-.152-6.174-16.076-33.251-20.633-60.46-10.178-27.223 10.456-44.276 31.967-38.105 48.043 2.792 7.266 9.862 12.164 19.273 14.402-15.603 11.168-23.785 26.049-19.206 37.953 6.176 16.079 33.251 20.633 60.46 10.176 6.809-2.611 12.975-5.918 18.311-9.656.169.627.358 1.251.595 1.867 6.174 16.075 33.241 20.631 60.462 10.176 27.22-10.455 44.272-31.965 38.099-48.039"/><path fill="none" stroke="#2B2B2B" stroke-width="5" stroke-miterlimit="10" d="M226.058 108.87c-3.021-7.855-11.031-12.949-21.609-14.896 17.068-11.315 26.261-27.05 21.471-39.518-6.177-16.074-33.244-20.635-60.461-10.179-7.015 2.694-13.343 6.124-18.778 10.001-.018-.05-.032-.102-.052-.152-6.174-16.076-33.251-20.633-60.46-10.178-27.223 10.456-44.276 31.967-38.105 48.043 2.792 7.266 9.862 12.164 19.273 14.402-15.603 11.168-23.785 26.049-19.206 37.953 6.176 16.079 33.251 20.633 60.46 10.176 6.809-2.611 12.975-5.918 18.311-9.656.169.627.358 1.251.595 1.867 6.174 16.075 33.241 20.631 60.462 10.176 27.22-10.455 44.272-31.965 38.099-48.039z"/></svg>
<svg
viewBox="43.801 35.326 186.516 130.185"
xmlns="http://www.w3.org/2000/svg"
>
<path
opacity=".5"
fill="#DFDEDE"
d="M226.058 108.87c-3.021-7.855-11.031-12.949-21.609-14.896 17.068-11.315 26.261-27.05 21.471-39.518-6.177-16.074-33.244-20.635-60.461-10.179-7.015 2.694-13.343 6.124-18.778 10.001-.018-.05-.032-.102-.052-.152-6.174-16.076-33.251-20.633-60.46-10.178-27.223 10.456-44.276 31.967-38.105 48.043 2.792 7.266 9.862 12.164 19.273 14.402-15.603 11.168-23.785 26.049-19.206 37.953 6.176 16.079 33.251 20.633 60.46 10.176 6.809-2.611 12.975-5.918 18.311-9.656.169.627.358 1.251.595 1.867 6.174 16.075 33.241 20.631 60.462 10.176 27.22-10.455 44.272-31.965 38.099-48.039"
/>
<path
fill="none"
stroke="#2B2B2B"
stroke-width="5"
stroke-miterlimit="10"
d="M226.058 108.87c-3.021-7.855-11.031-12.949-21.609-14.896 17.068-11.315 26.261-27.05 21.471-39.518-6.177-16.074-33.244-20.635-60.461-10.179-7.015 2.694-13.343 6.124-18.778 10.001-.018-.05-.032-.102-.052-.152-6.174-16.076-33.251-20.633-60.46-10.178-27.223 10.456-44.276 31.967-38.105 48.043 2.792 7.266 9.862 12.164 19.273 14.402-15.603 11.168-23.785 26.049-19.206 37.953 6.176 16.079 33.251 20.633 60.46 10.176 6.809-2.611 12.975-5.918 18.311-9.656.169.627.358 1.251.595 1.867 6.174 16.075 33.241 20.631 60.462 10.176 27.22-10.455 44.272-31.965 38.099-48.039z"
/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

View file

@ -1 +1,17 @@
<svg viewBox="43.727 35.716 186.52 130.194" xmlns="http://www.w3.org/2000/svg"><path opacity=".5" fill="#DFDEDE" d="M225.982 109.258c-3.021-7.855-11.031-12.949-21.609-14.896 17.068-11.315 26.261-27.05 21.471-39.518-6.177-16.074-33.244-20.635-60.461-10.179-7.015 2.694-13.343 6.124-18.778 10.001-.018-.05-.032-.102-.052-.152-6.174-16.076-33.251-20.633-60.46-10.178-27.222 10.456-44.276 31.967-38.104 48.043 2.792 7.266 9.862 12.164 19.273 14.402-15.603 11.168-23.785 26.049-19.206 37.953 6.176 16.079 33.251 20.633 60.46 10.176 6.809-2.611 12.975-5.918 18.311-9.656.169.627.358 1.251.595 1.867 6.174 16.075 33.241 20.631 60.462 10.176 27.22-10.455 44.272-31.965 38.098-48.039"/><path fill="none" stroke="#D8FFA5" stroke-width="5" stroke-miterlimit="10" d="M225.982 109.258c-3.021-7.855-11.031-12.949-21.609-14.896 17.068-11.315 26.261-27.05 21.471-39.518-6.177-16.074-33.244-20.635-60.461-10.179-7.015 2.694-13.343 6.124-18.778 10.001-.018-.05-.032-.102-.052-.152-6.174-16.076-33.251-20.633-60.46-10.178-27.222 10.456-44.276 31.967-38.104 48.043 2.792 7.266 9.862 12.164 19.273 14.402-15.603 11.168-23.785 26.049-19.206 37.953 6.176 16.079 33.251 20.633 60.46 10.176 6.809-2.611 12.975-5.918 18.311-9.656.169.627.358 1.251.595 1.867 6.174 16.075 33.241 20.631 60.462 10.176 27.22-10.455 44.272-31.965 38.098-48.039z"/></svg>
<svg
viewBox="43.727 35.716 186.52 130.194"
xmlns="http://www.w3.org/2000/svg"
>
<path
opacity=".5"
fill="#DFDEDE"
d="M225.982 109.258c-3.021-7.855-11.031-12.949-21.609-14.896 17.068-11.315 26.261-27.05 21.471-39.518-6.177-16.074-33.244-20.635-60.461-10.179-7.015 2.694-13.343 6.124-18.778 10.001-.018-.05-.032-.102-.052-.152-6.174-16.076-33.251-20.633-60.46-10.178-27.222 10.456-44.276 31.967-38.104 48.043 2.792 7.266 9.862 12.164 19.273 14.402-15.603 11.168-23.785 26.049-19.206 37.953 6.176 16.079 33.251 20.633 60.46 10.176 6.809-2.611 12.975-5.918 18.311-9.656.169.627.358 1.251.595 1.867 6.174 16.075 33.241 20.631 60.462 10.176 27.22-10.455 44.272-31.965 38.098-48.039"
/>
<path
fill="none"
stroke="#D8FFA5"
stroke-width="5"
stroke-miterlimit="10"
d="M225.982 109.258c-3.021-7.855-11.031-12.949-21.609-14.896 17.068-11.315 26.261-27.05 21.471-39.518-6.177-16.074-33.244-20.635-60.461-10.179-7.015 2.694-13.343 6.124-18.778 10.001-.018-.05-.032-.102-.052-.152-6.174-16.076-33.251-20.633-60.46-10.178-27.222 10.456-44.276 31.967-38.104 48.043 2.792 7.266 9.862 12.164 19.273 14.402-15.603 11.168-23.785 26.049-19.206 37.953 6.176 16.079 33.251 20.633 60.46 10.176 6.809-2.611 12.975-5.918 18.311-9.656.169.627.358 1.251.595 1.867 6.174 16.075 33.241 20.631 60.462 10.176 27.22-10.455 44.272-31.965 38.098-48.039z"
/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

View file

@ -1 +1,6 @@
<svg viewBox="94.634 56.652 88.879 79.521" xmlns="http://www.w3.org/2000/svg"><path d="m94.623 136.156 88.869-36.863-88.869-42.648s21.33 20.87 21.33 39.756c0 18.891-21.33 39.755-21.33 39.755"/></svg>
<svg
viewBox="94.634 56.652 88.879 79.521"
xmlns="http://www.w3.org/2000/svg"
>
<path d="m94.623 136.156 88.869-36.863-88.869-42.648s21.33 20.87 21.33 39.756c0 18.891-21.33 39.755-21.33 39.755" />
</svg>

Before

Width:  |  Height:  |  Size: 201 B

After

Width:  |  Height:  |  Size: 210 B

Before After
Before After

View file

@ -1 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="32.026 31.499 14.793 16.534"><path d="m32.026 31.499 6.858 16.534 7.935-16.534s-3.883 3.968-7.396 3.968c-3.515 0-7.397-3.968-7.397-3.968"/></svg>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="32.026 31.499 14.793 16.534"
>
<path d="m32.026 31.499 6.858 16.534 7.935-16.534s-3.883 3.968-7.396 3.968c-3.515 0-7.397-3.968-7.397-3.968" />
</svg>

Before

Width:  |  Height:  |  Size: 195 B

After

Width:  |  Height:  |  Size: 205 B

Before After
Before After

View file

@ -1,4 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="4.189 16.921 81.623 56.159" xmlns="http://www.w3.org/2000/svg">
<path d="M85.241 48.817c-1.365-3.553-4.989-5.856-9.771-6.737 7.718-5.116 11.871-12.229 9.706-17.868-2.79-7.268-15.031-9.329-27.335-4.602-3.173 1.218-6.032 2.768-8.491 4.521l-.024-.068c-2.791-7.269-15.035-9.329-27.338-4.601C9.681 24.19 1.969 33.914 4.76 41.184c1.262 3.283 4.458 5.501 8.712 6.514C6.419 52.746 2.721 59.473 4.79 64.857c2.791 7.27 15.033 9.329 27.337 4.602 3.077-1.183 5.866-2.676 8.278-4.366.076.284.162.565.269.843 2.791 7.271 15.032 9.33 27.336 4.604 12.31-4.73 20.022-14.456 17.231-21.723" fill="#808080" />
</svg>
<svg
viewBox="4.189 16.921 81.623 56.159"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M85.241 48.817c-1.365-3.553-4.989-5.856-9.771-6.737 7.718-5.116 11.871-12.229 9.706-17.868-2.79-7.268-15.031-9.329-27.335-4.602-3.173 1.218-6.032 2.768-8.491 4.521l-.024-.068c-2.791-7.269-15.035-9.329-27.338-4.601C9.681 24.19 1.969 33.914 4.76 41.184c1.262 3.283 4.458 5.501 8.712 6.514C6.419 52.746 2.721 59.473 4.79 64.857c2.791 7.27 15.033 9.329 27.337 4.602 3.077-1.183 5.866-2.676 8.278-4.366.076.284.162.565.269.843 2.791 7.271 15.032 9.33 27.336 4.604 12.31-4.73 20.022-14.456 17.231-21.723"
fill="#808080"
/>
</svg>

Before

Width:  |  Height:  |  Size: 651 B

After

Width:  |  Height:  |  Size: 667 B

Before After
Before After

View file

@ -1 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="2.433 9.473 85.134 70.17"><path fill="#E7FFB4" d="M84.857 38.272c-2.238-3.079-6.335-4.365-11.182-3.978 6.131-6.94 8.302-14.885 4.751-19.772-4.576-6.298-16.933-5.12-27.595 2.63-2.749 1.998-5.11 4.235-7.031 6.565l-.041-.06c-4.577-6.299-16.937-5.12-27.597 2.632C5.498 34.041.565 45.429 5.143 51.729c2.068 2.845 5.73 4.16 10.101 4.038-5.506 6.701-7.337 14.156-3.945 18.821 4.577 6.3 16.935 5.12 27.596-2.63 2.666-1.939 4.974-4.103 6.866-6.36.147.255.303.504.478.745 4.578 6.301 16.935 5.121 27.596-2.628 10.667-7.755 15.599-19.146 11.022-25.443"/></svg>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="2.433 9.473 85.134 70.17"
>
<path
fill="#E7FFB4"
d="M84.857 38.272c-2.238-3.079-6.335-4.365-11.182-3.978 6.131-6.94 8.302-14.885 4.751-19.772-4.576-6.298-16.933-5.12-27.595 2.63-2.749 1.998-5.11 4.235-7.031 6.565l-.041-.06c-4.577-6.299-16.937-5.12-27.597 2.632C5.498 34.041.565 45.429 5.143 51.729c2.068 2.845 5.73 4.16 10.101 4.038-5.506 6.701-7.337 14.156-3.945 18.821 4.577 6.3 16.935 5.12 27.596-2.63 2.666-1.939 4.974-4.103 6.866-6.36.147.255.303.504.478.745 4.578 6.301 16.935 5.121 27.596-2.628 10.667-7.755 15.599-19.146 11.022-25.443"
/>
</svg>

Before

Width:  |  Height:  |  Size: 598 B

After

Width:  |  Height:  |  Size: 619 B

Before After
Before After

View file

@ -1,4 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="4.189 16.921 81.623 56.159" xmlns="http://www.w3.org/2000/svg">
<path d="M85.241 48.817c-1.365-3.553-4.989-5.856-9.771-6.737 7.718-5.116 11.871-12.229 9.706-17.868-2.79-7.268-15.031-9.329-27.335-4.602-3.173 1.218-6.032 2.768-8.491 4.521l-.024-.068c-2.791-7.269-15.035-9.329-27.338-4.601C9.681 24.19 1.969 33.914 4.76 41.184c1.262 3.283 4.458 5.501 8.712 6.514C6.419 52.746 2.721 59.473 4.79 64.857c2.791 7.27 15.033 9.329 27.337 4.602 3.077-1.183 5.866-2.676 8.278-4.366.076.284.162.565.269.843 2.791 7.271 15.032 9.33 27.336 4.604 12.31-4.73 20.022-14.456 17.231-21.723" style="fill: rgb(73, 9, 24);"/>
</svg>
<svg
viewBox="4.189 16.921 81.623 56.159"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M85.241 48.817c-1.365-3.553-4.989-5.856-9.771-6.737 7.718-5.116 11.871-12.229 9.706-17.868-2.79-7.268-15.031-9.329-27.335-4.602-3.173 1.218-6.032 2.768-8.491 4.521l-.024-.068c-2.791-7.269-15.035-9.329-27.338-4.601C9.681 24.19 1.969 33.914 4.76 41.184c1.262 3.283 4.458 5.501 8.712 6.514C6.419 52.746 2.721 59.473 4.79 64.857c2.791 7.27 15.033 9.329 27.337 4.602 3.077-1.183 5.866-2.676 8.278-4.366.076.284.162.565.269.843 2.791 7.271 15.032 9.33 27.336 4.604 12.31-4.73 20.022-14.456 17.231-21.723"
style="fill: rgb(73, 9, 24)"
/>
</svg>

Before

Width:  |  Height:  |  Size: 665 B

After

Width:  |  Height:  |  Size: 681 B

Before After
Before After

View file

@ -1,4 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="4.189 16.921 81.623 56.159" xmlns="http://www.w3.org/2000/svg">
<path fill="#E7FFB4" d="M85.241 48.817c-1.365-3.553-4.989-5.856-9.771-6.737 7.718-5.116 11.871-12.229 9.706-17.868-2.79-7.268-15.031-9.329-27.335-4.602-3.173 1.218-6.032 2.768-8.491 4.521l-.024-.068c-2.791-7.269-15.035-9.329-27.338-4.601C9.681 24.19 1.969 33.914 4.76 41.184c1.262 3.283 4.458 5.501 8.712 6.514C6.419 52.746 2.721 59.473 4.79 64.857c2.791 7.27 15.033 9.329 27.337 4.602 3.077-1.183 5.866-2.676 8.278-4.366.076.284.162.565.269.843 2.791 7.271 15.032 9.33 27.336 4.604 12.31-4.73 20.022-14.456 17.231-21.723"/>
</svg>
<svg
viewBox="4.189 16.921 81.623 56.159"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill="#E7FFB4"
d="M85.241 48.817c-1.365-3.553-4.989-5.856-9.771-6.737 7.718-5.116 11.871-12.229 9.706-17.868-2.79-7.268-15.031-9.329-27.335-4.602-3.173 1.218-6.032 2.768-8.491 4.521l-.024-.068c-2.791-7.269-15.035-9.329-27.338-4.601C9.681 24.19 1.969 33.914 4.76 41.184c1.262 3.283 4.458 5.501 8.712 6.514C6.419 52.746 2.721 59.473 4.79 64.857c2.791 7.27 15.033 9.329 27.337 4.602 3.077-1.183 5.866-2.676 8.278-4.366.076.284.162.565.269.843 2.791 7.271 15.032 9.33 27.336 4.604 12.31-4.73 20.022-14.456 17.231-21.723"
/>
</svg>

Before

Width:  |  Height:  |  Size: 650 B

After

Width:  |  Height:  |  Size: 667 B

Before After
Before After

View file

@ -1 +1,24 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon line-color" data-name="Line Color" viewBox="0 0 24 24"><path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 19 5 5"/><path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 5 5 19" data-name="primary"/></svg>
<svg
xmlns="http://www.w3.org/2000/svg"
class="icon line-color"
data-name="Line Color"
viewBox="0 0 24 24"
>
<path
fill="none"
stroke="#000"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 19 5 5"
/>
<path
fill="none"
stroke="#000"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 5 5 19"
data-name="primary"
/>
</svg>

Before

Width:  |  Height:  |  Size: 358 B

After

Width:  |  Height:  |  Size: 432 B

Before After
Before After

View file

@ -1 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="34.739 35.077 8.402 7.319"><path d="M39.895 41.075q-1.494.606-2.617.369-1.123-.239-1.597-1.406-.445-1.097.188-2.068.634-.97 2.128-1.576 1.553-.63 2.641-.379 1.088.253 1.556 1.409.44 1.086-.134 2.046-.576.961-2.165 1.605M38.4 37.387q-1.168.474-1.66 1.053-.492.58-.208 1.281.28.69 1.028.773.748.085 1.939-.398 1.18-.479 1.658-1.06.477-.581.198-1.27-.289-.712-1.032-.785-.743-.072-1.923.406"/></svg>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="34.739 35.077 8.402 7.319"
>
<path d="M39.895 41.075q-1.494.606-2.617.369-1.123-.239-1.597-1.406-.445-1.097.188-2.068.634-.97 2.128-1.576 1.553-.63 2.641-.379 1.088.253 1.556 1.409.44 1.086-.134 2.046-.576.961-2.165 1.605M38.4 37.387q-1.168.474-1.66 1.053-.492.58-.208 1.281.28.69 1.028.773.748.085 1.939-.398 1.18-.479 1.658-1.06.477-.581.198-1.27-.289-.712-1.032-.785-.743-.072-1.923.406" />
</svg>

Before

Width:  |  Height:  |  Size: 446 B

After

Width:  |  Height:  |  Size: 456 B

Before After
Before After

View file

@ -1 +1,11 @@
<svg xmlns="http://www.w4.org/2000/svg" width="15" height="15" viewBox="0 0 15 15"><path d="M8.293 2.293a1 1 0 0 1 1.414 0l4.5 4.5a1 1 0 0 1 0 1.414l-4.5 4.5a1 1 0 0 1-1.414-1.414L11 8.5H1.5a1 1 0 0 1 0-2H11L8.293 3.707a1 1 0 0 1 0-1.414" fill="red"/></svg>
<svg
xmlns="http://www.w4.org/2000/svg"
width="15"
height="15"
viewBox="0 0 15 15"
>
<path
d="M8.293 2.293a1 1 0 0 1 1.414 0l4.5 4.5a1 1 0 0 1 0 1.414l-4.5 4.5a1 1 0 0 1-1.414-1.414L11 8.5H1.5a1 1 0 0 1 0-2H11L8.293 3.707a1 1 0 0 1 0-1.414"
fill="red"
/>
</svg>

Before

Width:  |  Height:  |  Size: 258 B

After

Width:  |  Height:  |  Size: 282 B

Before After
Before After

View file

@ -1 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" transform="scale(-1 1)" viewBox="0 0 15 15"><path d="M8.293 2.293a1 1 0 0 1 1.414 0l4.5 4.5a1 1 0 0 1 0 1.414l-4.5 4.5a1 1 0 0 1-1.414-1.414L11 8.5H1.5a1 1 0 0 1 0-2H11L8.293 3.707a1 1 0 0 1 0-1.414" /></svg>
<svg
xmlns="http://www.w3.org/2000/svg"
width="15"
height="15"
transform="scale(-1 1)"
viewBox="0 0 15 15"
>
<path d="M8.293 2.293a1 1 0 0 1 1.414 0l4.5 4.5a1 1 0 0 1 0 1.414l-4.5 4.5a1 1 0 0 1-1.414-1.414L11 8.5H1.5a1 1 0 0 1 0-2H11L8.293 3.707a1 1 0 0 1 0-1.414" />
</svg>

Before

Width:  |  Height:  |  Size: 271 B

After

Width:  |  Height:  |  Size: 287 B

Before After
Before After

View file

@ -1,13 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="330.107px" height="330.773px" viewBox="0 0 330.107 330.773" enable-background="new 0 0 330.107 330.773"
xml:space="preserve">
<g id="logo_x2F_colors">
<ellipse fill="#EBFFB8" cx="165.872" cy="162.37" rx="164.236" ry="161.992"/>
<g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M256.14,174.292c0.624,1.266,0.236,5.389,0.142,5.907
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!doctype svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
width="330.107px"
height="330.773px"
viewBox="0 0 330.107 330.773"
enable-background="new 0 0 330.107 330.773"
xml:space="preserve"
>
<g id="logo_x2F_colors">
<ellipse
fill="#EBFFB8"
cx="165.872"
cy="162.37"
rx="164.236"
ry="161.992"
/>
<g>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M256.14,174.292c0.624,1.266,0.236,5.389,0.142,5.907
c-0.165,0.873-0.366,5.486-0.339,6.494c0.03,0.981-0.037,5.803-0.067,6.871c-0.061,2.059-0.419,3.634-0.353,5.689
c0.065,2.075-0.045,4.115-0.176,6.188c-0.064,0.991-0.149,5.077-0.266,6.136c-0.214,1.976-0.326,4.438-0.703,6.396
c-0.18,0.946-0.581,5.088-0.84,6.161c-0.479,1.982-1.034,5.444-1.652,7.539c-0.396,1.344-2.98,6.876-6.584,9.736
@ -23,8 +42,13 @@
c0.283-0.925,0.844-3.277,0.982-4.224c0.158-1.088,0.746-4.319,0.843-5.301c0.136-1.396,0.497-9.892,0.645-10.94
c0.278-2.004,0.508-7.808,0.473-9.878c-0.019-1.023,0.288-3.498,0.264-4.521c-0.025-1.097,0.062-7.451-0.08-9.534
c-0.137-2.058,0.086-4.604-0.083-6.658c-0.052-0.637,0.005-1.417,0.323-2.033c0.3-0.585,0.672-0.698,1.31-0.966
c0.867-0.366,1.639-0.822,2.529-1.164C252.635,175.333,255.338,174.318,256.14,174.292z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M95.368,240.441c-0.003-0.45-0.282-2.143-0.28-2.598
c0.867-0.366,1.639-0.822,2.529-1.164C252.635,175.333,255.338,174.318,256.14,174.292z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M95.368,240.441c-0.003-0.45-0.282-2.143-0.28-2.598
c0.002-0.916-0.063-1.613,0-2.526c0.067-1.018-0.075-2.626,0-3.789c0.028-0.469,0.139-0.42,0.139-1.402
c0-1.013,0.026-3.481,0-4.491c-0.052-2.035,0.133-3.676,0.106-5.721c-0.054-4.137,0.167-8.312-0.134-12.442
c-0.151-2.07-0.123-4.101,0.006-6.17c0.062-0.968,0.126-0.463,0.149-1.431c0.025-1.058-0.081-0.694-1.558-0.598
@ -51,8 +75,13 @@
c0.014,2.109-0.104,4.51-0.25,6.616c-0.144,2.054-0.141,3.588-0.136,5.622c0.003,2.27-0.221,4.759-0.171,7.032
c0.048,2.271,0.13,4.554,0.098,6.824c-0.017,1.136-0.113,2.694-0.163,3.826c-0.017,0.426,0.068,1.238-0.175,1.636
c-0.256,0.411-1.326,0.97-1.795,1.238c-1.447,0.833-2.262,1.34-3.496,1.82c-0.37,0.146-0.939-0.022-1.236-0.319
c-0.147-0.15-0.511-0.832-0.549-1.019C95.301,241.81,95.375,241.513,95.368,240.441z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M133.788,243.492c-0.473-0.146-0.111-10.932-0.105-11.157
c-0.147-0.15-0.511-0.832-0.549-1.019C95.301,241.81,95.375,241.513,95.368,240.441z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M133.788,243.492c-0.473-0.146-0.111-10.932-0.105-11.157
c-0.003,0.12,0.004-3.417-0.024-4.714c-0.031-1.412-0.125-2.748-0.186-4.158c-0.062-1.408-0.096-2.819-0.134-4.229
c-0.037-1.438-0.025-2.886,0.001-4.322c0.059-2.86,0.245-5.72,0.39-8.579c0.145-2.88,0.111-4.506,0.111-7.389
c-0.998,0.313-1.975,0.225-2.996,0.501c-0.503,0.138-3.559,0.098-4.185,0.159c-1.162,0.111-2.771-0.142-3.083,0.349
@ -73,8 +102,13 @@
C136.24,243.656,135.161,243.914,133.788,243.492z M133.932,192.823c-0.111-2.553-0.137-5.758-0.532-8.168
c-0.184-1.136-0.433-3.177-1.091-4.207c-0.205-0.32-0.477-0.714-1.575-0.988c-1.123-0.281-1.547,0.266-1.946,0.372
c-2.615,0.696-2.825,3.775-3.449,5.563c-0.922,2.628-1.214,5.829-1.893,8.21c0.804,0,1.529,0.134,2.324,0.058
c0.932-0.091,1.7,0.077,2.607-0.018C130.454,193.426,132.048,193.397,133.932,192.823z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M208.743,178.101c-0.564,0.717-5.647,6.054-6.142,6.852
c0.932-0.091,1.7,0.077,2.607-0.018C130.454,193.426,132.048,193.397,133.932,192.823z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M208.743,178.101c-0.564,0.717-5.647,6.054-6.142,6.852
c-0.49,0.79-2.506,2.904-2.761,3.294c-0.19,0.286-2.529,3.547-3.214,4.512c-0.35,0.494-1.129,1.836-1.186,2.396
c-0.094,0.941-0.302,1.752,0.275,2.639c0.242,0.374,0.496,0.946,0.694,1.34c0.205,0.406,4.422,9.228,4.639,9.625
c0.259,0.471,5.928,12.979,6.146,13.883c0.233,0.98,2.601,6.334,3.644,8.222c1.016,1.844,2.092,3.97,3.22,5.776
@ -84,8 +118,13 @@
c-1.568-3.705-2.947-5.791-4.01-9.153c-0.127-0.399-0.166-1.336-0.056-1.75c0.105-0.392,0.621-1.737,0.758-2.125
c0.292-0.815,1.361-2.113,1.624-2.447c0.268-0.336,1.851-2.58,2.42-3.308c0.553-0.703,1.856-2.596,2.341-3.325
c0.484-0.729,4.608-5.682,6.583-7.556c0.803-0.762,4.247-4.194,5.252-4.09c1.033,0.107,1.478,2.067,1.667,2.72
C208.606,176.621,209.252,177.455,208.743,178.101z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M183.833,175.865c0.031,0.313,0.395,7.007,0.33,7.995
C208.606,176.621,209.252,177.455,208.743,178.101z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M183.833,175.865c0.031,0.313,0.395,7.007,0.33,7.995
c-0.027,0.414-0.22,3.441-0.132,4.419c0.086,0.953,0.01,5.818-0.057,6.771c-0.023,0.31,0.121,3.432,0.126,3.902
c0.007,1-0.165,3.777-0.207,4.753c-0.046,1.034-0.039,3.636,0,4.104c0.035,0.44,0.098,3.667,0.104,4.209
c0.023,2.042-0.047,4.101,0.031,6.138c0.079,2.019-0.144,4.786-0.241,6.81c-0.105,2.21-0.021,10.085-0.105,11.158
@ -94,8 +133,13 @@
c0.018-0.471,0.194-5.161,0.141-5.894c-0.03-0.395,0.007-4.662,0.007-5.555c-0.001-1.058,0.002-2.117,0.004-3.172
c0.002-1.984-0.249-3.995-0.044-5.974c0.05-0.499-0.107-4.751-0.227-5.766c-0.242-2.041-0.191-4.09-0.295-6.138
c-0.103-2.011-0.047-4.012,0.131-6.013c0.084-0.969,0.18-5.238,0.294-6.25c0.117-1.076,1.048-1.555,1.899-2.098
c1.242-0.794,4.192-2.041,5.014-2.146C183.825,174.873,183.764,175.179,183.833,175.865z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M163.603,202.786c-0.327,1.961-0.003,4.088-0.327,6.051
c1.242-0.794,4.192-2.041,5.014-2.146C183.825,174.873,183.764,175.179,183.833,175.865z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M163.603,202.786c-0.327,1.961-0.003,4.088-0.327,6.051
c-0.153,0.913-0.331,3.709-0.331,4.727c0,1.826-0.416,5.138-0.282,7.158c0.142,2.104-0.01,4.69-0.141,6.735
c-0.132,2.099-0.14,3.929-0.14,6.035c0,1.009,0.076,5.682-0.28,6.666c-0.511,1.408-3.76,2.572-5.318,3.204
c-0.928,0.376-1.852,0.286-2.623-0.283c-0.746-0.547-0.653-1.295-0.536-2.018c0.146-0.922,0.243-2.868,0.477-3.778
@ -103,49 +147,63 @@
c0.053-1.972,0.034-8.552,0.096-10.551c0.059-2.027,0.42-4.048,0.451-6.074c0.033-2.093-0.106-4.188-0.186-6.28
c-0.028-0.744-0.072-1.49-0.067-2.236c0.008-0.719-0.163-1.542-0.03-2.25c0.111-0.6,0.873-0.85,1.476-1.122
c0.88-0.397,1.753-0.805,2.62-1.215c1.111-0.526,2.591-1.208,3.646-0.179c0.527,0.517,0.551,1.356,0.675,1.979
C163.361,195.148,163.769,201.799,163.603,202.786z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M158.061,188.91c-1.36,0.13-3.944,0.762-4.253-0.85
C163.361,195.148,163.769,201.799,163.603,202.786z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M158.061,188.91c-1.36,0.13-3.944,0.762-4.253-0.85
c-0.118-0.616,0.837-1.216,1.345-1.625c0.746-0.603,1.592-1.134,2.547-1.53c0.395-0.161,0.902-0.395,1.357-0.424
c0.467-0.029,0.935,0.163,1.361,0.281c0.545,0.149,1.135,0.223,1.706,0.298c0.448,0.058,1.194-0.014,1.571,0.211
c0.593,0.354-0.886,1.479-1.165,1.734c-0.8,0.729-1.517,1.293-2.582,1.774c-0.035-0.048-0.413,0.074-0.448,0.025
C158.361,188.914,158.097,188.958,158.061,188.91z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M155.311,183.014c-1.12-0.002-0.427-0.802,0.003-1.173
C158.361,188.914,158.097,188.958,158.061,188.91z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M155.311,183.014c-1.12-0.002-0.427-0.802,0.003-1.173
c0.68-0.582,4.113-2.3,5.148-2.56c1.005-0.254,2.154-0.189,3.191-0.109c1.102,0.086,2.107,0.288,1.062,1.136
c-0.776,0.629-1.587,1.238-2.521,1.727c-1.057,0.552-1.993,0.719-3.231,0.859C158.961,182.873,156.52,183.014,155.311,183.014z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M154.77,177.503c0.293-0.291,0.844-0.653,1.253-0.86
c-0.776,0.629-1.587,1.238-2.521,1.727c-1.057,0.552-1.993,0.719-3.231,0.859C158.961,182.873,156.52,183.014,155.311,183.014z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M154.77,177.503c0.293-0.291,0.844-0.653,1.253-0.86
c0.483-0.245,0.571-0.458,1.08-0.672c1.113-0.468,1.478-1.019,2.51-1.581c0.393-0.214,0.591-0.433,1.063-0.536
c0.601-0.134,3.981-0.078,4.499-0.098c0.503-0.022,1.013,0.03,1.516,0.051C164.062,176.816,163.687,177.607,154.77,177.503z"/>
</g>
<g>
<path fill="#202020" d="M75,149.773c15.5,2.5,165.69,0,175.47,0s9.028-6.834,9.028-6.834s1.959-4.05-31.998-5.666
c-33.958-1.617-60.152,2.646-76.576,5.573s-65.882-0.384-71.424-0.601S59.5,147.273,75,149.773z"/>
<path fill="#202020" d="M250.495,123.773c-87.74-1.097-128.746,6.052-159.245,4.25c-20.582-1.216-20.922-7.918-21.211-11.084
c0.601-0.134,3.981-0.078,4.499-0.098c0.503-0.022,1.013,0.03,1.516,0.051C164.062,176.816,163.687,177.607,154.77,177.503z"
/>
</g>
<g>
<path
fill="#202020"
d="M75,149.773c15.5,2.5,165.69,0,175.47,0s9.028-6.834,9.028-6.834s1.959-4.05-31.998-5.666
c-33.958-1.617-60.152,2.646-76.576,5.573s-65.882-0.384-71.424-0.601S59.5,147.273,75,149.773z"
/>
<path
fill="#202020"
d="M250.495,123.773c-87.74-1.097-128.746,6.052-159.245,4.25c-20.582-1.216-20.922-7.918-21.211-11.084
s0-6.406,33.957-8.022c33.958-1.617,54.865,5.762,77.504,6.606c22.638,0.846,63.45,0.664,68.995,0.784
C260.5,116.523,270.5,124.023,250.495,123.773z"/>
<path fill="#202020" d="M80.75,89.329c0,0,121.5-1.806,166.72,1.444c9.754,0.701,8.53,8,8.53,8s-4.541,6.668-33,6.5
c-33.996-0.201-52.361-8.656-75-9.5c-22.638-0.846-67.416,2.225-72.958,2.442S63.612,89.329,80.75,89.329z"/>
</g>
</g>
<g id="home_loading">
</g>
<g id="home_scroll">
</g>
<g id="home_menu">
</g>
<g id="shop_w_x2F_menu">
</g>
<g id="shop_scroll">
</g>
<g id="shop_bottom">
</g>
<g id="prod_small_info">
</g>
<g id="prod_big_info">
</g>
<g id="prod_earrings">
</g>
<g id="prod_bottom">
</g>
<g id="about">
</g>
C260.5,116.523,270.5,124.023,250.495,123.773z"
/>
<path
fill="#202020"
d="M80.75,89.329c0,0,121.5-1.806,166.72,1.444c9.754,0.701,8.53,8,8.53,8s-4.541,6.668-33,6.5
c-33.996-0.201-52.361-8.656-75-9.5c-22.638-0.846-67.416,2.225-72.958,2.442S63.612,89.329,80.75,89.329z"
/>
</g>
</g>
<g id="home_loading" />
<g id="home_scroll" />
<g id="home_menu" />
<g id="shop_w_x2F_menu" />
<g id="shop_scroll" />
<g id="shop_bottom" />
<g id="prod_small_info" />
<g id="prod_big_info" />
<g id="prod_earrings" />
<g id="prod_bottom" />
<g id="about" />
</svg>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

@ -1 +1,9 @@
<svg viewBox="29.047 55.883 209.764 80.943" xmlns="http://www.w3.org/2000/svg"><path d="M38.421 133.462c16.438 3.1 175.723 0 186.094 0 10.372 0 9.575-8.475 9.575-8.475s2.077-5.022-33.935-7.026c-36.015-2.005-63.796 3.282-81.213 6.912-17.419 3.628-69.872-.477-75.749-.747-5.878-.269-21.211 6.234-4.772 9.336m6.099-74.953S173.376 56.27 221.333 60.3c10.344.87 9.046 9.92 9.046 9.92s-4.816 8.269-34.997 8.06c-36.054-.25-55.531-10.734-79.542-11.78-24.007-1.049-71.499 2.759-77.374 3.029-5.878.268-12.123-11.02 6.054-11.02m180.022 42.712c-93.052-1.36-136.54 7.504-168.887 5.27-21.829-1.507-22.188-9.818-22.495-13.744s0-7.943 36.014-9.948c36.013-2.005 58.187 7.146 82.195 8.191 24.01 1.049 67.293.823 73.173.972 10.61.268 21.215 9.568 0 9.259" fill="#2B2B2B"/></svg>
<svg
viewBox="29.047 55.883 209.764 80.943"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M38.421 133.462c16.438 3.1 175.723 0 186.094 0 10.372 0 9.575-8.475 9.575-8.475s2.077-5.022-33.935-7.026c-36.015-2.005-63.796 3.282-81.213 6.912-17.419 3.628-69.872-.477-75.749-.747-5.878-.269-21.211 6.234-4.772 9.336m6.099-74.953S173.376 56.27 221.333 60.3c10.344.87 9.046 9.92 9.046 9.92s-4.816 8.269-34.997 8.06c-36.054-.25-55.531-10.734-79.542-11.78-24.007-1.049-71.499 2.759-77.374 3.029-5.878.268-12.123-11.02 6.054-11.02m180.022 42.712c-93.052-1.36-136.54 7.504-168.887 5.27-21.829-1.507-22.188-9.818-22.495-13.744s0-7.943 36.014-9.948c36.013-2.005 58.187 7.146 82.195 8.191 24.01 1.049 67.293.823 73.173.972 10.61.268 21.215 9.568 0 9.259"
fill="#2B2B2B"
/>
</svg>

Before

Width:  |  Height:  |  Size: 760 B

After

Width:  |  Height:  |  Size: 779 B

Before After
Before After

View file

@ -1,13 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="330.107px" height="330.773px" viewBox="0 0 330.107 330.773" enable-background="new 0 0 330.107 330.773"
xml:space="preserve">
<g id="logo_x2F_colors">
<ellipse display="none" fill="#DEFDB5" cx="165.872" cy="162.37" rx="164.236" ry="161.992"/>
<g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M256.14,137.243c0.624,1.266,0.236,5.389,0.142,5.907
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!doctype svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
width="330.107px"
height="330.773px"
viewBox="0 0 330.107 330.773"
enable-background="new 0 0 330.107 330.773"
xml:space="preserve"
>
<g id="logo_x2F_colors">
<ellipse
display="none"
fill="#DEFDB5"
cx="165.872"
cy="162.37"
rx="164.236"
ry="161.992"
/>
<g>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M256.14,137.243c0.624,1.266,0.236,5.389,0.142,5.907
c-0.165,0.873-0.366,5.486-0.339,6.494c0.03,0.981-0.037,5.803-0.067,6.871c-0.061,2.059-0.419,3.634-0.353,5.689
c0.065,2.075-0.045,4.115-0.176,6.188c-0.064,0.991-0.149,5.077-0.266,6.136c-0.214,1.976-0.326,4.438-0.703,6.396
c-0.18,0.946-0.581,5.088-0.84,6.161c-0.479,1.982-1.034,5.444-1.652,7.539c-0.396,1.344-2.98,6.876-6.584,9.736
@ -23,8 +43,13 @@
c0.283-0.925,0.844-3.277,0.982-4.224c0.158-1.088,0.746-4.319,0.843-5.301c0.136-1.396,0.497-9.892,0.645-10.94
c0.278-2.004,0.508-7.808,0.473-9.878c-0.019-1.023,0.288-3.498,0.264-4.521c-0.025-1.097,0.062-7.451-0.08-9.534
c-0.137-2.058,0.086-4.604-0.083-6.658c-0.052-0.637,0.005-1.417,0.323-2.033c0.3-0.585,0.672-0.698,1.31-0.966
c0.867-0.366,1.639-0.822,2.529-1.164C252.635,138.285,255.338,137.27,256.14,137.243z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M95.368,203.393c-0.003-0.45-0.282-2.143-0.28-2.598
c0.867-0.366,1.639-0.822,2.529-1.164C252.635,138.285,255.338,137.27,256.14,137.243z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M95.368,203.393c-0.003-0.45-0.282-2.143-0.28-2.598
c0.002-0.916-0.063-1.613,0-2.526c0.067-1.018-0.075-2.626,0-3.789c0.028-0.469,0.139-0.42,0.139-1.402
c0-1.013,0.026-3.481,0-4.491c-0.052-2.035,0.133-3.676,0.106-5.721c-0.054-4.137,0.167-8.312-0.134-12.442
c-0.151-2.07-0.123-4.101,0.006-6.17c0.062-0.968,0.126-0.463,0.149-1.431c0.025-1.058-0.081-0.694-1.558-0.598
@ -51,8 +76,13 @@
c0.014,2.109-0.104,4.51-0.25,6.616c-0.144,2.054-0.141,3.588-0.136,5.622c0.003,2.27-0.221,4.759-0.171,7.032
c0.048,2.271,0.13,4.554,0.098,6.824c-0.017,1.136-0.113,2.694-0.163,3.826c-0.017,0.426,0.068,1.238-0.175,1.636
c-0.256,0.411-1.326,0.97-1.795,1.238c-1.447,0.833-2.262,1.34-3.496,1.82c-0.37,0.146-0.939-0.022-1.236-0.319
c-0.147-0.15-0.511-0.832-0.549-1.019C95.301,204.762,95.375,204.465,95.368,203.393z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M133.788,206.443c-0.473-0.146-0.111-10.932-0.105-11.157
c-0.147-0.15-0.511-0.832-0.549-1.019C95.301,204.762,95.375,204.465,95.368,203.393z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M133.788,206.443c-0.473-0.146-0.111-10.932-0.105-11.157
c-0.003,0.12,0.004-3.417-0.024-4.714c-0.031-1.412-0.125-2.748-0.186-4.158c-0.062-1.408-0.096-2.819-0.134-4.229
c-0.037-1.438-0.025-2.886,0.001-4.322c0.059-2.86,0.245-5.72,0.39-8.579c0.145-2.88,0.111-4.506,0.111-7.389
c-0.998,0.313-1.975,0.225-2.996,0.501c-0.503,0.138-3.559,0.098-4.185,0.159c-1.162,0.111-2.771-0.142-3.083,0.349
@ -73,8 +103,13 @@
C136.24,206.607,135.161,206.865,133.788,206.443z M133.932,155.774c-0.111-2.553-0.137-5.758-0.532-8.168
c-0.184-1.136-0.433-3.177-1.091-4.207c-0.205-0.32-0.477-0.714-1.575-0.988c-1.123-0.281-1.547,0.266-1.946,0.372
c-2.615,0.696-2.825,3.775-3.449,5.563c-0.922,2.628-1.214,5.829-1.893,8.21c0.804,0,1.529,0.134,2.324,0.058
c0.932-0.091,1.7,0.077,2.607-0.018C130.454,156.377,132.048,156.349,133.932,155.774z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M208.743,141.052c-0.564,0.717-5.647,6.054-6.142,6.852
c0.932-0.091,1.7,0.077,2.607-0.018C130.454,156.377,132.048,156.349,133.932,155.774z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M208.743,141.052c-0.564,0.717-5.647,6.054-6.142,6.852
c-0.49,0.79-2.506,2.904-2.761,3.294c-0.19,0.286-2.529,3.547-3.214,4.512c-0.35,0.494-1.129,1.836-1.186,2.396
c-0.094,0.941-0.302,1.752,0.275,2.639c0.242,0.374,0.496,0.946,0.694,1.34c0.205,0.406,4.422,9.228,4.639,9.625
c0.259,0.471,5.928,12.979,6.146,13.883c0.233,0.98,2.601,6.334,3.644,8.222c1.016,1.844,2.092,3.97,3.22,5.776
@ -84,8 +119,13 @@
c-1.568-3.705-2.947-5.791-4.01-9.153c-0.127-0.399-0.166-1.336-0.056-1.75c0.105-0.392,0.621-1.737,0.758-2.125
c0.292-0.815,1.361-2.113,1.624-2.447c0.268-0.336,1.851-2.58,2.42-3.308c0.553-0.703,1.856-2.596,2.341-3.325
c0.484-0.729,4.608-5.682,6.583-7.556c0.803-0.762,4.247-4.194,5.252-4.09c1.033,0.107,1.478,2.067,1.667,2.72
C208.606,139.572,209.252,140.406,208.743,141.052z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M183.833,138.816c0.031,0.313,0.395,7.007,0.33,7.995
C208.606,139.572,209.252,140.406,208.743,141.052z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M183.833,138.816c0.031,0.313,0.395,7.007,0.33,7.995
c-0.027,0.414-0.22,3.441-0.132,4.419c0.086,0.953,0.01,5.818-0.057,6.771c-0.023,0.31,0.121,3.432,0.126,3.902
c0.007,1-0.165,3.777-0.207,4.753c-0.046,1.034-0.039,3.636,0,4.104c0.035,0.44,0.098,3.667,0.104,4.209
c0.023,2.042-0.047,4.101,0.031,6.138c0.079,2.019-0.144,4.786-0.241,6.81c-0.105,2.21-0.021,10.085-0.105,11.158
@ -94,8 +134,13 @@
c0.018-0.471,0.194-5.161,0.141-5.894c-0.03-0.395,0.007-4.662,0.007-5.555c-0.001-1.058,0.002-2.117,0.004-3.172
c0.002-1.984-0.249-3.995-0.044-5.974c0.05-0.499-0.107-4.751-0.227-5.766c-0.242-2.041-0.191-4.09-0.295-6.138
c-0.103-2.011-0.047-4.012,0.131-6.013c0.084-0.969,0.18-5.238,0.294-6.25c0.117-1.076,1.048-1.555,1.899-2.098
c1.242-0.794,4.192-2.041,5.014-2.146C183.825,137.825,183.764,138.13,183.833,138.816z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M163.603,165.738c-0.327,1.961-0.003,4.088-0.327,6.051
c1.242-0.794,4.192-2.041,5.014-2.146C183.825,137.825,183.764,138.13,183.833,138.816z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M163.603,165.738c-0.327,1.961-0.003,4.088-0.327,6.051
c-0.153,0.913-0.331,3.709-0.331,4.727c0,1.826-0.416,5.138-0.282,7.158c0.142,2.104-0.01,4.69-0.141,6.735
c-0.132,2.099-0.14,3.929-0.14,6.035c0,1.009,0.076,5.682-0.28,6.666c-0.511,1.408-3.76,2.572-5.318,3.204
c-0.928,0.376-1.852,0.286-2.623-0.283c-0.746-0.547-0.653-1.295-0.536-2.018c0.146-0.922,0.243-2.868,0.477-3.778
@ -103,49 +148,66 @@
c0.053-1.972,0.034-8.552,0.096-10.551c0.059-2.027,0.42-4.048,0.451-6.074c0.033-2.093-0.106-4.188-0.186-6.28
c-0.028-0.744-0.072-1.49-0.067-2.236c0.008-0.719-0.163-1.542-0.03-2.25c0.111-0.6,0.873-0.85,1.476-1.122
c0.88-0.397,1.753-0.805,2.62-1.215c1.111-0.526,2.591-1.208,3.646-0.179c0.527,0.517,0.551,1.356,0.675,1.979
C163.361,158.1,163.769,164.75,163.603,165.738z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M158.061,151.862c-1.36,0.13-3.944,0.762-4.253-0.85
C163.361,158.1,163.769,164.75,163.603,165.738z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M158.061,151.862c-1.36,0.13-3.944,0.762-4.253-0.85
c-0.118-0.616,0.837-1.216,1.345-1.625c0.746-0.603,1.592-1.134,2.547-1.53c0.395-0.161,0.902-0.395,1.357-0.424
c0.467-0.029,0.935,0.163,1.361,0.281c0.545,0.149,1.135,0.223,1.706,0.298c0.448,0.058,1.194-0.014,1.571,0.211
c0.593,0.354-0.886,1.479-1.165,1.734c-0.8,0.729-1.517,1.293-2.582,1.774c-0.035-0.048-0.413,0.074-0.448,0.025
C158.361,151.865,158.097,151.91,158.061,151.862z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M155.311,145.966c-1.12-0.002-0.427-0.802,0.003-1.173
C158.361,151.865,158.097,151.91,158.061,151.862z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M155.311,145.966c-1.12-0.002-0.427-0.802,0.003-1.173
c0.68-0.582,4.113-2.3,5.148-2.56c1.005-0.254,2.154-0.189,3.191-0.109c1.102,0.086,2.107,0.288,1.062,1.136
c-0.776,0.629-1.587,1.238-2.521,1.727c-1.057,0.552-1.993,0.719-3.231,0.859C158.961,145.825,156.52,145.966,155.311,145.966z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#202020" d="M154.77,140.455c0.293-0.291,0.844-0.653,1.253-0.86
c-0.776,0.629-1.587,1.238-2.521,1.727c-1.057,0.552-1.993,0.719-3.231,0.859C158.961,145.825,156.52,145.966,155.311,145.966z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#202020"
d="M154.77,140.455c0.293-0.291,0.844-0.653,1.253-0.86
c0.483-0.245,0.571-0.458,1.08-0.672c1.113-0.468,1.478-1.019,2.51-1.581c0.393-0.214,0.591-0.433,1.063-0.536
c0.601-0.134,3.981-0.078,4.499-0.098c0.503-0.022,1.013,0.03,1.516,0.051C164.062,139.768,163.687,140.559,154.77,140.455z"/>
</g>
<g display="none">
<path display="inline" fill="#202020" d="M75,149.773c15.5,2.5,165.69,0,175.47,0s9.028-6.834,9.028-6.834
s1.959-4.05-31.998-5.666c-33.958-1.617-60.152,2.646-76.576,5.573s-65.882-0.384-71.424-0.601S59.5,147.273,75,149.773z"/>
<path display="inline" fill="#202020" d="M250.495,123.773c-87.74-1.097-128.746,6.052-159.245,4.25
c0.601-0.134,3.981-0.078,4.499-0.098c0.503-0.022,1.013,0.03,1.516,0.051C164.062,139.768,163.687,140.559,154.77,140.455z"
/>
</g>
<g display="none">
<path
display="inline"
fill="#202020"
d="M75,149.773c15.5,2.5,165.69,0,175.47,0s9.028-6.834,9.028-6.834
s1.959-4.05-31.998-5.666c-33.958-1.617-60.152,2.646-76.576,5.573s-65.882-0.384-71.424-0.601S59.5,147.273,75,149.773z"
/>
<path
display="inline"
fill="#202020"
d="M250.495,123.773c-87.74-1.097-128.746,6.052-159.245,4.25
c-20.582-1.216-20.922-7.918-21.211-11.084s0-6.406,33.957-8.022c33.958-1.617,54.865,5.762,77.504,6.606
c22.638,0.846,63.45,0.664,68.995,0.784C260.5,116.523,270.5,124.023,250.495,123.773z"/>
<path display="inline" fill="#202020" d="M80.75,89.329c0,0,121.5-1.806,166.72,1.444c9.754,0.701,8.53,8,8.53,8
s-4.541,6.668-33,6.5c-33.996-0.201-52.361-8.656-75-9.5c-22.638-0.846-67.416,2.225-72.958,2.442S63.612,89.329,80.75,89.329z"/>
</g>
</g>
<g id="home_loading">
</g>
<g id="home_scroll">
</g>
<g id="home_menu">
</g>
<g id="shop_w_x2F_menu">
</g>
<g id="shop_scroll">
</g>
<g id="shop_bottom">
</g>
<g id="prod_small_info">
</g>
<g id="prod_big_info">
</g>
<g id="prod_earrings">
</g>
<g id="prod_bottom">
</g>
<g id="about">
</g>
c22.638,0.846,63.45,0.664,68.995,0.784C260.5,116.523,270.5,124.023,250.495,123.773z"
/>
<path
display="inline"
fill="#202020"
d="M80.75,89.329c0,0,121.5-1.806,166.72,1.444c9.754,0.701,8.53,8,8.53,8
s-4.541,6.668-33,6.5c-33.996-0.201-52.361-8.656-75-9.5c-22.638-0.846-67.416,2.225-72.958,2.442S63.612,89.329,80.75,89.329z"
/>
</g>
</g>
<g id="home_loading" />
<g id="home_scroll" />
<g id="home_menu" />
<g id="shop_w_x2F_menu" />
<g id="shop_scroll" />
<g id="shop_bottom" />
<g id="prod_small_info" />
<g id="prod_big_info" />
<g id="prod_earrings" />
<g id="prod_bottom" />
<g id="about" />
</svg>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

@ -4,6 +4,6 @@
viewBox="0 0 307.49 77.116"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
><path
d="M32.444 37.183c-20.81 0-21.059 17.971-21.059 36.43 0 1.02-.949 2.25-2.183 2.25h-7.02C.949 75.863 0 74.884 0 73.613V2.52C0 1.249.948.271 2.182.271h7.59c1.526 0 2.181.767 2.181 1.858 0 8.244 2.358 26.106 20.49 26.106 18.816 0 20.491-16.657 20.491-26.106 0-1.092 1.043-1.858 2.182-1.858h7.59c1.232 0 2.181.978 2.181 2.249v71.093c0 1.271-.948 2.25-2.181 2.25h-7.021c-1.233 0-2.182-1.261-2.182-2.25.002-16.652.434-36.43-21.059-36.43M71.91 74.247c-.854-34.243 16.317-55.889 32.159-66.01 7.114-4.524 15.652-7.646 31.115-7.861 1.518 0 2.276 1.184 2.276 3.015v55.565c0 9.692-8.063 15.387-15.842 13.771-12.522-2.585-18.594-17.647-26.183-25.832-2.656-2.799-6.355-2.691-8.917.754-3.51 4.738-3.226 9.8-3.226 25.844 0 2.047-.189 2.263-1.992 2.37h-7.874c-.947 0-1.516-.431-1.516-1.616m55.116-22.506-.285-29.721c0-4.2-2.276-6.999-5.977-6.892-4.269.107-10.909 3.337-14.419 6.568-5.027 4.522-5.881 7.107-4.079 12.599 1.423 4.2 9.961 18.199 16.222 22.291 4.269 2.908 8.538.647 8.538-4.845m23.441 21.312V2.703c0-2.162.569-2.703 2.088-2.703h9.651c1.803 0 1.96.541 1.96 2.703l.095 70.35c0 2.053-.949 2.81-2.467 2.81h-8.955c-1.518 0-2.372-.649-2.372-2.81m26.796.878V2.459c0-1.395 1.183-1.717 2.131-1.717h8.539c1.138 0 2.226.322 2.226 1.717v24.716c0 1.54 1.606 1.54 1.606 1.54 3.875 0 11.305.032 11.305.032 18.014 0 19.026-16.768 19.026-25.858 0-1.621.569-2.146 1.993-2.146L233.09.64c1.233 0 2.092.841 2.092 2.249 0 15.577-1.188 29.832-16.069 29.832 17.291 0 16.543 20.726 16.543 41.102 0 1.186-.38 2.04-1.708 2.04h-9.29c-1.707 0-1.896-.858-1.896-2.254 0-21.024-1.217-35.922-20.182-35.922h-10.903c-1.138 0-1.518.429-1.518 1.824v34.42c0 1.181-1.088 1.932-2.226 1.932h-8.539c-.948 0-2.131-.751-2.131-1.932m114.835-31.974V3.248c0-1.847.398-2.607 2.093-2.607h11.205c1.895 0 2.094.761 2.094 2.607v41.275c0 16.075-13.059 33.021-30.801 32.585-17.741-.434-30.799-16.51-30.799-32.585V3.248c0-1.847.199-2.607 2.093-2.607h11.205c1.694 0 2.093.761 2.093 2.607v38.709c0 11.403 2.433 23.85 15.408 23.85 13.431-.001 15.409-12.447 15.409-23.85"
/></svg>
>
<path d="M32.444 37.183c-20.81 0-21.059 17.971-21.059 36.43 0 1.02-.949 2.25-2.183 2.25h-7.02C.949 75.863 0 74.884 0 73.613V2.52C0 1.249.948.271 2.182.271h7.59c1.526 0 2.181.767 2.181 1.858 0 8.244 2.358 26.106 20.49 26.106 18.816 0 20.491-16.657 20.491-26.106 0-1.092 1.043-1.858 2.182-1.858h7.59c1.232 0 2.181.978 2.181 2.249v71.093c0 1.271-.948 2.25-2.181 2.25h-7.021c-1.233 0-2.182-1.261-2.182-2.25.002-16.652.434-36.43-21.059-36.43M71.91 74.247c-.854-34.243 16.317-55.889 32.159-66.01 7.114-4.524 15.652-7.646 31.115-7.861 1.518 0 2.276 1.184 2.276 3.015v55.565c0 9.692-8.063 15.387-15.842 13.771-12.522-2.585-18.594-17.647-26.183-25.832-2.656-2.799-6.355-2.691-8.917.754-3.51 4.738-3.226 9.8-3.226 25.844 0 2.047-.189 2.263-1.992 2.37h-7.874c-.947 0-1.516-.431-1.516-1.616m55.116-22.506-.285-29.721c0-4.2-2.276-6.999-5.977-6.892-4.269.107-10.909 3.337-14.419 6.568-5.027 4.522-5.881 7.107-4.079 12.599 1.423 4.2 9.961 18.199 16.222 22.291 4.269 2.908 8.538.647 8.538-4.845m23.441 21.312V2.703c0-2.162.569-2.703 2.088-2.703h9.651c1.803 0 1.96.541 1.96 2.703l.095 70.35c0 2.053-.949 2.81-2.467 2.81h-8.955c-1.518 0-2.372-.649-2.372-2.81m26.796.878V2.459c0-1.395 1.183-1.717 2.131-1.717h8.539c1.138 0 2.226.322 2.226 1.717v24.716c0 1.54 1.606 1.54 1.606 1.54 3.875 0 11.305.032 11.305.032 18.014 0 19.026-16.768 19.026-25.858 0-1.621.569-2.146 1.993-2.146L233.09.64c1.233 0 2.092.841 2.092 2.249 0 15.577-1.188 29.832-16.069 29.832 17.291 0 16.543 20.726 16.543 41.102 0 1.186-.38 2.04-1.708 2.04h-9.29c-1.707 0-1.896-.858-1.896-2.254 0-21.024-1.217-35.922-20.182-35.922h-10.903c-1.138 0-1.518.429-1.518 1.824v34.42c0 1.181-1.088 1.932-2.226 1.932h-8.539c-.948 0-2.131-.751-2.131-1.932m114.835-31.974V3.248c0-1.847.398-2.607 2.093-2.607h11.205c1.895 0 2.094.761 2.094 2.607v41.275c0 16.075-13.059 33.021-30.801 32.585-17.741-.434-30.799-16.51-30.799-32.585V3.248c0-1.847.199-2.607 2.093-2.607h11.205c1.694 0 2.093.761 2.093 2.607v38.709c0 11.403 2.433 23.85 15.408 23.85 13.431-.001 15.409-12.447 15.409-23.85" />
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Before After
Before After

View file

@ -1 +1,24 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="329.449 122.475 21.745 29"><path fill="#fff" d="M349.05 131.283c.28-2.099 0-3.499-1.124-4.898-1.217-1.4-3.37-2-6.085-2h-7.957c-.562 0-1.03.4-1.124 1l-3.276 22.192c-.094.499.187.899.655.899h4.962l-.375 2.299c-.093.3.281.7.562.7h4.213c.468 0 .842-.4.936-.899l.093-.2.749-5.198.094-.3c.094-.6.468-.9.936-.9h.655c4.026 0 7.115-1.799 8.052-6.698.374-2.099.187-3.898-.843-5.098-.374-.299-.749-.699-1.123-.899" opacity=".7"/><path fill="#fff" d="M349.05 131.283c.28-2.099 0-3.499-1.124-4.898-1.217-1.4-3.37-2-6.085-2h-7.957c-.562 0-1.03.4-1.124 1l-3.276 22.192c-.094.499.187.899.655.899h4.962l1.217-8.297-.094.3c.187-.599.562-.999 1.217-.999h2.34c4.588 0 8.145-2 9.175-7.697 0-.2 0-.4.094-.5" opacity=".7"/><path fill="#fff" d="M337.628 131.283c0-.3.188-.6.562-.8.094 0 .281-.1.374-.1h6.273c.749 0 1.404.1 2.059.2.188 0 .281 0 .562.1.094.1.281.1.468.2.094 0 .094 0 .281.1l.843.3c.28-2.099 0-3.499-1.124-4.798-1.217-1.4-3.37-2.1-6.085-2.1h-7.957c-.562 0-1.03.5-1.124 1l-3.276 22.192c-.094.499.187.899.655.899h4.962l1.217-8.297z"/><path fill="#231f20" d="M349.01 131.261c.448.263.846.579 1.145.947.498.579.796 1.316.946 2.157.149-1.683-.1-3.051-.946-4.103-.299-.369-.647-.632-1.045-.895 0 .579 0 1.21-.1 1.894m-19.362 14.995 3.136-20.835c.05-.578.548-.999 1.095-.999h7.964c2.737 0 4.878.631 6.072 2.052.598.736.946 1.578 1.095 2.525.199-1.894-.099-3.209-1.095-4.419-1.194-1.474-3.335-2.105-6.072-2.105h-7.964c-.547 0-1.045.421-1.145 1l-3.285 22.202c0 .21.05.421.199.579m5.127 2.209-.05.316c-.05.211.05.421.199.579l.15-.895z" opacity=".2"/></svg>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="329.449 122.475 21.745 29"
>
<path
fill="#fff"
d="M349.05 131.283c.28-2.099 0-3.499-1.124-4.898-1.217-1.4-3.37-2-6.085-2h-7.957c-.562 0-1.03.4-1.124 1l-3.276 22.192c-.094.499.187.899.655.899h4.962l-.375 2.299c-.093.3.281.7.562.7h4.213c.468 0 .842-.4.936-.899l.093-.2.749-5.198.094-.3c.094-.6.468-.9.936-.9h.655c4.026 0 7.115-1.799 8.052-6.698.374-2.099.187-3.898-.843-5.098-.374-.299-.749-.699-1.123-.899"
opacity=".7"
/>
<path
fill="#fff"
d="M349.05 131.283c.28-2.099 0-3.499-1.124-4.898-1.217-1.4-3.37-2-6.085-2h-7.957c-.562 0-1.03.4-1.124 1l-3.276 22.192c-.094.499.187.899.655.899h4.962l1.217-8.297-.094.3c.187-.599.562-.999 1.217-.999h2.34c4.588 0 8.145-2 9.175-7.697 0-.2 0-.4.094-.5"
opacity=".7"
/>
<path
fill="#fff"
d="M337.628 131.283c0-.3.188-.6.562-.8.094 0 .281-.1.374-.1h6.273c.749 0 1.404.1 2.059.2.188 0 .281 0 .562.1.094.1.281.1.468.2.094 0 .094 0 .281.1l.843.3c.28-2.099 0-3.499-1.124-4.798-1.217-1.4-3.37-2.1-6.085-2.1h-7.957c-.562 0-1.03.5-1.124 1l-3.276 22.192c-.094.499.187.899.655.899h4.962l1.217-8.297z"
/>
<path
fill="#231f20"
d="M349.01 131.261c.448.263.846.579 1.145.947.498.579.796 1.316.946 2.157.149-1.683-.1-3.051-.946-4.103-.299-.369-.647-.632-1.045-.895 0 .579 0 1.21-.1 1.894m-19.362 14.995 3.136-20.835c.05-.578.548-.999 1.095-.999h7.964c2.737 0 4.878.631 6.072 2.052.598.736.946 1.578 1.095 2.525.199-1.894-.099-3.209-1.095-4.419-1.194-1.474-3.335-2.105-6.072-2.105h-7.964c-.547 0-1.045.421-1.145 1l-3.285 22.202c0 .21.05.421.199.579m5.127 2.209-.05.316c-.05.211.05.421.199.579l.15-.895z"
opacity=".2"
/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Before After
Before After

View file

@ -1 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="201.754 136.33 100.039 26.6"><path fill="#fff" d="M213.773 136.33h-7.8c-.5 0-1 .4-1.1.9l-3.1 20c-.1.4.2.7.6.7h3.7c.5 0 1-.4 1.1-.9l.8-5.4c.1-.5.5-.9 1.1-.9h2.5c5.1 0 8.1-2.5 8.9-7.4.3-2.1 0-3.8-1-5-1.1-1.3-3.1-2-5.7-2m.9 7.3c-.4 2.8-2.6 2.8-4.6 2.8h-1.2l.8-5.2c0-.3.3-.5.6-.5h.5c1.4 0 2.7 0 3.4.8.5.4.7 1.1.5 2.1m22.3-.1h-3.7c-.3 0-.6.2-.6.5l-.2 1-.3-.4c-.8-1.2-2.6-1.6-4.4-1.6-4.1 0-7.6 3.1-8.3 7.5-.4 2.2.1 4.3 1.4 5.7 1.1 1.3 2.8 1.9 4.7 1.9 3.3 0 5.2-2.1 5.2-2.1l-.2 1c-.1.4.2.8.6.8h3.4c.5 0 1-.4 1.1-.9l2-12.8c.1-.2-.3-.6-.7-.6m-5.1 7.2c-.4 2.1-2 3.6-4.2 3.6-1.1 0-1.9-.3-2.5-1s-.8-1.6-.6-2.6c.3-2.1 2.1-3.6 4.2-3.6 1.1 0 1.9.4 2.5 1 .5.7.7 1.6.6 2.6m25-7.2h-3.7c-.4 0-.7.2-.9.5l-5.2 7.6-2.2-7.3c-.1-.5-.6-.8-1-.8h-3.7c-.4 0-.8.4-.6.9l4.1 12.1-3.9 5.4c-.3.4 0 1 .5 1h3.7c.4 0 .7-.2.9-.5l12.5-18c.3-.3 0-.9-.5-.9m12.4-7.2h-7.8c-.5 0-1 .4-1.1.9l-3.1 19.9c-.1.4.2.7.6.7h4c.4 0 .7-.3.7-.6l.9-5.7c.1-.5.5-.9 1.1-.9h2.5c5.1 0 8.1-2.5 8.9-7.4.3-2.1 0-3.8-1-5-1.2-1.2-3.1-1.9-5.7-1.9m.9 7.3c-.4 2.8-2.6 2.8-4.6 2.8h-1.2l.8-5.2c0-.3.3-.5.6-.5h.5c1.4 0 2.7 0 3.4.8.5.4.6 1.1.5 2.1m22.3-.1h-3.7c-.3 0-.6.2-.6.5l-.2 1-.3-.4c-.8-1.2-2.6-1.6-4.4-1.6-4.1 0-7.6 3.1-8.3 7.5-.4 2.2.1 4.3 1.4 5.7 1.1 1.3 2.8 1.9 4.7 1.9 3.3 0 5.2-2.1 5.2-2.1l-.2 1c-.1.4.2.8.6.8h3.4c.5 0 1-.4 1.1-.9l2-12.8c0-.2-.3-.6-.7-.6m-5.2 7.2c-.4 2.1-2 3.6-4.2 3.6-1.1 0-1.9-.3-2.5-1s-.8-1.6-.6-2.6c.3-2.1 2.1-3.6 4.2-3.6 1.1 0 1.9.4 2.5 1 .6.7.8 1.6.6 2.6m9.6-13.9-3.2 20.3c-.1.4.2.7.6.7h3.2c.5 0 1-.4 1.1-.9l3.2-19.9c.1-.4-.2-.7-.6-.7h-3.6c-.4 0-.6.2-.7.5"/></svg>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="201.754 136.33 100.039 26.6"
>
<path
fill="#fff"
d="M213.773 136.33h-7.8c-.5 0-1 .4-1.1.9l-3.1 20c-.1.4.2.7.6.7h3.7c.5 0 1-.4 1.1-.9l.8-5.4c.1-.5.5-.9 1.1-.9h2.5c5.1 0 8.1-2.5 8.9-7.4.3-2.1 0-3.8-1-5-1.1-1.3-3.1-2-5.7-2m.9 7.3c-.4 2.8-2.6 2.8-4.6 2.8h-1.2l.8-5.2c0-.3.3-.5.6-.5h.5c1.4 0 2.7 0 3.4.8.5.4.7 1.1.5 2.1m22.3-.1h-3.7c-.3 0-.6.2-.6.5l-.2 1-.3-.4c-.8-1.2-2.6-1.6-4.4-1.6-4.1 0-7.6 3.1-8.3 7.5-.4 2.2.1 4.3 1.4 5.7 1.1 1.3 2.8 1.9 4.7 1.9 3.3 0 5.2-2.1 5.2-2.1l-.2 1c-.1.4.2.8.6.8h3.4c.5 0 1-.4 1.1-.9l2-12.8c.1-.2-.3-.6-.7-.6m-5.1 7.2c-.4 2.1-2 3.6-4.2 3.6-1.1 0-1.9-.3-2.5-1s-.8-1.6-.6-2.6c.3-2.1 2.1-3.6 4.2-3.6 1.1 0 1.9.4 2.5 1 .5.7.7 1.6.6 2.6m25-7.2h-3.7c-.4 0-.7.2-.9.5l-5.2 7.6-2.2-7.3c-.1-.5-.6-.8-1-.8h-3.7c-.4 0-.8.4-.6.9l4.1 12.1-3.9 5.4c-.3.4 0 1 .5 1h3.7c.4 0 .7-.2.9-.5l12.5-18c.3-.3 0-.9-.5-.9m12.4-7.2h-7.8c-.5 0-1 .4-1.1.9l-3.1 19.9c-.1.4.2.7.6.7h4c.4 0 .7-.3.7-.6l.9-5.7c.1-.5.5-.9 1.1-.9h2.5c5.1 0 8.1-2.5 8.9-7.4.3-2.1 0-3.8-1-5-1.2-1.2-3.1-1.9-5.7-1.9m.9 7.3c-.4 2.8-2.6 2.8-4.6 2.8h-1.2l.8-5.2c0-.3.3-.5.6-.5h.5c1.4 0 2.7 0 3.4.8.5.4.6 1.1.5 2.1m22.3-.1h-3.7c-.3 0-.6.2-.6.5l-.2 1-.3-.4c-.8-1.2-2.6-1.6-4.4-1.6-4.1 0-7.6 3.1-8.3 7.5-.4 2.2.1 4.3 1.4 5.7 1.1 1.3 2.8 1.9 4.7 1.9 3.3 0 5.2-2.1 5.2-2.1l-.2 1c-.1.4.2.8.6.8h3.4c.5 0 1-.4 1.1-.9l2-12.8c0-.2-.3-.6-.7-.6m-5.2 7.2c-.4 2.1-2 3.6-4.2 3.6-1.1 0-1.9-.3-2.5-1s-.8-1.6-.6-2.6c.3-2.1 2.1-3.6 4.2-3.6 1.1 0 1.9.4 2.5 1 .6.7.8 1.6.6 2.6m9.6-13.9-3.2 20.3c-.1.4.2.7.6.7h3.2c.5 0 1-.4 1.1-.9l3.2-19.9c.1-.4-.2-.7-.6-.7h-3.6c-.4 0-.6.2-.7.5"
/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Before After
Before After

View file

@ -1,20 +1,20 @@
{
"background_color": "#FFF",
"display": "standalone",
"icons": [
{
"sizes": "192x192",
"src": "img/android-chrome-192x192.png",
"type": "image/png"
},
{
"sizes": "512x512",
"src": "img/android-chrome-512x512.png",
"type": "image/png"
}
],
"name": "Haiku Atelier",
"short_name": "Haiku Atelier",
"theme_color": "#E7FFB4",
"start_url": "https://haikuatelier.fr.ddev.site"
}
"background_color": "#FFF",
"display": "standalone",
"icons": [
{
"sizes": "192x192",
"src": "img/android-chrome-192x192.png",
"type": "image/png"
},
{
"sizes": "512x512",
"src": "img/android-chrome-512x512.png",
"type": "image/png"
}
],
"name": "Haiku Atelier",
"short_name": "Haiku Atelier",
"theme_color": "#E7FFB4",
"start_url": "https://haikuatelier.fr.ddev.site"
}

View file

@ -1,4 +1,4 @@
jQuery(document).ready(function($) {
jQuery(document).ready(function ($) {
"use strict";
/**
@ -9,7 +9,7 @@ jQuery(document).ready(function($) {
* @link https://github.com/maddisondesigns
*/
$(".customize-control-tinymce-editor").each(function() {
$(".customize-control-tinymce-editor").each(function () {
// Get the toolbar strings that were passed from the PHP Class
var tinyMCEToolbar1String = _wpCustomizeSettings.controls[$(this).attr("id")].skyrockettinymcetoolbar1;
var tinyMCEToolbar2String = _wpCustomizeSettings.controls[$(this).attr("id")].skyrockettinymcetoolbar2;
@ -25,8 +25,8 @@ jQuery(document).ready(function($) {
mediaButtons: tinyMCEMediaButtons,
});
});
$(document).on("tinymce-editor-init", function(event, editor) {
editor.on("change", function(e) {
$(document).on("tinymce-editor-init", function (event, editor) {
editor.on("change", function (e) {
tinyMCE.triggerSave();
$("#" + editor.id).trigger("change");
});

View file

@ -1,36 +1,32 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
/**
* Le modèle de la Page d'Accueil.
*/
use HaikuAtelier\WP\Resource;
use Timber\Timber;
// Contexte et modèles
$contexte = Timber::context();
$modeles = ['accueil.twig'];
$context = Timber::context();
$templates = ['accueil.twig'];
// Charge les scripts et styles de la page
function charge_scripts_styles_page_accueil(): void {
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-accueil',
src: get_template_directory_uri() . '/assets/css/pages/page-accueil.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-accueil.css'),
media: 'all',
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-scripts-page-accueil',
src: get_template_directory_uri() . '/assets/js/scripts-page-accueil.js',
deps: [],
version: filemtime(get_template_directory() . '/assets/js/scripts-page-accueil.js'),
);
Resource::enqueue_style_file(
handle: 'haiku-atelier-2024-styles-page-accueil',
path: '/assets/css/pages/page-accueil.css'
);
Resource::enqueue_script_module_file(
id: 'haiku-atelier-2024-scripts-page-accueil',
path: '/assets/js/scripts-page-accueil.js'
);
}
add_action('wp_enqueue_scripts', 'charge_scripts_styles_page_accueil');
// Rendu
Timber::render(
filenames: $modeles,
data: $contexte,
data: $context,
filenames: $templates
);

View file

@ -6,8 +6,6 @@ use Carbon_Fields\Carbon_Fields;
use HaikuAtelier\StarterSite;
use Timber\Timber;
use function wp_enqueue_script_module;
// Récupère les dépendances Composer
require_once __DIR__ . '../../../../../vendor/autoload.php';
require_once __DIR__ . '/src/StarterSite.php';
@ -25,43 +23,43 @@ Timber::$dirname = ['views'];
// Charge les Scripts du thème (report d'erreurs)
function load_scripts(): void {
// wp_enqueue_script_module(
// id: 'haiku-atelier-2024-gaffe',
// deps: [],
// src: get_template_directory_uri() . '/assets/js/gaffe.js',
// version: filemtime(get_template_directory() . '/assets/js/gaffe.js'),
// );
wp_enqueue_script_module(
id: 'haiku-atelier-2024-bouton-panier',
deps: [],
src: get_template_directory_uri() . '/assets/js/scripts-bouton-panier.js',
version: filemtime(get_template_directory() . '/assets/js/scripts-bouton-panier.js'),
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-menu-mobile',
deps: [],
src: get_template_directory_uri() . '/assets/js/scripts-menu-mobile.js',
version: filemtime(get_template_directory() . '/assets/js/scripts-menu-mobile.js'),
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-bouton-retour-sommet',
deps: [],
src: get_template_directory_uri() . '/assets/js/scripts-bouton-retour-sommet.js',
version: filemtime(get_template_directory() . '/assets/js/scripts-bouton-retour-sommet.js'),
);
// wp_enqueue_script_module(
// id: 'haiku-atelier-2024-gaffe',
// deps: [],
// src: get_template_directory_uri() . '/assets/js/gaffe.js',
// version: filemtime(get_template_directory() . '/assets/js/gaffe.js'),
// );
wp_enqueue_script_module(
id: 'haiku-atelier-2024-bouton-panier',
deps: [],
src: get_template_directory_uri() . '/assets/js/scripts-bouton-panier.js',
version: filemtime(get_template_directory() . '/assets/js/scripts-bouton-panier.js')
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-menu-mobile',
deps: [],
src: get_template_directory_uri() . '/assets/js/scripts-menu-mobile.js',
version: filemtime(get_template_directory() . '/assets/js/scripts-menu-mobile.js')
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-bouton-retour-sommet',
deps: [],
src: get_template_directory_uri() . '/assets/js/scripts-bouton-retour-sommet.js',
version: filemtime(get_template_directory() . '/assets/js/scripts-bouton-retour-sommet.js')
);
}
add_action('wp_enqueue_scripts', 'load_scripts');
// Charge les styles du thème
function charge_styles_haiku_atelier_2024(): void {
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles',
src: get_template_directory_uri() . '/assets/css/main.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/main.css'),
media: 'all',
);
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles',
src: get_template_directory_uri() . '/assets/css/main.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/main.css'),
media: 'all'
);
}
add_action('wp_enqueue_scripts', 'charge_styles_haiku_atelier_2024');
@ -73,92 +71,92 @@ new StarterSite();
* Personnalisation du thème.
*/
function enregistre_personnalisations_theme(mixed $wp_customize): void {
// Section « Réseaux sociaux »
$wp_customize->add_section('liens_reseaux_sociaux', [
'title' => __('Liens des réseaux sociaux'),
'description' => __("Liens des réseaux sociaux s'affichant dans le pied de page."),
]);
// Section « Réseaux sociaux »
$wp_customize->add_section('liens_reseaux_sociaux', [
'title' => __('Liens des réseaux sociaux'),
'description' => __("Liens des réseaux sociaux s'affichant dans le pied de page.")
]);
// Instagram
$wp_customize->add_setting('lien_instagram', ['type' => 'theme_mod', 'capability' => 'edit_theme_options']);
$wp_customize->add_control('lien_instagram', [
'type' => 'url',
'section' => 'liens_reseaux_sociaux',
'label' => __('Profil Instagram'),
]);
// Instagram
$wp_customize->add_setting('lien_instagram', ['type' => 'theme_mod', 'capability' => 'edit_theme_options']);
$wp_customize->add_control('lien_instagram', [
'type' => 'url',
'section' => 'liens_reseaux_sociaux',
'label' => __('Profil Instagram')
]);
// Facebook
$wp_customize->add_setting('lien_facebook', ['type' => 'theme_mod', 'capability' => 'edit_theme_options']);
$wp_customize->add_control('lien_facebook', [
'type' => 'url',
'section' => 'liens_reseaux_sociaux',
'label' => __('Profil Facebook'),
]);
// Facebook
$wp_customize->add_setting('lien_facebook', ['type' => 'theme_mod', 'capability' => 'edit_theme_options']);
$wp_customize->add_control('lien_facebook', [
'type' => 'url',
'section' => 'liens_reseaux_sociaux',
'label' => __('Profil Facebook')
]);
// Pinterest
$wp_customize->add_setting('lien_pinterest', ['type' => 'theme_mod', 'capability' => 'edit_theme_options']);
$wp_customize->add_control('lien_pinterest', [
'type' => 'url',
'section' => 'liens_reseaux_sociaux',
'label' => __('Profil Pinterest'),
]);
// Pinterest
$wp_customize->add_setting('lien_pinterest', ['type' => 'theme_mod', 'capability' => 'edit_theme_options']);
$wp_customize->add_control('lien_pinterest', [
'type' => 'url',
'section' => 'liens_reseaux_sociaux',
'label' => __('Profil Pinterest')
]);
// Section « Descriptions Produits »
$wp_customize->add_section('descriptions_produits', [
'title' => __('Textes des descriptions Produits'),
'description' => __('Textes des descriptions apparaissant sur les pages Produit.'),
]);
// Section « Descriptions Produits »
$wp_customize->add_section('descriptions_produits', [
'title' => __('Textes des descriptions Produits'),
'description' => __('Textes des descriptions apparaissant sur les pages Produit.')
]);
$wp_customize->add_setting('texte_conditions_livraison', [
'capability' => 'edit_theme_options',
'default' => '',
'sanitize_callback' => 'wp_kses_post',
'transport' => 'postMessage',
'type' => 'theme_mod',
]);
$wp_customize->add_control(new Controle_Personnalise_TinyMCE($wp_customize, 'texte_conditions_livraison', [
'label' => __('Conditions de livraison'),
'description' => __('Descriptif des conditions de livraison.'),
'section' => 'descriptions_produits',
'input_attrs' => [
'toolbar1' => 'bold italic bullist numlist alignleft aligncenter alignright link',
'mediaButtons' => true,
],
]));
$wp_customize->add_setting('texte_conditions_livraison', [
'capability' => 'edit_theme_options',
'default' => '',
'sanitize_callback' => 'wp_kses_post',
'transport' => 'postMessage',
'type' => 'theme_mod'
]);
$wp_customize->add_control(new Controle_Personnalise_TinyMCE($wp_customize, 'texte_conditions_livraison', [
'label' => __('Conditions de livraison'),
'description' => __('Descriptif des conditions de livraison.'),
'section' => 'descriptions_produits',
'input_attrs' => [
'toolbar1' => 'bold italic bullist numlist alignleft aligncenter alignright link',
'mediaButtons' => true
]
]));
$wp_customize->add_setting('texte_entretien_produit', [
'capability' => 'edit_theme_options',
'default' => '',
'sanitize_callback' => 'wp_kses_post',
'transport' => 'postMessage',
'type' => 'theme_mod',
]);
$wp_customize->add_control(new Controle_Personnalise_TinyMCE($wp_customize, 'texte_entretien_produit', [
'label' => __('Entretien du Produit'),
'description' => __("Descriptif des bonnes pratiques pour l'entretien du Produit."),
'section' => 'descriptions_produits',
'input_attrs' => [
'toolbar1' => 'bold italic bullist numlist alignleft aligncenter alignright link',
'mediaButtons' => true,
],
]));
$wp_customize->add_setting('texte_entretien_produit', [
'capability' => 'edit_theme_options',
'default' => '',
'sanitize_callback' => 'wp_kses_post',
'transport' => 'postMessage',
'type' => 'theme_mod'
]);
$wp_customize->add_control(new Controle_Personnalise_TinyMCE($wp_customize, 'texte_entretien_produit', [
'label' => __('Entretien du Produit'),
'description' => __("Descriptif des bonnes pratiques pour l'entretien du Produit."),
'section' => 'descriptions_produits',
'input_attrs' => [
'toolbar1' => 'bold italic bullist numlist alignleft aligncenter alignright link',
'mediaButtons' => true
]
]));
}
add_action('customize_register', 'enregistre_personnalisations_theme');
function retire_tailles_image_par_defaut(mixed $sizes): mixed {
/** @var list<string> */
$targets = ['full', 'thumbnail'];
/** @var list<string> */
$targets = ['full', 'thumbnail'];
foreach ($sizes as $size_index => $size) {
if (in_array($size, $targets, true)) {
continue;
}
unset($sizes[$size_index]);
foreach ($sizes as $size_index => $size) {
if (in_array($size, $targets, true)) {
continue;
}
return $sizes;
unset($sizes[$size_index]);
}
return $sizes;
}
add_filter('intermediate_image_sizes', 'retire_tailles_image_par_defaut', 10, 1);
@ -170,7 +168,7 @@ add_filter('auto_update_translation', '__return_false');
// Block Patterns
add_action('after_setup_theme', static function (): void {
remove_theme_support('core-block-patterns');
remove_theme_support('core-block-patterns');
});
add_filter('should_load_remote_block_patterns', '__return_false');
@ -180,9 +178,9 @@ add_filter('should_load_remote_block_patterns', '__return_false');
// Charge Carbon Fields
function charge_carbon_fields(): void {
// Nécessaire pour que Carbon Fields trouve ses ressources
define('Carbon_Fields\URL', home_url('/vendor/htmlburger/carbon-fields'));
Carbon_Fields::boot();
// Nécessaire pour que Carbon Fields trouve ses ressources
define('Carbon_Fields\URL', home_url('/vendor/htmlburger/carbon-fields'));
Carbon_Fields::boot();
}
add_action('after_setup_theme', 'charge_carbon_fields');

View file

@ -4,7 +4,10 @@ declare(strict_types=1);
use Timber\Timber;
$contexte = Timber::context();
$modeles = ['base.twig'];
$context = Timber::context();
$templates = ['base.twig'];
Timber::render($filenames = $modeles, $data = $contexte);
Timber::render(
data: $context,
filenames: $templates
);

View file

@ -1,41 +1,45 @@
<?php
declare(strict_types=1);
/**
* Le modèle de la Page À Propos (« About »).
*/
declare(strict_types=1);
use HaikuAtelier\WP\Resource;
use Timber\Timber;
// Contexte et modèles
$contexte = Timber::context();
$modeles = ['a-propos.twig'];
$context = Timber::context();
$templates = ['a-propos.twig'];
$dimensions_image = getimagesize(filename: get_template_directory_uri() . '/assets/img/about/haikuabout.png');
$contexte['dimensions_image'] = $dimensions_image;
// Les dimensions de l'image du storytelling.
$image_dimensions = getimagesize(filename: get_template_directory() . '/assets/img/about/haikuabout.png');
// Charge les scripts et styles de la page
if (is_bool($image_dimensions)) {
throw new Exception("Impossible d'obtenir les dimensions de l'image principale de la page.");
}
$context['image_dimensions'] = $image_dimensions;
/**
* Charge les scripts et styles de la page.
*
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
*/
function charge_scripts_styles_page_a_propos(): void {
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-a-propos',
src: get_template_directory_uri() . '/assets/css/pages/page-a-propos.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-a-propos.css'),
media: 'all',
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-scripts-page-a-propos',
src: get_template_directory_uri() . '/assets/js/scripts-page-a-propos.js',
deps: [],
version: filemtime(get_template_directory() . '/assets/js/scripts-page-a-propos.js'),
);
Resource::enqueue_style_file(
handle: 'haiku-atelier-2024-styles-page-a-propos',
path: '/assets/css/pages/page-a-propos.css'
);
Resource::enqueue_script_module_file(
id: 'haiku-atelier-2024-scripts-page-a-propos',
path: '/assets/js/scripts-page-a-propos.js'
);
}
add_action('wp_enqueue_scripts', 'charge_scripts_styles_page_a_propos');
// Rendu
Timber::render(
filenames: $modeles,
data: $contexte,
data: $context,
filenames: $templates
);

View file

@ -1,14 +1,16 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
/**
* Le modèle de la Page Panier (« Cart »).
*/
use function Crell\fp\pipe;
use Illuminate\Support\Number;
use Timber\Timber;
use function Crell\fp\pipe;
// Importe la fonction pour récupérer les informations affichées des Produits dans le Panier
require_once __DIR__ . '/src/inc/TraitementInformations.php';
@ -17,74 +19,74 @@ $contexte = Timber::context();
$modeles = ['panier.twig'];
$pays_acceptes = [
'AD',
'AL',
'AM',
'AR',
'AT',
'AU',
'BA',
'BE',
'BG',
'BR',
'CA',
'CH',
'CL',
'CR',
'CU',
'CY',
'CZ',
'DE',
'DK',
'DZ',
'EE',
'EG',
'ES',
'FI',
'FR',
'GF',
'GP',
'GR',
'HR',
'HU',
'IE',
'IS',
'IT',
'JP',
'KR',
'LB',
'LI',
'LT',
'LU',
'LV',
'MA',
'MD',
'ME',
'MF',
'MQ',
'MT',
'MX',
'NC',
'NL',
'NO',
'NZ',
'PF',
'PL',
'PM',
'PS',
'PT',
'RE',
'RO',
'SE',
'SI',
'SK',
'SM',
'TN',
'TR',
'TW',
'US',
'YT',
'ZA',
'AD',
'AL',
'AM',
'AR',
'AT',
'AU',
'BA',
'BE',
'BG',
'BR',
'CA',
'CH',
'CL',
'CR',
'CU',
'CY',
'CZ',
'DE',
'DK',
'DZ',
'EE',
'EG',
'ES',
'FI',
'FR',
'GF',
'GP',
'GR',
'HR',
'HU',
'IE',
'IS',
'IT',
'JP',
'KR',
'LB',
'LI',
'LT',
'LU',
'LV',
'MA',
'MD',
'ME',
'MF',
'MQ',
'MT',
'MX',
'NC',
'NL',
'NO',
'NZ',
'PF',
'PL',
'PM',
'PS',
'PT',
'RE',
'RO',
'SE',
'SI',
'SK',
'SM',
'TN',
'TR',
'TW',
'US',
'YT',
'ZA'
];
// Récupère les informations affichés des Produits du Panier
@ -103,22 +105,22 @@ $sous_total_reduction = Number::format(WC()->cart->get_totals()['discount_total'
$total_panier = Number::format((float) WC()->cart->get_totals()['total'], maxPrecision: 2);
foreach (WC()->cart->get_cart() as $cle_panier => $article_panier) {
$panier[$cle_panier] = [
'attributs' => $article_panier['data']?->get_type() === 'variation'
? recupere_et_formate_attributs_produit($article_panier['data']?->get_attributes())
: [],
'cle' => $cle_panier,
'id_produit' => $article_panier['product_id'],
'id_variation' => $article_panier['variation_id'],
'image' => pipe($article_panier['data']?->get_image_id(), static fn($id): string => genere_balise_img_multiformats(
id: (string) $id,
lazy: true,
)),
'prix' => $article_panier['data']?->get_price(),
'quantite' => $article_panier['quantity'],
'url' => $article_panier['data']?->get_permalink(),
'titre' => $article_panier['data']?->get_title(),
];
$panier[$cle_panier] = [
'attributs' => $article_panier['data']?->get_type() === 'variation'
? recupere_et_formate_attributs_produit($article_panier['data']?->get_attributes())
: [],
'cle' => $cle_panier,
'id_produit' => $article_panier['product_id'],
'id_variation' => $article_panier['variation_id'],
'image' => pipe($article_panier['data']?->get_image_id(), static fn($id): string => genere_balise_img_multiformats(
id: (string) $id,
lazy: true
)),
'prix' => $article_panier['data']?->get_price(),
'quantite' => $article_panier['quantity'],
'url' => $article_panier['data']?->get_permalink(),
'titre' => $article_panier['data']?->get_title()
];
}
// Récupère les Adresses de l'Utilisateur
@ -129,13 +131,13 @@ $adresse_renseignee = $adresse_livraison['city'] !== '';
$pays_livraison = collect(WC()->countries->get_countries())->only($pays_acceptes)->toArray();
$total_livraison = Number::format((float) WC()->cart->get_totals()['shipping_total'], precision: 0);
$methodes_livraison = collect(WC()->session->get('shipping_for_package_0')['rates'])
->values()
->map(static fn(WC_Shipping_Rate $methode): array => [
'id' => $methode->get_method_id(),
'prix' => Number::format((int) $methode->get_cost(), maxPrecision: 2),
'selectionnee' => collect(WC()->session->get('chosen_shipping_methods'))->first() === $methode->get_id(),
'titre' => $methode->get_label(),
]);
->values()
->map(static fn(WC_Shipping_Rate $methode): array => [
'id' => $methode->get_method_id(),
'prix' => Number::format((int) $methode->get_cost(), maxPrecision: 2),
'selectionnee' => collect(WC()->session->get('chosen_shipping_methods'))->first() === $methode->get_id(),
'titre' => $methode->get_label()
]);
$contexte['email'] = $email;
$contexte['adresse_livraison'] = $adresse_livraison;
@ -152,19 +154,19 @@ $contexte['methodes_livraison'] = $methodes_livraison;
// Charge les scripts et styles de la page
function charge_scripts_styles_page_panier(): void {
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-panier',
src: get_template_directory_uri() . '/assets/css/pages/page-panier.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-panier.css'),
media: 'all',
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-scripts-page-panier',
src: get_template_directory_uri() . '/assets/js/scripts-page-panier.js',
deps: [],
version: filemtime(get_template_directory() . '/assets/js/scripts-page-panier.js'),
);
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-panier',
src: get_template_directory_uri() . '/assets/css/pages/page-panier.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-panier.css'),
media: 'all'
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-scripts-page-panier',
src: get_template_directory_uri() . '/assets/js/scripts-page-panier.js',
deps: [],
version: filemtime(get_template_directory() . '/assets/js/scripts-page-panier.js')
);
}
add_action('wp_enqueue_scripts', 'charge_scripts_styles_page_panier');
@ -174,6 +176,6 @@ add_action('wp_enqueue_scripts', 'charge_scripts_styles_page_panier');
// Rendu
Timber::render(
filenames: $modeles,
data: $contexte,
filenames: $modeles,
data: $contexte
);

View file

@ -17,19 +17,19 @@ header('Content-Type: application/json; charset=utf-8');
// TODO: Appliquer le bon calcul pour les montants vs. percentages
function get_discount_amount(WC_Coupon $coupon) {
if ($coupon->get_discount_type() === 'fixed_cart') {
return $coupon->get_amount() * 100;
} else {
return $coupon->get_amount();
}
if ($coupon->get_discount_type() === 'fixed_cart') {
return $coupon->get_amount() * 100;
} else {
return $coupon->get_amount();
}
}
function get_discount_duration(WC_Coupon $coupon): string {
if ($coupon->get_discount_type() === 'fixed_cart') {
return 'once';
} else {
return 'forever';
}
if ($coupon->get_discount_type() === 'fixed_cart') {
return 'once';
} else {
return 'forever';
}
}
// Récupère les informations nécessaires
@ -38,37 +38,37 @@ $session_wc = WC()->session;
/** @var array<string,string> $urls URLs utilisables pour rediriger l'Utilisateur. */
$urls = [
'accueil' => get_page_link(get_page_by_path('home')),
'succes_commande' => get_page_link(get_page_by_path('successful-order')),
'echec_commande' => get_page_link(get_page_by_path('failed-order')),
'accueil' => get_page_link(get_page_by_path('home')),
'succes_commande' => get_page_link(get_page_by_path('successful-order')),
'echec_commande' => get_page_link(get_page_by_path('failed-order'))
];
// Redirige à la page d'accueil si le Panier est vide
if (WC()->cart->is_empty()) {
header('Location: ' . $urls['accueil']);
header('Location: ' . $urls['accueil']);
return;
return;
}
// Vérifie que les paramètres d'URLs nécessaires soient présents
/** @var string $order_id */
$order_id = $_GET['order_id'];
if (!$order_id) {
$reponse = ['succes' => false, 'status' => 'order_key is missing'];
echo json_encode($reponse);
http_response_code(400);
$reponse = ['succes' => false, 'status' => 'order_key is missing'];
echo json_encode($reponse);
http_response_code(400);
return;
return;
}
/** @var string $order_key */
$order_key = $_GET['order_key'];
if (!$order_key) {
$reponse = ['succes' => false, 'status' => 'order_key is missing'];
echo json_encode($reponse);
http_response_code(400);
$reponse = ['succes' => false, 'status' => 'order_key is missing'];
echo json_encode($reponse);
http_response_code(400);
return;
return;
}
// Récupère le Panier et l'Email du Client
@ -80,29 +80,29 @@ $email_client = WC()->session->get('customer')['email'];
/** @var list<Product> $articles */
$articles = collect($panier->get_cart())
->map(static function ($article_panier) {
$titre_produit = match ('variable' === $article_panier['data']?->get_type()) {
true => $article_panier['data']?->get_title()
. ' ('
. explode(': ', (string) $article_panier['data']?->get_attribute_summary())[1]
. ')',
false => $article_panier['data']?->get_title(),
};
->map(static function ($article_panier) {
$titre_produit = match ('variable' === $article_panier['data']?->get_type()) {
true => $article_panier['data']?->get_title()
. ' ('
. explode(': ', (string) $article_panier['data']?->get_attribute_summary())[1]
. ')',
false => $article_panier['data']?->get_title()
};
return [
'price_data' => [
'currency' => 'EUR',
'product_data' => [
'name' => $titre_produit,
'images' => [wp_get_attachment_image_url($article_panier['data']?->get_image_id())],
],
'unit_amount' => $article_panier['data']?->get_price() * 100,
],
'quantity' => $article_panier['quantity'],
];
})
->values()
->toArray();
return [
'price_data' => [
'currency' => 'EUR',
'product_data' => [
'name' => $titre_produit,
'images' => [wp_get_attachment_image_url($article_panier['data']?->get_image_id())]
],
'unit_amount' => $article_panier['data']?->get_price() * 100
],
'quantity' => $article_panier['quantity']
];
})
->values()
->toArray();
// Récupère la Commande et la Méthode de Livraison
/** @var WC_Order $commande */
@ -112,7 +112,7 @@ $methode_livraison = ['nom' => $commande->get_shipping_method(), 'cout' => $comm
// Le nom de la méthode de livraison ne peut être une chaîne vide.
if (empty($methode_livraison['nom'])) {
$methode_livraison['nom'] = 'Free';
$methode_livraison['nom'] = 'Free';
}
// Sélectionne la clé API Stripe
@ -121,39 +121,42 @@ Stripe::setApiKey(Config::get('STRIPE_API_SECRET'));
// Met à jour les Codes promos
$coupons_stripe = collect(Coupon::all()->data);
$coupons_wc = collect(WC()->cart->get_coupons())
->map(static fn(WC_Coupon $coupon): array => [
'currency' => 'EUR',
'duration' => get_discount_duration($coupon),
'fixed_cart' === $coupon->get_discount_type() ? 'amount_off' : 'percent_off' => get_discount_amount($coupon),
'id' => $coupon->get_code(),
'name' => $coupon->get_code(),
])
->each(static function (array $item) use ($coupons_stripe): void {
// Si le code promo n'existe pas, le créer
if (!$coupons_stripe->contains('name', $item['name'])) {
Coupon::create($item);
}
});
$reductions_stripe = $coupons_wc->map(static fn($coupon): array => ['coupon' => $coupon['name']])->values()->toArray();
->map(static fn(WC_Coupon $coupon): array => [
'currency' => 'EUR',
'duration' => get_discount_duration($coupon),
'fixed_cart' === $coupon->get_discount_type() ? 'amount_off' : 'percent_off' => get_discount_amount($coupon),
'id' => $coupon->get_code(),
'name' => $coupon->get_code()
])
->each(static function (array $item) use ($coupons_stripe): void {
// Si le code promo n'existe pas, le créer
if (!$coupons_stripe->contains('name', $item['name'])) {
Coupon::create($item);
}
});
$reductions_stripe = $coupons_wc
->map(static fn($coupon): array => ['coupon' => $coupon['name']])
->values()
->toArray();
/** @var Session $session_checkout_stripe */
$session_checkout_stripe = \Stripe\Checkout\Session::create([
'cancel_url' => $urls['echec_commande'],
'customer_email' => $email_client,
'discounts' => $reductions_stripe,
'line_items' => $articles,
'mode' => 'payment',
'success_url' => $urls['succes_commande'] . '?session_id={CHECKOUT_SESSION_ID}',
'metadata' => ['order_id' => $order_id, 'order_key' => $order_key],
'shipping_options' => [['shipping_rate_data' => [
'display_name' => $methode_livraison['nom'],
'fixed_amount' => ['amount' => $methode_livraison['cout'], 'currency' => 'EUR'],
'tax_behavior' => 'inclusive',
'type' => 'fixed_amount',
]]],
'cancel_url' => $urls['echec_commande'],
'customer_email' => $email_client,
'discounts' => $reductions_stripe,
'line_items' => $articles,
'mode' => 'payment',
'success_url' => $urls['succes_commande'] . '?session_id={CHECKOUT_SESSION_ID}',
'metadata' => ['order_id' => $order_id, 'order_key' => $order_key],
'shipping_options' => [['shipping_rate_data' => [
'display_name' => $methode_livraison['nom'],
'fixed_amount' => ['amount' => $methode_livraison['cout'], 'currency' => 'EUR'],
'tax_behavior' => 'inclusive',
'type' => 'fixed_amount'
]]]
], ['idempotency_key' => Uuid::v4()]);
// echo json_encode($session_checkout_stripe);
header('HTTP/1.1 303 See Other');
header('Location: ' . $session_checkout_stripe->url);
exit;
exit();

View file

@ -1,4 +1,6 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
/**
* Modèle de la Page Contact.
@ -12,19 +14,19 @@ $modeles = ['contact.twig'];
// Charge les scripts et styles de la page
function charge_scripts_styles_page_contact(): void {
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-contact',
src: get_template_directory_uri() . '/assets/css/pages/page-modele-simple.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-modele-simple.css'),
media: 'all',
);
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-contact',
src: get_template_directory_uri() . '/assets/css/pages/page-modele-simple.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-modele-simple.css'),
media: 'all'
);
}
add_action('wp_enqueue_scripts', 'charge_scripts_styles_page_contact');
// Rendu
Timber::render(
filenames: $modeles,
data: $contexte,
filenames: $modeles,
data: $contexte
);

View file

@ -14,19 +14,19 @@ $modeles = ['echec-commande.twig'];
// Charge les scripts et styles de la page
function charge_scripts_styles_page_echec_commande(): void {
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-a-propos',
src: get_template_directory_uri() . '/assets/css/pages/page-modele-simple.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-modele-simple.css'),
media: 'all',
);
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-a-propos',
src: get_template_directory_uri() . '/assets/css/pages/page-modele-simple.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-modele-simple.css'),
media: 'all'
);
}
add_action('wp_enqueue_scripts', 'charge_scripts_styles_page_echec_commande');
// Rendu
Timber::render(
filenames: $modeles,
data: $contexte,
filenames: $modeles,
data: $contexte
);

View file

@ -6,13 +6,13 @@
declare(strict_types=1);
use function Crell\fp\pipe;
use Roots\WPConfig\Config;
use Stripe\Checkout\Session;
use Stripe\StripeClient;
use Timber\Timber;
use function Crell\fp\pipe;
require_once __DIR__ . '/src/inc/TraitementInformations.php';
/** @var string $url_accueil L'URL de la page d'Accueil. */
@ -22,9 +22,9 @@ $url_accueil = get_page_link(get_page_by_path('home')?->ID);
$session_id = $_GET['session_id'];
// Redirige à l'Accueil si le paramètre d'ID de Session Stripe n'est pas présent avec un code HTTP 301
if (!$session_id) {
header("Location: {$url_accueil}");
header("Location: {$url_accueil}");
return;
return;
}
// Instancie un Client Stripe
@ -32,89 +32,89 @@ if (!$session_id) {
$client_stripe = new StripeClient(Config::get('STRIPE_API_SECRET'));
try {
/** @var Session $session_stripe La Session Stripe pour la Commande. */
$session_stripe = $client_stripe->checkout->sessions->retrieve($session_id);
/** @var Session $session_stripe La Session Stripe pour la Commande. */
$session_stripe = $client_stripe->checkout->sessions->retrieve($session_id);
/** @var string $order_id L'ID de la Commande WooCommerce passée en métadonnée à la Session. */
$order_id = $session_stripe->metadata['order_id'];
/** @var string $order_id L'ID de la Commande WooCommerce passée en métadonnée à la Session. */
$order_id = $session_stripe->metadata['order_id'];
/** @var bool|WC_Order|WC_Order_Refund $commande La Commande WooCommerce liée à la Session Stripe, `false` si inexistante. */
$commande = wc_get_order("{$order_id}");
/** @var bool|WC_Order|WC_Order_Refund $commande La Commande WooCommerce liée à la Session Stripe, `false` si inexistante. */
$commande = wc_get_order("{$order_id}");
/** @var WC_Cart $panier */
$panier = WC()->cart;
/** @var WC_Cart $panier */
$panier = WC()->cart;
if (false === $commande) {
throw new Error("La commande {$order_id} n'existe pas.");
}
if (false === $commande) {
throw new Error("La commande {$order_id} n'existe pas.");
}
// Passe la Commande en état "Payé" et réinitialise le Panier
if ('pending' === $commande->get_status()) {
$commande->payment_complete($session_id);
// $commande->set_payment_method_title("Stripe - Carte bancaire");
$commande->set_transaction_id($session_id);
// Passe la Commande en état "Payé" et réinitialise le Panier
if ('pending' === $commande->get_status()) {
$commande->payment_complete($session_id);
// $commande->set_payment_method_title("Stripe - Carte bancaire");
$commande->set_transaction_id($session_id);
$panier->empty_cart();
}
$panier->empty_cart();
}
// Contexte et modèles
$contexte = Timber::context();
$modeles = ['succes-commande.twig'];
// Contexte et modèles
$contexte = Timber::context();
$modeles = ['succes-commande.twig'];
// Récupère les données des Produits
/** @var mixed $produits Les Produits de la Commande sous forme de tableau contenant uniquement les données affichées nécessaires pour le Page. */
$produits = collect($commande->get_items())->map(static function (WC_Order_Item $produit_commande) {
/** @var string $id_produit L'ID du Produit. */
$id_produit = $produit_commande['product_id'];
// Récupère les données des Produits
/** @var mixed $produits Les Produits de la Commande sous forme de tableau contenant uniquement les données affichées nécessaires pour le Page. */
$produits = collect($commande->get_items())->map(static function (WC_Order_Item $produit_commande) {
/** @var string $id_produit L'ID du Produit. */
$id_produit = $produit_commande['product_id'];
/** @var false|WC_Product|WC_Product_Variable $produit Les informations du Produit. */
$produit = wc_get_product($produit_commande['product_id']);
/** @var false|WC_Product|WC_Product_Variable $produit Les informations du Produit. */
$produit = wc_get_product($produit_commande['product_id']);
// Récupère le nom et la valeur de l'attribut du Produit
$attribut = $produit->is_type('variable')
? collect($produit->get_attributes())->mapWithKeys(static function ($_atr, $cle) use ($produit_commande) {
$nom_attribut = wc_attribute_label($cle, $produit_commande->get_product());
$valeur_attribut = $produit_commande->get_product()->get_attribute($cle);
// Récupère le nom et la valeur de l'attribut du Produit
$attribut = $produit->is_type('variable')
? collect($produit->get_attributes())->mapWithKeys(static function ($_atr, $cle) use ($produit_commande) {
$nom_attribut = wc_attribute_label($cle, $produit_commande->get_product());
$valeur_attribut = $produit_commande->get_product()->get_attribute($cle);
return [['nom' => $nom_attribut, 'valeur' => $valeur_attribut]];
})->toArray()
: [];
return [['nom' => $nom_attribut, 'valeur' => $valeur_attribut]];
})->toArray()
: [];
return [
'attribut' => $attribut,
'id_produit' => $id_produit,
'image' => pipe($produit->get_image_id(), static fn($id): string => genere_balise_img_multiformats(
id: $id,
lazy: true,
)),
'permalien' => $produit->get_permalink(),
'prix' => $produit_commande->get_data()['total'],
'quantite' => $produit_commande->get_quantity(),
'titre' => $produit->get_title(),
];
});
return [
'attribut' => $attribut,
'id_produit' => $id_produit,
'image' => pipe($produit->get_image_id(), static fn($id): string => genere_balise_img_multiformats(
id: $id,
lazy: true
)),
'permalien' => $produit->get_permalink(),
'prix' => $produit_commande->get_data()['total'],
'quantite' => $produit_commande->get_quantity(),
'titre' => $produit->get_title()
];
});
$contexte['produits'] = $produits;
$contexte['produits'] = $produits;
// Charge les scripts et styles de la page
function charge_scripts_styles_page_succes_commande(): void {
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-succes-commande',
src: get_template_directory_uri() . '/assets/css/pages/page-succes-commande.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-succes-commande.css'),
media: 'all',
);
}
add_action('wp_enqueue_scripts', 'charge_scripts_styles_page_succes_commande');
// Rendu
Timber::render(
filenames: $modeles,
data: $contexte,
// Charge les scripts et styles de la page
function charge_scripts_styles_page_succes_commande(): void {
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-succes-commande',
src: get_template_directory_uri() . '/assets/css/pages/page-succes-commande.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-succes-commande.css'),
media: 'all'
);
}
add_action('wp_enqueue_scripts', 'charge_scripts_styles_page_succes_commande');
// Rendu
Timber::render(
filenames: $modeles,
data: $contexte
);
} catch (Error $error) {
http_response_code(500);
echo json_encode(['error' => esc_html($error->getMessage())]);
http_response_code(500);
echo json_encode(['error' => esc_html($error->getMessage())]);
}

View file

@ -1,4 +1,6 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
/**
* Le modèle de la Page « Terms & Conditions ».
@ -12,19 +14,19 @@ $modeles = ['cgv.twig'];
// Charge les scripts et styles de la page
function charge_scripts_styles_page_cgv(): void {
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-cgv',
src: get_template_directory_uri() . '/assets/css/pages/page-modele-simple.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-modele-simple.css'),
media: 'all',
);
wp_enqueue_style(
handle: 'haiku-atelier-2024-styles-page-cgv',
src: get_template_directory_uri() . '/assets/css/pages/page-modele-simple.css',
deps: [],
ver: filemtime(get_template_directory() . '/assets/css/pages/page-modele-simple.css'),
media: 'all'
);
}
add_action('wp_enqueue_scripts', 'charge_scripts_styles_page_cgv');
// Rendu
Timber::render(
filenames: $modeles,
data: $contexte,
filenames: $modeles,
data: $contexte
);

View file

@ -1,4 +1,6 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
/**
* Le modèle de la Page d'un Produit.
@ -18,7 +20,7 @@ $product = wc_get_product();
// Le Produit DOIT exister.
if ($product === null || is_bool($product)) {
throw new Exception("Le Produit n'existe pas.");
throw new Exception("Le Produit n'existe pas.");
}
// Assemble les données d'intérêt pour la page au sein d'une Classe.
@ -28,8 +30,8 @@ $donnees_produit = Product::new($product);
$prix_maximal = collect($donnees_produit->variations)->max('price');
$produits_meme_collection = array_map(
array: recupere_produits_meme_collection($donnees_produit->collection)($donnees_produit->id),
callback: Product::new(...),
array: recupere_produits_meme_collection($donnees_produit->collection)($donnees_produit->id),
callback: Product::new(...)
);
$context['produit'] = $donnees_produit;
@ -41,18 +43,18 @@ $context['produits_meme_collection'] = $produits_meme_collection;
* Charge les Scripts nécessaires pour la page Produit.
*/
function charge_scripts_page_produit(): void {
wp_enqueue_script_module(
id: 'haiku-atelier-2024-scripts-page-produit',
src: get_template_directory_uri() . '/assets/js/scripts-page-produit.js',
deps: [],
version: filemtime(get_template_directory() . '/assets/js/scripts-page-produit.js'),
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-scripts-menu-categories',
src: get_template_directory_uri() . '/assets/js/scripts-menu-categories.js',
deps: [],
version: filemtime(get_template_directory() . '/assets/js/scripts-menu-categories.js'),
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-scripts-page-produit',
src: get_template_directory_uri() . '/assets/js/scripts-page-produit.js',
deps: [],
version: filemtime(get_template_directory() . '/assets/js/scripts-page-produit.js')
);
wp_enqueue_script_module(
id: 'haiku-atelier-2024-scripts-menu-categories',
src: get_template_directory_uri() . '/assets/js/scripts-menu-categories.js',
deps: [],
version: filemtime(get_template_directory() . '/assets/js/scripts-menu-categories.js')
);
}
add_action('wp_enqueue_scripts', 'charge_scripts_page_produit');
@ -62,6 +64,6 @@ echo "<script>console.debug({$lal});</script>";
// Rendu
Timber::render(
filenames: $templates,
data: $context,
filenames: $templates,
data: $context
);

View file

@ -4,17 +4,16 @@ declare(strict_types=1);
namespace HaikuAtelier;
use function Crell\fp\pipe;
use function Env\env;
use Roots\WPConfig\Config;
use Timber\Site;
use Timber\URLHelper;
use function WC;
use function add_action;
use function add_theme_support;
use function array_map;
use function base64_encode;
use function Crell\fp\pipe;
use function Env\env;
use function esc_url;
use function get_categories;
use function get_option;
@ -24,168 +23,168 @@ use function get_privacy_policy_url;
use function get_theme_mod;
use function get_theme_mods;
use function preg_match;
use function WC;
use function wp_create_nonce;
use function wp_get_attachment_image_src;
use function wpautop;
final class StarterSite extends Site {
public function __construct() {
add_action('after_setup_theme', $this->defini_fonctionnalites_theme(...));
add_action('after_setup_theme', [$this, 'charge_traductions_theme']);
public function __construct() {
add_action('after_setup_theme', $this->defini_fonctionnalites_theme(...));
add_action('after_setup_theme', [$this, 'charge_traductions_theme']);
add_action('timber/context', $this->ajoute_au_contexte_twig(...));
add_action('timber/twig/environment/options', $this->maj_environnement_twig(...));
add_action('timber/context', $this->ajoute_au_contexte_twig(...));
add_action('timber/twig/environment/options', $this->maj_environnement_twig(...));
parent::__construct();
}
parent::__construct();
}
/**
* @param array<int,mixed> $context
*
* @return array<int,mixed>
*/
public function ajoute_au_contexte_twig(array $context): array {
$context['site'] = $this;
/**
* @param array<int,mixed> $context
*
* @return array<int,mixed>
*/
public function ajoute_au_contexte_twig(array $context): array {
$context['site'] = $this;
$context['environnement'] = env('WP_ENV');
$context['environnement'] = env('WP_ENV');
// Récupère les liens des réseaux sociaux définis dans la personnalisation du thème
$personnalisations_theme = get_theme_mods();
$liens_reseaux_sociaux = [
'facebook' => ['nom' => 'Facebook', 'url' => $personnalisations_theme['lien_facebook'] ?? ''],
'instagram' => ['nom' => 'Instagram', 'url' => $personnalisations_theme['lien_instagram'] ?? ''],
'pinterest' => ['nom' => 'Pinterest', 'url' => $personnalisations_theme['lien_pinterest'] ?? ''],
];
$context['liens_reseaux_sociaux'] = $liens_reseaux_sociaux;
// Récupère les liens des réseaux sociaux définis dans la personnalisation du thème
$personnalisations_theme = get_theme_mods();
$liens_reseaux_sociaux = [
'facebook' => ['nom' => 'Facebook', 'url' => $personnalisations_theme['lien_facebook'] ?? ''],
'instagram' => ['nom' => 'Instagram', 'url' => $personnalisations_theme['lien_instagram'] ?? ''],
'pinterest' => ['nom' => 'Pinterest', 'url' => $personnalisations_theme['lien_pinterest'] ?? '']
];
$context['liens_reseaux_sociaux'] = $liens_reseaux_sociaux;
// Récupère les textes apparaissant sur les pages Produits
$descriptions_produits = [
'texte_conditions_livraison' => wpautop($personnalisations_theme['texte_conditions_livraison']) ?? '',
'texte_entretien_produit' => wpautop($personnalisations_theme['texte_entretien_produit']) ?? '',
];
$context['descriptions_produits'] = $descriptions_produits;
// Récupère les textes apparaissant sur les pages Produits
$descriptions_produits = [
'texte_conditions_livraison' => wpautop($personnalisations_theme['texte_conditions_livraison']) ?? '',
'texte_entretien_produit' => wpautop($personnalisations_theme['texte_entretien_produit']) ?? ''
];
$context['descriptions_produits'] = $descriptions_produits;
// Logo personnalisée
$context['logo'] = pipe(get_theme_mod('custom_logo'), static fn($id) => wp_get_attachment_image_src(
attachment_id: $id,
size: 'full',
));
// Logo personnalisée
$context['logo'] = pipe(get_theme_mod('custom_logo'), static fn($id) => wp_get_attachment_image_src(
attachment_id: $id,
size: 'full'
));
// Informations des Pages
$recupere_informations_page = static function ($slug) {
$page = get_page_by_path($slug);
// Informations des Pages
$recupere_informations_page = static function ($slug) {
$page = get_page_by_path($slug);
return (object) ['nom' => $page->post_title ?? '', 'lien' => get_page_link($page?->ID)];
};
return (object) ['nom' => $page->post_title ?? '', 'lien' => get_page_link($page?->ID)];
};
// Pages spécifiques
$context['pages'] = (object) [
'about' => $recupere_informations_page('about'),
'account' => $recupere_informations_page('account'),
'cart' => $recupere_informations_page('cart'),
'checkout' => $recupere_informations_page('checkout'),
'contact' => $recupere_informations_page('contact'),
'failed_order' => $recupere_informations_page('failed_order'),
'home' => $recupere_informations_page('home'),
'shop' => $recupere_informations_page('shop'),
'successful_order' => $recupere_informations_page('successful_order'),
];
// Pages spécifiques
$context['pages'] = (object) [
'about' => $recupere_informations_page('about'),
'account' => $recupere_informations_page('account'),
'cart' => $recupere_informations_page('cart'),
'checkout' => $recupere_informations_page('checkout'),
'contact' => $recupere_informations_page('contact'),
'failed_order' => $recupere_informations_page('failed_order'),
'home' => $recupere_informations_page('home'),
'shop' => $recupere_informations_page('shop'),
'successful_order' => $recupere_informations_page('successful_order')
];
// Récupère la Page courante
$url_courante = URLHelper::get_current_url();
$context['page_courante'] = $url_courante;
$context['est_page_tous_produits'] = preg_match(
pattern: '/(\bshop\b)/',
subject: $url_courante,
);
$context['est_page_boutique'] = preg_match(
pattern: '/(\bshop\b)/',
subject: $url_courante,
)
|| preg_match(
pattern: '/(\bproduct\b)/',
subject: $url_courante,
)
|| preg_match(
pattern: '/(\bproduct-category\b)/',
subject: $url_courante,
);
// Récupère la Page courante
$url_courante = URLHelper::get_current_url();
$context['page_courante'] = $url_courante;
$context['est_page_tous_produits'] = preg_match(
pattern: '/(\bshop\b)/',
subject: $url_courante
);
$context['est_page_boutique'] = preg_match(
pattern: '/(\bshop\b)/',
subject: $url_courante
)
|| preg_match(
pattern: '/(\bproduct\b)/',
subject: $url_courante
)
|| preg_match(
pattern: '/(\bproduct-category\b)/',
subject: $url_courante
);
// Politique de confidentialité
$politique_confidentialite_lien = pipe(get_privacy_policy_url(), esc_url(...));
$context['lien_politique_confidentialite'] = $politique_confidentialite_lien;
// Politique de confidentialité
$politique_confidentialite_lien = pipe(get_privacy_policy_url(), esc_url(...));
$context['lien_politique_confidentialite'] = $politique_confidentialite_lien;
// Chemin de base pour une Catégorie de Produit (p. ex. /product-category/<produit>)
$context['base_categorie_produit'] = get_option('woocommerce_permalinks')['category_base'] ?? '';
// Chemin de base pour une Catégorie de Produit (p. ex. /product-category/<produit>)
$context['base_categorie_produit'] = get_option('woocommerce_permalinks')['category_base'] ?? '';
// Récupère les Catégories de Produits
$cree_entree_menu = static fn($categorie): array => [
'nom' => $categorie->name,
'slug' => $categorie->slug,
// Détermine si l'URL courante est celle de la Page d'Archive d'une Catégorie de Produits
'courante' => preg_match(
pattern: "/(\\b{$categorie->slug}\\b)/",
subject: (string) pipe(URLHelper::get_current_url(), URLHelper::get_rel_url(...)),
),
];
$entrees_menu_categories = pipe(
get_categories(['hide_empty' => false, 'orderby' => 'menu_order', 'taxonomy' => 'product_cat']),
static fn($categories): array => array_map(
callback: $cree_entree_menu,
array: $categories,
),
);
// Récupère les Catégories de Produits
$cree_entree_menu = static fn($categorie): array => [
'nom' => $categorie->name,
'slug' => $categorie->slug,
// Détermine si l'URL courante est celle de la Page d'Archive d'une Catégorie de Produits
'courante' => preg_match(
pattern: "/(\\b{$categorie->slug}\\b)/",
subject: (string) pipe(URLHelper::get_current_url(), URLHelper::get_rel_url(...))
)
];
$entrees_menu_categories = pipe(
get_categories(['hide_empty' => false, 'orderby' => 'menu_order', 'taxonomy' => 'product_cat']),
static fn($categories): array => array_map(
callback: $cree_entree_menu,
array: $categories
)
);
$context['categories_produits'] = $entrees_menu_categories;
$context['categories_produits'] = $entrees_menu_categories;
// Récupère le Panier de l'Utilisateur
$panier = WC()?->cart?->get_cart();
$quantite_articles = WC()?->cart?->get_cart_contents_count();
$articles_presents = $quantite_articles > 0 ? 'true' : 'false';
// Récupère le Panier de l'Utilisateur
$panier = WC()?->cart?->get_cart();
$quantite_articles = WC()?->cart?->get_cart_contents_count();
$articles_presents = $quantite_articles > 0 ? 'true' : 'false';
$context['panier'] = $panier;
$context['quantite_articles'] = $quantite_articles;
$context['articles_presents'] = $articles_presents;
$context['panier'] = $panier;
$context['quantite_articles'] = $quantite_articles;
$context['articles_presents'] = $articles_presents;
// Nonce WooCommerce pour l'API Rest
$nonce_wc = wp_create_nonce('wc_store_api');
$context['nonce_wc'] = $nonce_wc;
// TODO: Utiliser des variables d'environnement
$auth_string = base64_encode(
Config::get('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . Config::get('WOOCOMMERCE_API_CONSUMER_SECRET'),
);
$context['auth_string'] = $auth_string;
// Nonce WooCommerce pour l'API Rest
$nonce_wc = wp_create_nonce('wc_store_api');
$context['nonce_wc'] = $nonce_wc;
// TODO: Utiliser des variables d'environnement
$auth_string = base64_encode(
Config::get('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . Config::get('WOOCOMMERCE_API_CONSUMER_SECRET')
);
$context['auth_string'] = $auth_string;
return $context;
}
return $context;
}
public function defini_fonctionnalites_theme(): void {
// Laisse WordPress gérer le titre de la page
add_theme_support('title-tag');
public function defini_fonctionnalites_theme(): void {
// Laisse WordPress gérer le titre de la page
add_theme_support('title-tag');
// Ajoute les Miniatures aux Posts et Pages
add_theme_support('post-thumbnails');
// Ajoute les Miniatures aux Posts et Pages
add_theme_support('post-thumbnails');
// Utilise des éléments sémantiques HTML5 pour ces éléments générés par WordPress
add_theme_support('html5', ['comment-list', 'comment-form', 'search-form', 'gallery', 'caption']);
// Utilise des éléments sémantiques HTML5 pour ces éléments générés par WordPress
add_theme_support('html5', ['comment-list', 'comment-form', 'search-form', 'gallery', 'caption']);
// Ajoute la possibilité d'un Logo personnalisé
add_theme_support('custom-logo');
// Ajoute la possibilité d'un Logo personnalisé
add_theme_support('custom-logo');
// Ajoute la prise en charge de WooCommerce
add_theme_support('woocommerce');
}
// Ajoute la prise en charge de WooCommerce
add_theme_support('woocommerce');
}
/**
* Met à jour l'environnement de Twig.
*
* @param array $options un tableau avec les options d'environnement
*/
public function maj_environnement_twig(array $options): array {
return $options;
}
// public function charge_traductions_theme(): void {
// load_theme_textdomain("haiku-atelier-2024", get_template_directory() . "/languages");
// }
/**
* Met à jour l'environnement de Twig.
*
* @param array $options un tableau avec les options d'environnement
*/
public function maj_environnement_twig(array $options): array {
return $options;
}
// public function charge_traductions_theme(): void {
// load_theme_textdomain("haiku-atelier-2024", get_template_directory() . "/languages");
// }
}

View file

@ -10,35 +10,35 @@ use Carbon_Fields\Container;
use Carbon_Fields\Field;
function cree_champs_personnalises_produit(): void {
Container::make('post_meta', "Product's Details")
->where('post_type', '=', 'product')
->add_fields([
// Galerie des photos Produit
Field::make('media_gallery', 'photos_colonne_gauche', __('Left Column Photos'))
->set_type(['image'])
->set_duplicates_allowed(false),
// Galerie des photos portées
Field::make('media_gallery', 'photos_colonne_droite', __('Right Column Photos'))
->set_type(['image'])
->set_duplicates_allowed(false),
// Texte des détails du Produit
Field::make('rich_text', 'haiku_details_produit', __("Product's Details")),
]);
}
function cree_champ_personnalise_commande($order): void {
woocommerce_wp_text_input([
'id' => 'tracking_number',
'label' => 'Tracking Number:',
'value' => $order->get_meta('tracking_number'),
'wrapper_class' => 'form-field-wide',
Container::make('post_meta', "Product's Details")
->where('post_type', '=', 'product')
->add_fields([
// Galerie des photos Produit
Field::make('media_gallery', 'photos_colonne_gauche', __('Left Column Photos'))
->set_type(['image'])
->set_duplicates_allowed(false),
// Galerie des photos portées
Field::make('media_gallery', 'photos_colonne_droite', __('Right Column Photos'))
->set_type(['image'])
->set_duplicates_allowed(false),
// Texte des détails du Produit
Field::make('rich_text', 'haiku_details_produit', __("Product's Details"))
]);
}
function cree_champ_personnalise_commande($order): void {
woocommerce_wp_text_input([
'id' => 'tracking_number',
'label' => 'Tracking Number:',
'value' => $order->get_meta('tracking_number'),
'wrapper_class' => 'form-field-wide'
]);
}
function maj_champ_personnalise_commande($order_id): void {
$order = wc_get_order($order_id);
$order->update_meta_data('tracking_number', wc_clean($_POST['tracking_number']));
$order->save();
$order = wc_get_order($order_id);
$order->update_meta_data('tracking_number', wc_clean($_POST['tracking_number']));
$order->save();
}
add_action('carbon_fields_register_fields', 'cree_champs_personnalises_produit');

View file

@ -9,69 +9,68 @@
declare(strict_types=1);
function enregistre_controle_personnalise_tinymce(): void {
/**
* TinyMCE Custom Control.
*
* @author Anthony Hortin <http://maddisondesigns.com>
* @license http://www.gnu.org/licenses/gpl-2.0.html
*
* @see https://github.com/maddisondesigns
*/
final class ControlesPersonnalises extends WP_Customize_Control {
/** The type of control being rendered. */
public $type = 'editeur_tinymce';
/**
* TinyMCE Custom Control.
*
* @author Anthony Hortin <http://maddisondesigns.com>
* @license http://www.gnu.org/licenses/gpl-2.0.html
*
* @see https://github.com/maddisondesigns
* Enqueue our scripts and styles.
*/
final class ControlesPersonnalises extends WP_Customize_Control {
/** The type of control being rendered. */
public $type = 'editeur_tinymce';
public function enqueue(): void {
wp_enqueue_script(
handle: 'controle-personnalise-tinymce',
src: get_template_directory_uri() . '/assets/vendor/controle-personnalise-tinymce.js',
deps: ['jquery'],
ver: '1.3',
args: true
);
wp_enqueue_editor();
}
/**
* Enqueue our scripts and styles.
*/
#[Override()]
public function enqueue(): void {
wp_enqueue_script(
handle: 'controle-personnalise-tinymce',
src: get_template_directory_uri() . '/assets/vendor/controle-personnalise-tinymce.js',
deps: ['jquery'],
ver: '1.3',
args: true,
);
wp_enqueue_editor();
}
/**
* Render the control in the customizer.
*/
#[Override()]
public function render_content(): void { ?>
/**
* Render the control in the customizer.
*/
public function render_content(): void { ?>
<div class="tinymce-control">
<span class="customize-control-title"><?php echo esc_html($this->label); ?></span>
<?php if (!empty($this->description)) { ?>
<span class="customize-control-description"><?php echo esc_html($this->description); ?></span>
<?php } ?>
<textarea id="<?php echo esc_attr($this->id); ?>" class="customize-control-tinymce-editor" <?php $this->link(); ?>><?php echo
esc_html($this->value())
<textarea id="<?php echo
esc_attr($this->id)
; ?>" class="customize-control-tinymce-editor" <?php $this->link(); ?>><?php echo
esc_html($this->value())
; ?></textarea>
</div>
<?php }
/**
* Pass our TinyMCE toolbar string to JavaScript.
*/
#[Override()]
public function to_json(): void {
parent::to_json();
/**
* Pass our TinyMCE toolbar string to JavaScript.
*/
public function to_json(): void {
parent::to_json();
$this->json['skyrockettinymcetoolbar1'] = isset($this->input_attrs['toolbar1'])
? esc_attr($this->input_attrs['toolbar1'])
: 'bold italic bullist numlist alignleft aligncenter alignright link';
$this->json['skyrockettinymcetoolbar1'] = isset($this->input_attrs['toolbar1'])
? esc_attr($this->input_attrs['toolbar1'])
: 'bold italic bullist numlist alignleft aligncenter alignright link';
$this->json['skyrockettinymcetoolbar2'] = isset($this->input_attrs['toolbar2'])
? esc_attr($this->input_attrs['toolbar2'])
: '';
$this->json['skyrocketmediabuttons'] = isset($this->input_attrs['mediaButtons'])
&& $this->input_attrs['mediaButtons'] === true
? true
: false;
}
$this->json['skyrockettinymcetoolbar2'] = isset($this->input_attrs['toolbar2'])
? esc_attr($this->input_attrs['toolbar2'])
: '';
$this->json['skyrocketmediabuttons'] = isset($this->input_attrs['mediaButtons'])
&& $this->input_attrs['mediaButtons'] === true
? true
: false;
}
}
}
add_action('customize_register', 'enregistre_controle_personnalise_tinymce');

View file

@ -1,4 +1,6 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
namespace HaikuAtelier\Data;
@ -7,27 +9,27 @@ use WC_Product_Attribute;
use WP_Term;
final readonly class Attribute {
/**
* @param list<AttributeOption> $options
*/
public function __construct(
public string $name,
public string $slug,
public array $options,
) {}
/**
* @param list<AttributeOption> $options
*/
public function __construct(
public string $name,
public string $slug,
public array $options
) {}
public static function new(WC_Product_Attribute $attribute): self {
$name = wc_attribute_label($attribute->get_name());
$slug = $attribute->get_name();
/** @var list<WP_Term> */
$terms = $attribute->get_terms() ?? [];
/** @var list<AttributeOption> */
$options = Arr::map($terms, static fn(WP_Term $term): AttributeOption => AttributeOption::new($term));
public static function new(WC_Product_Attribute $attribute): self {
$name = wc_attribute_label($attribute->get_name());
$slug = $attribute->get_name();
/** @var list<WP_Term> */
$terms = $attribute->get_terms() ?? [];
/** @var list<AttributeOption> */
$options = Arr::map($terms, AttributeOption::new(...));
return new self(
name: $name,
slug: $slug,
options: $options,
);
}
return new self(
name: $name,
slug: $slug,
options: $options
);
}
}

View file

@ -1,25 +1,27 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
namespace HaikuAtelier\Data;
use WP_Term;
final readonly class AttributeOption {
public function __construct(
public int $id,
public string $name,
public string $slug,
) {}
public function __construct(
public int $id,
public string $name,
public string $slug
) {}
public static function new(WP_Term $term): self {
$id = $term->term_taxonomy_id;
$name = $term->name;
$slug = $term->slug;
public static function new(WP_Term $term): self {
$id = $term->term_taxonomy_id;
$name = $term->name;
$slug = $term->slug;
return new self(
id: $id,
name: $name,
slug: $slug,
);
}
return new self(
id: $id,
name: $name,
slug: $slug
);
}
}

View file

@ -1,4 +1,6 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
namespace HaikuAtelier\Data;
@ -6,99 +8,93 @@ use HaikuAtelier\WP\HaikuProduct;
use HaikuAtelier\WP\Term;
use Illuminate\Support\Arr;
use Psl\Option;
use function Psl\Option\from_nullable;
use WC_Product;
use WC_Product_Attribute;
use WP_Term;
use function Psl\Option\from_nullable;
final readonly class Product {
/**
* @param list<Attribute> $attributes
* @param list<string> $left_column_photos
* @param list<string> $right_column_photos
* @param list<ProductVariation> $variations
*/
private function __construct(
public array $attributes,
public string $category,
public string $collection,
public string $details,
public int $id,
public string $name,
public string $price,
public array $left_column_photos,
public array $right_column_photos,
public string $default_photo,
public string $hover_photo,
public string $slug,
public int $stock,
public array $variations,
public string $url,
) {}
/**
* @param list<Attribute> $attributes
* @param list<string> $left_column_photos
* @param list<string> $right_column_photos
* @param list<ProductVariation> $variations
*/
private function __construct(
public array $attributes,
public string $category,
public string $collection,
public string $details,
public int $id,
public string $name,
public string $price,
public array $left_column_photos,
public array $right_column_photos,
public string $default_photo,
public string $hover_photo,
public string $slug,
public int $stock,
public array $variations,
public string $url
) {}
/**
* @return list<Attribute>
*/
public static function get_attributes_for_product(WC_Product $product): array {
/** @var list<Attribute> */
return $product->get_attributes()
|> (static fn($attributes) => Arr::map($attributes, static fn(WC_Product_Attribute $attribute): Attribute => Attribute::new(
$attribute,
)));
}
/**
* @return list<Attribute>
*/
public static function get_attributes_for_product(WC_Product $product): array {
/** @var list<Attribute> */
return $product->get_attributes() |> (static fn($attributes) => Arr::map($attributes, Attribute::new(...)));
}
public static function new(WC_Product $product): self {
/** @var list<Attribute> */
$attributes = self::get_attributes_for_product($product);
/** @var lowercase-string */
$category = $product->get_id() |> wc_get_product_category_list(...) |> strtolower(...);
public static function new(WC_Product $product): self {
/** @var list<Attribute> */
$attributes = self::get_attributes_for_product($product);
/** @var lowercase-string */
$category = $product->get_id() |> wc_get_product_category_list(...) |> strtolower(...);
/** @var Option\Option<list<WP_Term>> */
$collection = Term::get_terms($product->get_id(), 'collection');
/** @var Option\Option<WP_Term> */
$collection = $collection->andThen(
static fn(array $terms): Option\Option => head($terms) |> from_nullable(...),
);
/** @var Option\Option<string> */
$collection = $collection->map(static fn(WP_Term $term) => $term->slug);
/** @var string */
$collection = $collection->unwrapOr('');
/** @var Option\Option<list<WP_Term>> */
$collection = Term::get_terms($product->get_id(), 'collection');
/** @var Option\Option<WP_Term> */
$collection = $collection->andThen(static fn(array $terms): Option\Option => head($terms) |> from_nullable(...));
/** @var Option\Option<string> */
$collection = $collection->map(static fn(WP_Term $term) => $term->slug);
/** @var string */
$collection = $collection->unwrapOr('');
/** @var string */
$details = $product->get_description() |> wpautop(...);
$id = $product->get_id();
$name = $product->get_name();
$price = $product->get_price();
/** @var list<string> */
$left_column_photos = HaikuProduct::get_left_column_photos($id);
/** @var list<string> */
$right_column_photos = HaikuProduct::get_right_column_photos($id);
$default_photo = $left_column_photos[0] ?? genere_balise_img_multiformats('-1');
$hover_photo = $right_column_photos[0] ?? genere_balise_img_multiformats('-1', true);
$slug = $product->get_slug();
$stock = $product->get_stock_quantity() ?? 1;
$variations = $product->get_children()
|> (static fn($ids) => Arr::map($ids, wc_get_product(...)))
|> (static fn($products) => Arr::map($products, ProductVariation::new(...)));
$url = $product->get_permalink();
/** @var string */
$details = $product->get_description() |> wpautop(...);
$id = $product->get_id();
$name = $product->get_name();
$price = $product->get_price();
/** @var list<string> */
$left_column_photos = HaikuProduct::get_left_column_photos($id);
/** @var list<string> */
$right_column_photos = HaikuProduct::get_right_column_photos($id);
$default_photo = $left_column_photos[0] ?? genere_balise_img_multiformats('-1');
$hover_photo = $right_column_photos[0] ?? genere_balise_img_multiformats('-1', true);
$slug = $product->get_slug();
$stock = $product->get_stock_quantity() ?? 1;
$variations = $product->get_children()
|> (static fn($ids) => Arr::map($ids, wc_get_product(...)))
|> (static fn($products) => Arr::map($products, ProductVariation::new(...)));
$url = $product->get_permalink();
return new self(
attributes: $attributes,
category: $category,
collection: $collection,
details: $details,
id: $id,
name: $name,
price: $price,
left_column_photos: $left_column_photos,
right_column_photos: $right_column_photos,
default_photo: $default_photo,
hover_photo: $hover_photo,
slug: $slug,
stock: $stock,
variations: $variations,
url: $url,
);
}
return new self(
attributes: $attributes,
category: $category,
collection: $collection,
details: $details,
id: $id,
name: $name,
price: $price,
left_column_photos: $left_column_photos,
right_column_photos: $right_column_photos,
default_photo: $default_photo,
hover_photo: $hover_photo,
slug: $slug,
stock: $stock,
variations: $variations,
url: $url
);
}
}

View file

@ -1,35 +1,37 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
namespace HaikuAtelier\Data;
use WC_Product;
final readonly class ProductVariation {
/**
* @param int $id L'ID de la Variation
* @param string $price Le prix de la Variation
* @param list<ProductVariationAttribute> $attributes Les attributs appliqués à la Variation
*/
private function __construct(
public int $id,
public string $price,
public array $attributes,
) {}
/**
* @param int $id L'ID de la Variation
* @param string $price Le prix de la Variation
* @param list<ProductVariationAttribute> $attributes Les attributs appliqués à la Variation
*/
private function __construct(
public int $id,
public string $price,
public array $attributes
) {}
/**
* Créé une nouvelle instance de `ProductVariation` à partir d'un `WC_Product`.
*/
public static function new(WC_Product $product): self {
$id = $product->get_id();
$price = $product->get_price();
/** @var list<ProductVariationAttribute> */
$attributes = array_map(
/** @phpstan-ignore argument.type (Impossible à satisfaire) */
static fn(string $key, string $value) => new ProductVariationAttribute($key, $value),
array_keys($product->get_attributes()),
array_values($product->get_attributes()),
);
/**
* Créé une nouvelle instance de `ProductVariation` à partir d'un `WC_Product`.
*/
public static function new(WC_Product $product): self {
$id = $product->get_id();
$price = $product->get_price();
/** @var list<ProductVariationAttribute> */
$attributes = array_map(
/** @phpstan-ignore argument.type (Impossible à satisfaire) */
static fn(string $key, string $value) => new ProductVariationAttribute($key, $value),
array_keys($product->get_attributes()),
array_values($product->get_attributes())
);
return new self($id, $price, $attributes);
}
return new self($id, $price, $attributes);
}
}

View file

@ -1,14 +1,16 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
namespace HaikuAtelier\Data;
final readonly class ProductVariationAttribute {
/**
* @param string $attribute Le slug de l'Attribut
* @param string $value Le slug de la valeur de l'Attribut
*/
public function __construct(
public string $attribute,
public string $value,
) {}
/**
* @param string $attribute Le slug de l'Attribut
* @param string $value Le slug de la valeur de l'Attribut
*/
public function __construct(
public string $attribute,
public string $value
) {}
}

View file

@ -8,7 +8,7 @@ declare(strict_types=1);
// Désactive divers transformations du contenu par WordPress
function desactive_wpautop(): void {
remove_filter('the_content', 'wpautop');
remove_filter('the_content', 'wpautop');
}
/**
@ -19,15 +19,15 @@ function desactive_wpautop(): void {
* @return array<string, bool> le même tableau avec des configurations en plus
*/
function desactive_transformation_contenu_tinymce(array $configuration): array {
// Ne supprime pas les retours à la ligne
$configuration['remove_linebreaks'] = false;
// Convertis les caractères de retours à la ligne en <br>
$configuration['convert_newlines_to_brs'] = true;
// Supprime les <br> redondants
$configuration['remove_redundant_brs'] = false;
// Ne supprime pas les retours à la ligne
$configuration['remove_linebreaks'] = false;
// Convertis les caractères de retours à la ligne en <br>
$configuration['convert_newlines_to_brs'] = true;
// Supprime les <br> redondants
$configuration['remove_redundant_brs'] = false;
// Retourne $configuration à WordPress
return $configuration;
// Retourne $configuration à WordPress
return $configuration;
}
/**
@ -38,18 +38,18 @@ function desactive_transformation_contenu_tinymce(array $configuration): array {
* @return array<string, string> le même tableau avec SVG en plus
*/
function autorise_import_svg_mediatheque(array $file_types): array {
$new_filetypes = [];
$new_filetypes['svg'] = 'image/svg+xml';
$new_filetypes = [];
$new_filetypes['svg'] = 'image/svg+xml';
return array_merge($file_types, $new_filetypes);
return array_merge($file_types, $new_filetypes);
}
function retire_motifs_blocs_gutenberg(): void {
remove_theme_support('core-block-patterns');
remove_theme_support('core-block-patterns');
}
function retire_styles_core_block(): void {
wp_dequeue_style('core-block-supports');
wp_dequeue_style('core-block-supports');
}
// Désactive les appels à l'API de la mise à jour des traductions

View file

@ -17,17 +17,17 @@ require_once 'TraitementInformations.php';
* scripts et styles inutiles.
*/
function desactive_images_produit_woocommerce(): void {
remove_action('woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10);
remove_action('woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20);
remove_action('woocommerce_product_thumbnails', 'woocommerce_show_product_thumbnails', 20);
remove_action('woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10);
remove_action('woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20);
remove_action('woocommerce_product_thumbnails', 'woocommerce_show_product_thumbnails', 20);
}
/**
* Désactive les champs liés aux images Produit de l'administration.
*/
function desactive_champs_admin_images_produit_woocommerce(): void {
// Désactive le champ « Galerie d'images du Produit »
remove_meta_box('woocommerce-product-images', 'product', 'side');
// Désactive le champ « Galerie d'images du Produit »
remove_meta_box('woocommerce-product-images', 'product', 'side');
}
// Scripts et styles
@ -36,55 +36,55 @@ function desactive_champs_admin_images_produit_woocommerce(): void {
* Désactive tous les scripts et styles WooCommerce.
*/
function dequeue_woocommerce_styles_scripts(): void {
// Styles
wp_dequeue_style('photoswipe-default-skin-css');
wp_dequeue_style('photoswipe-default-skin');
wp_dequeue_style('photoswipe');
wp_dequeue_style('wc-blocks-style');
wp_dequeue_style('woocommerce_chosen_styles');
wp_dequeue_style('woocommerce_fancybox_styles');
wp_dequeue_style('woocommerce_frontend_styles');
wp_dequeue_style('woocommerce_prettyPhoto_css');
wp_dequeue_style('woocommerce-blocks');
wp_dequeue_style('woocommerce-general');
wp_dequeue_style('woocommerce-inline');
wp_dequeue_style('woocommerce-layout');
wp_dequeue_style('woocommerce-smallscreen');
wp_dequeue_style('wp-block-library');
// Styles
wp_dequeue_style('photoswipe-default-skin-css');
wp_dequeue_style('photoswipe-default-skin');
wp_dequeue_style('photoswipe');
wp_dequeue_style('wc-blocks-style');
wp_dequeue_style('woocommerce_chosen_styles');
wp_dequeue_style('woocommerce_fancybox_styles');
wp_dequeue_style('woocommerce_frontend_styles');
wp_dequeue_style('woocommerce_prettyPhoto_css');
wp_dequeue_style('woocommerce-blocks');
wp_dequeue_style('woocommerce-general');
wp_dequeue_style('woocommerce-inline');
wp_dequeue_style('woocommerce-layout');
wp_dequeue_style('woocommerce-smallscreen');
wp_dequeue_style('wp-block-library');
// Scripts
wp_dequeue_script('fancybox');
wp_dequeue_script('flexslider');
wp_dequeue_script('jquery-blockui');
wp_dequeue_script('jquery-placeholder');
wp_dequeue_script('photoswipe-ui-default');
wp_dequeue_script('prettyPhoto-init');
wp_dequeue_script('prettyPhoto');
wp_dequeue_script('sourcebuster-js');
wp_dequeue_script('wc_price_slider');
wp_dequeue_script('wc-add-to-cart-variation');
wp_dequeue_script('wc-add-to-cart');
wp_dequeue_script('wc-blocks');
wp_dequeue_script('wc-cart-fragments');
wp_dequeue_script('wc-cart');
wp_dequeue_script('wc-checkout');
wp_dequeue_script('wc-chosen');
wp_dequeue_script('wc-order-attribution');
wp_dequeue_script('wc-single-product');
wp_dequeue_script('woocommerce');
wp_dequeue_script('zoom');
wp_deregister_script('flexslider');
wp_deregister_script('sourcebuster-js');
wp_deregister_script('wc-order-attribution');
wp_deregister_script('zoom');
// Scripts
wp_dequeue_script('fancybox');
wp_dequeue_script('flexslider');
wp_dequeue_script('jquery-blockui');
wp_dequeue_script('jquery-placeholder');
wp_dequeue_script('photoswipe-ui-default');
wp_dequeue_script('prettyPhoto-init');
wp_dequeue_script('prettyPhoto');
wp_dequeue_script('sourcebuster-js');
wp_dequeue_script('wc_price_slider');
wp_dequeue_script('wc-add-to-cart-variation');
wp_dequeue_script('wc-add-to-cart');
wp_dequeue_script('wc-blocks');
wp_dequeue_script('wc-cart-fragments');
wp_dequeue_script('wc-cart');
wp_dequeue_script('wc-checkout');
wp_dequeue_script('wc-chosen');
wp_dequeue_script('wc-order-attribution');
wp_dequeue_script('wc-single-product');
wp_dequeue_script('woocommerce');
wp_dequeue_script('zoom');
wp_deregister_script('flexslider');
wp_deregister_script('sourcebuster-js');
wp_deregister_script('wc-order-attribution');
wp_deregister_script('zoom');
}
/**
* Désactive scripts et styles liés aux blocs Gutenberg.
*/
function desactive_blocs_gutenberg_woocommerce(): void {
wp_deregister_style('wc-blocks-style');
wp_dequeue_style('wc-blocks-style');
wp_deregister_style('wc-blocks-style');
wp_dequeue_style('wc-blocks-style');
}
/**
@ -93,35 +93,35 @@ function desactive_blocs_gutenberg_woocommerce(): void {
* Cette fonction surcharge son homonyme et désactive les fonctionnalités non désirées.
*/
function woocommerce_photoswipe(): void {
remove_theme_support('wc-product-gallery-zoom');
remove_theme_support('wc-product-gallery-lightbox');
remove_theme_support('wc-product-gallery-slider');
remove_theme_support('wc-product-gallery-zoom');
remove_theme_support('wc-product-gallery-lightbox');
remove_theme_support('wc-product-gallery-slider');
}
/**
* Désactive l'Attribution des Commandes WooCommerce.
*/
function desactive_attribution_commande_woocommerce(): void {
update_option('woocommerce_feature_order_attribution_enabled', '');
update_option('woocommerce_feature_order_attribution_enabled', '');
}
/**
* Retire d'autres merdes WooCommerce.
*/
function retire_script_galerie(): void {
remove_action('wp_head', 'wc_gallery_noscript');
remove_action('wp_head', 'wc_gallery_noscript');
}
function retire_merdes_wc(): void {
// remove WC generator tag
remove_filter('get_the_generator_html', 'wc_generator_tag', 10, 2);
remove_filter('get_the_generator_xhtml', 'wc_generator_tag', 10, 2);
// unload WC scripts
remove_action('wp_enqueue_scripts', [WC_Frontend_Scripts::class, 'load_scripts']);
remove_action('wp_print_scripts', [WC_Frontend_Scripts::class, 'localize_printed_scripts'], 5);
remove_action('wp_print_footer_scripts', [WC_Frontend_Scripts::class, 'localize_printed_scripts'], 5);
// remove "Show the gallery if JS is disabled"
remove_action('wp_head', 'wc_gallery_noscript');
// remove WC generator tag
remove_filter('get_the_generator_html', 'wc_generator_tag', 10, 2);
remove_filter('get_the_generator_xhtml', 'wc_generator_tag', 10, 2);
// unload WC scripts
remove_action('wp_enqueue_scripts', [WC_Frontend_Scripts::class, 'load_scripts']);
remove_action('wp_print_scripts', [WC_Frontend_Scripts::class, 'localize_printed_scripts'], 5);
remove_action('wp_print_footer_scripts', [WC_Frontend_Scripts::class, 'localize_printed_scripts'], 5);
// remove "Show the gallery if JS is disabled"
remove_action('wp_head', 'wc_gallery_noscript');
}
/**
@ -130,49 +130,49 @@ function retire_merdes_wc(): void {
* @param WP_REST_Response $response the response object
*/
function genere_balises_img_dans_produit_dans_reponse_rest(
WP_REST_Response $response,
mixed $_product,
WP_REST_Response $response,
mixed $_product
): WP_REST_Response {
// Vérifie que la Réponse a des données
if (empty($response->data)) {
return $response;
}
// Génère la balise <img> pour l'image au repos
$response->data['image_repos'] = pipe(
$response->data['meta_data'],
static fn($metadata): array => array_filter(
array: $metadata,
callback: static fn($entree): bool => '_photos_colonne_gauche|||0|value' === $entree->key,
),
static fn($metadata): array => array_map(
array: $metadata,
callback: static fn($entree): string => genere_balise_img_multiformats(
id: $entree?->value,
lazy: true,
),
),
static fn($image) => array_values(array: $image)[0],
);
// Génère la balise <img> pour l'image au survol
$response->data['image_survol'] = pipe(
$response->data['meta_data'],
static fn($metadata): array => array_filter(
array: $metadata,
callback: static fn($entree): bool => '_photos_colonne_droite|||0|value' === $entree->key,
),
static fn($metadata): array => array_map(
array: $metadata,
callback: static fn($entree): string => genere_balise_img_multiformats(
id: $entree?->value,
lazy: true,
),
),
static fn($image) => array_values(array: $image)[0],
);
// Vérifie que la Réponse a des données
if (empty($response->data)) {
return $response;
}
// Génère la balise <img> pour l'image au repos
$response->data['image_repos'] = pipe(
$response->data['meta_data'],
static fn($metadata): array => array_filter(
array: $metadata,
callback: static fn($entree): bool => '_photos_colonne_gauche|||0|value' === $entree->key
),
static fn($metadata): array => array_map(
array: $metadata,
callback: static fn($entree): string => genere_balise_img_multiformats(
id: $entree?->value,
lazy: true
)
),
static fn($image) => array_values(array: $image)[0]
);
// Génère la balise <img> pour l'image au survol
$response->data['image_survol'] = pipe(
$response->data['meta_data'],
static fn($metadata): array => array_filter(
array: $metadata,
callback: static fn($entree): bool => '_photos_colonne_droite|||0|value' === $entree->key
),
static fn($metadata): array => array_map(
array: $metadata,
callback: static fn($entree): string => genere_balise_img_multiformats(
id: $entree?->value,
lazy: true
)
),
static fn($image) => array_values(array: $image)[0]
);
return $response;
}
add_filter('woocommerce_rest_prepare_product_object', 'genere_balises_img_dans_produit_dans_reponse_rest', 10, 2);
@ -181,27 +181,27 @@ add_filter('woocommerce_rest_prepare_product_object', 'genere_balises_img_dans_p
* TODO.
*/
function genere_prix_maximal_produit_variable_dans_reponse_rest(
WP_REST_Response $reponse,
WC_Data $_produit,
WP_REST_Response $reponse,
WC_Data $_produit
): WP_REST_Response {
// Vérifie que la Réponse a des données
if (empty($reponse->data)) {
return $reponse;
}
// Vérifie que la Réponse a des données
if (empty($reponse->data)) {
return $reponse;
}
// Si le Produit n'est pas Variable, assigner le prix du Produit comme prix maximal
if ('variable' !== $reponse->data['type']) {
$reponse->data['prix_maximal'] = $reponse->data['regular_price'];
return $reponse;
}
// Assigne le prix de la Variation la plus chère dans la Réponse
$reponse->data['prix_maximal'] = collect($reponse->data['variations'])
->map(wc_get_product(...))
->map(static fn($p) => $p->get_price())->max();
// Si le Produit n'est pas Variable, assigner le prix du Produit comme prix maximal
if ('variable' !== $reponse->data['type']) {
$reponse->data['prix_maximal'] = $reponse->data['regular_price'];
return $reponse;
}
// Assigne le prix de la Variation la plus chère dans la Réponse
$reponse->data['prix_maximal'] = collect($reponse->data['variations'])
->map(wc_get_product(...))
->map(static fn($p) => $p->get_price())->max();
return $reponse;
}
add_filter('woocommerce_rest_prepare_product_object', 'genere_prix_maximal_produit_variable_dans_reponse_rest', 10, 2);
@ -210,7 +210,7 @@ add_filter('woocommerce_rest_prepare_product_object', 'genere_prix_maximal_produ
* Retire la propagande commerciale de WooCommerce du menu.
*/
function remove_payments_ad_tab(): void {
remove_menu_page('admin.php?page=wc-settings&tab=checkout');
remove_menu_page('admin.php?page=wc-settings&tab=checkout');
}
add_action('add_meta_boxes', 'desactive_champs_admin_images_produit_woocommerce', 40);

View file

@ -10,8 +10,8 @@ declare(strict_types=1);
* Génère la balise `<img>` d'un Média attaché à un Produit selon son ID.
*/
function genere_balise_img(int $id_image): string {
return wp_get_attachment_image(
attachment_id: $id_image,
size: 'full',
);
return wp_get_attachment_image(
attachment_id: $id_image,
size: 'full'
);
}

View file

@ -10,31 +10,31 @@ declare(strict_types=1);
* Enregistre la Taxonomie « Collection ».
*/
function enregistre_taxonomie_collection(): void {
$labels = [
'add_new_item' => __('Add New Collection'),
'all_items' => __('All Collections'),
'edit_item' => __('Edit Collection'),
'menu_name' => __('Collections'),
'name' => __('Collections'),
'new_item_name' => __('New Collection Name'),
'search_items' => __('Search Collections'),
'singular_name' => __('Collection'),
'update_item' => __('Update Collection'),
];
$args = [
'description' => __('An ensemble of pieces thematically or chronologically grouped together.'),
'hierarchical' => false,
'labels' => $labels,
'publicly_queryable' => false,
'query_var' => true,
'rewrite' => ['slug' => 'collection'],
'show_admin_column' => true,
'show_in_menu' => true,
'show_in_quick_edit' => true,
'show_ui' => true,
];
$labels = [
'add_new_item' => __('Add New Collection'),
'all_items' => __('All Collections'),
'edit_item' => __('Edit Collection'),
'menu_name' => __('Collections'),
'name' => __('Collections'),
'new_item_name' => __('New Collection Name'),
'search_items' => __('Search Collections'),
'singular_name' => __('Collection'),
'update_item' => __('Update Collection')
];
$args = [
'description' => __('An ensemble of pieces thematically or chronologically grouped together.'),
'hierarchical' => false,
'labels' => $labels,
'publicly_queryable' => false,
'query_var' => true,
'rewrite' => ['slug' => 'collection'],
'show_admin_column' => true,
'show_in_menu' => true,
'show_in_quick_edit' => true,
'show_ui' => true
];
register_taxonomy('collection', ['product'], $args);
register_taxonomy('collection', ['product'], $args);
}
add_action('init', 'enregistre_taxonomie_collection');

View file

@ -1,14 +1,15 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
/**
* Fonctions pour le traitement d'informations.
*/
use function Crell\fp\pipe;
use HaikuAtelier\Data\Attribute;
use HaikuAtelier\Data\Product;
use WC_Product;
use function Crell\fp\pipe;
// Page Shop
@ -20,7 +21,8 @@ use WC_Product;
*
* @return string TODO
*/
function genere_balise_img_multiformats($id, bool $lazy = false): string {
function genere_balise_img_multiformats($id, bool $lazy = false): string
{
$int_id = (int) $id;
if (-1 === $id) {
@ -43,29 +45,24 @@ function genere_balise_img_multiformats($id, bool $lazy = false): string {
array: $tableau,
callback: static fn($chemin_format): bool => false !== $chemin_format,
),
static fn($tableau): array => array_map(
array: $tableau,
callback: static fn($chemin_format): array => [
'format' => pathinfo((string) $chemin_format)['extension'],
'taille' => filesize($chemin_format),
'url' => pathinfo($url)['dirname']
. '/'
. pathinfo($url)['filename']
. '.'
. pathinfo((string) $chemin_format)['extension'],
],
),
);
usort(
array: $formats,
callback: static fn($a, $b): int => $a['taille'] <=> $b['taille'],
static fn($tableau): array => array_map(array: $tableau, callback: static fn($chemin_format): array => [
'format' => pathinfo((string) $chemin_format)['extension'],
'taille' => filesize($chemin_format),
'url' =>
pathinfo($url)['dirname']
. '/'
. pathinfo($url)['filename']
. '.'
. pathinfo((string) $chemin_format)['extension'],
]),
);
usort(array: $formats, callback: static fn($a, $b): int => $a['taille'] <=> $b['taille']);
// Construis les balises <source> avec les formats valides
$sources = '';
foreach ($formats as $format) {
$height = $dimensions[0] ?? '';
$width = $dimensions[1] ?? '';
$height = $dimensions[0];
$width = $dimensions[1];
$sources .= "<source height='{$height}' srcset='{$format['url']}' type='image/{$format['format']}' width='{$width}' />\n";
}
@ -89,7 +86,8 @@ function genere_balise_img_multiformats($id, bool $lazy = false): string {
/**
* TODO.
*/
function tri_variations_par_prix_descendant(WC_Product $a, WC_Product $b): int {
function tri_variations_par_prix_descendant(WC_Product $a, WC_Product $b): int
{
return $b->get_price() <=> $a->get_price();
}
@ -99,16 +97,14 @@ function tri_variations_par_prix_descendant(WC_Product $a, WC_Product $b): int {
*
* @return mixed un tableau avec uniquement les informations pour la Grille de Produits
*/
function recupere_informations_produit_shop(WC_Product $produit): mixed {
function recupere_informations_produit_shop(WC_Product $produit): mixed
{
/** @var int $prix_maximal Le prix maximal du Produit. */
$prix_maximal = pipe(
// Récupère les Variations
$produit->get_children(),
// Récupère les informations de chaque Variation
static fn($enfants): array => array_map(
callback: wc_get_product(...),
array: $enfants,
),
static fn($enfants): array => array_map(callback: wc_get_product(...), array: $enfants),
// Trie les Variations par prix descendant
static fn($variations): array => array_map(
callback: static fn($variation) => $variation->get_price(),
@ -152,7 +148,8 @@ function recupere_informations_produit_shop(WC_Product $produit): mixed {
/**
* Retourne un tableau associatif des informations affichées sur la page Produit depuis les données brutes d'un Produit.
*/
function recupere_informations_produit_page_produit(WC_Product $product): mixed {
function recupere_informations_produit_page_produit(WC_Product $product): mixed
{
/** @var list<Attribute> */
$attributs = Product::get_attributes_for_product($product);
@ -204,7 +201,8 @@ function recupere_informations_produit_page_produit(WC_Product $product): mixed
*
* Pour faciliter l'usage avec `array_map`, utilise une fonction avec curryfication.
*/
function recupere_produits_meme_collection(string $slug_collection): mixed {
function recupere_produits_meme_collection(string $slug_collection): mixed
{
// @param int $id_produit
return static fn($id_produit) => wc_get_products([
'exclude' => [$id_produit],
@ -218,7 +216,8 @@ function recupere_produits_meme_collection(string $slug_collection): mixed {
// Page Panier
function recupere_et_formate_attributs_produit(mixed $attributs_produit): mixed {
function recupere_et_formate_attributs_produit(mixed $attributs_produit): mixed
{
return [
'taille' => ['nom' => 'Size', 'valeur' => $attributs_produit['pa_size'] ?? false],
'pierre' => ['nom' => 'Stone', 'valeur' => $attributs_produit['pa_stone'] ?? false],

View file

@ -1,4 +1,6 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
namespace HaikuAtelier\WP;
@ -8,28 +10,28 @@ use function is_array;
use function is_string;
final readonly class HaikuProduct {
/**
* @return list<string>
*/
public static function get_left_column_photos(int $post_id): array {
/** @var list<string> */
return Post::get_post_meta_array($post_id, '_photos_colonne_gauche|||0|value')->unwrapOr([])
|> (static fn(array $meta) => Arr::where($meta, static fn($meta): bool => is_string($meta)))
|> (static fn(array $array) => Arr::map($array, genere_balise_img_multiformats(...)));
/**
* @return list<string>
*/
public static function get_left_column_photos(int $post_id): array {
/** @var list<string> */
return Post::get_post_meta_array($post_id, '_photos_colonne_gauche|||0|value')->unwrapOr([])
|> (static fn(array $meta) => Arr::where($meta, static fn($meta): bool => is_string($meta)))
|> (static fn(array $array) => Arr::map($array, genere_balise_img_multiformats(...)));
}
/**
* @return list<string>
*/
public static function get_right_column_photos(int $post_id): array {
$meta = carbon_get_post_meta($post_id, 'photos_colonne_droite');
if (is_array($meta)) {
/** @var list<string> */
return Arr::where($meta, static fn($meta): bool => is_string($meta))
|> (static fn(array $array) => Arr::map($array, genere_balise_img_multiformats(...)));
}
/**
* @return list<string>
*/
public static function get_right_column_photos(int $post_id): array {
$meta = carbon_get_post_meta($post_id, 'photos_colonne_droite');
if (is_array($meta)) {
/** @var list<string> */
return Arr::where($meta, static fn($meta): bool => is_string($meta))
|> (static fn(array $array) => Arr::map($array, genere_balise_img_multiformats(...)));
}
return [];
}
return [];
}
}

View file

@ -1,55 +1,57 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
namespace HaikuAtelier\WP;
use Psl\Option;
use WP_Error;
use WP_Term;
use function is_array;
use function Psl\Option\none;
use function Psl\Option\some;
use WP_Error;
use WP_Term;
use function is_array;
final readonly class Post {
/**
* @return Option\Option<mixed>
*/
public static function get_post_meta(int $post_id, string $key): Option\Option {
/** @var false|mixed|string */
$value = get_post_meta($post_id, $key, true);
/**
* @return Option\Option<mixed>
*/
public static function get_post_meta(int $post_id, string $key): Option\Option {
/** @var false|mixed|string */
$value = get_post_meta($post_id, $key, true);
if ($value === false) {
return none();
}
return some($value);
if ($value === false) {
return none();
}
/**
* @return Option\Option<array<mixed>>
*/
public static function get_post_meta_array(int $post_id, string $key): Option\Option {
/** @var array<mixed>|false */
$value = get_post_meta($post_id, $key, false);
return some($value);
}
if (is_array($value)) {
return some($value);
}
/**
* @return Option\Option<array<mixed>>
*/
public static function get_post_meta_array(int $post_id, string $key): Option\Option {
/** @var array<mixed>|false */
$value = get_post_meta($post_id, $key, false);
return none();
if (is_array($value)) {
return some($value);
}
/**
* @return Option\Option<array<mixed>>
*/
public static function get_terms(int $post_id, string $taxonomy_name): Option\Option {
/** @var false|list<WP_Term>|WP_Error */
$terms = get_the_terms($post_id, $taxonomy_name);
return none();
}
if (is_array($terms)) {
return some($terms);
}
/**
* @return Option\Option<array<mixed>>
*/
public static function get_terms(int $post_id, string $taxonomy_name): Option\Option {
/** @var false|list<WP_Term>|WP_Error */
$terms = get_the_terms($post_id, $taxonomy_name);
return none();
if (is_array($terms)) {
return some($terms);
}
return none();
}
}

View file

@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace HaikuAtelier\WP;
use Exception;
use function is_bool;
final readonly class Resource {
public static function enqueue_script_module_file(string $path, string $id): void {
$file_uri = get_template_directory_uri() . $path;
$file_path = get_template_directory() . $path;
$file_mtime = filemtime($file_path);
if (is_bool($file_mtime)) {
throw new Exception("Could not get modification time of file: {$file_uri} ");
}
$version = (string) $file_mtime;
wp_enqueue_script_module(
id: $id,
src: $file_uri,
deps: [],
version: $version
);
}
public static function enqueue_style_file(string $path, string $handle): void {
$file_uri = get_template_directory_uri() . $path;
$file_path = get_template_directory() . $path;
$file_mtime = filemtime($file_path);
if (is_bool($file_mtime)) {
throw new Exception("Could not get modification time of file: {$file_uri} ");
}
$ver = (string) $file_mtime;
wp_enqueue_style(
handle: $handle,
src: $file_uri,
deps: [],
ver: $ver,
media: 'all'
);
}
}

View file

@ -1,26 +1,28 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
namespace HaikuAtelier\WP;
use Psl\Option;
use function Psl\Option\none;
use function Psl\Option\some;
use WP_Term;
use function is_array;
use function Psl\Option\none;
use function Psl\Option\some;
final readonly class Term {
/**
* @return Option\Option<list<WP_Term>>
*/
public static function get_terms(int $post_id, string $taxonomy_name): Option\Option {
$terms = get_the_terms($post_id, $taxonomy_name);
/**
* @return Option\Option<list<WP_Term>>
*/
public static function get_terms(int $post_id, string $taxonomy_name): Option\Option {
$terms = get_the_terms($post_id, $taxonomy_name);
if (is_array($terms)) {
/** @var Option\Option<list<WP_Term>> */
return some($terms);
}
return none();
if (is_array($terms)) {
/** @var Option\Option<list<WP_Term>> */
return some($terms);
}
return none();
}
}

View file

@ -2,7 +2,7 @@
:root {
/* Couleurs */
--couleur-blanc: #fff;
--couleur-blanc: #ffffff;
--couleur-blanc-fond: rgb(255 255 255 / 90%);
--couleur-gris: #eceaeb;
--couleur-gris-fonce: #808080;

View file

@ -7,15 +7,15 @@
html {
font: 1rem / var(--hauteur-ligne-classique) Lato;
font-optical-sizing: auto;
font-kerning: normal;
font-variant-ligatures: common-ligatures no-discretionary-ligatures no-historical-ligatures
contextual;
-webkit-font-smoothing: antialiased; /* 2 */
font-kerning: normal;
color: var(--couleur-noir);
text-decoration-skip-ink: auto;
text-size-adjust: none; /* 2 */
text-rendering: geometricprecision; /* 3 */
letter-spacing: var(--espacement-inter-lettres-etendu-s);
-webkit-font-smoothing: antialiased; /* 2 */
}
strong {

View file

@ -132,9 +132,9 @@
}
a {
text-transform: lowercase;
padding-block: var(--espace-2xs);
padding-inline: var(--espace-s);
text-transform: lowercase;
&.lien-compte {
border-color: transparent;
@ -153,6 +153,7 @@
.bouton-menu-mobile {
--hauteur-bouton-menu: 22px;
display: none;
align-content: center;

View file

@ -49,7 +49,6 @@
margin: auto;
visibility: visible;
opacity: 1;
transition: 1s opacity ease-in-out, 1s visibility ease-in-out;
mask-image: linear-gradient(
var(--mask-direction, to right),
hsl(0deg 0% 0% / 0%),
@ -57,6 +56,7 @@
hsl(0deg 0% 0% / 100%) 80%,
hsl(0deg 0% 0% / 0%)
);
transition: 1s opacity ease-in-out, 1s visibility ease-in-out;
&[hidden] {
display: grid !important;

View file

@ -35,16 +35,13 @@ const creeTransportFetch = (options): Transport => {
...options.fetchOptions,
};
return pipe(
await fetch(options.url, optionsRequete),
(reponse: Response) => ({
headers: {
[ENTETE_GLITCHTIP_RATE_LIMITS]: reponse.headers.get(ENTETE_GLITCHTIP_RATE_LIMITS),
[ENTETE_GLITCHTIP_RETRY_AFTER]: reponse.headers.get(ENTETE_GLITCHTIP_RETRY_AFTER),
},
statusCode: reponse.status,
}),
);
return pipe(await fetch(options.url, optionsRequete), (reponse: Response) => ({
headers: {
[ENTETE_GLITCHTIP_RATE_LIMITS]: reponse.headers.get(ENTETE_GLITCHTIP_RATE_LIMITS),
[ENTETE_GLITCHTIP_RETRY_AFTER]: reponse.headers.get(ENTETE_GLITCHTIP_RETRY_AFTER),
},
statusCode: reponse.status,
}));
};
return createTransport(options, creeRequete);

View file

@ -1,39 +0,0 @@
import { configureSync, getConsoleSink, getLogger } from "@logtape/logtape";
import chalk from "chalk";
import log, { type Logger } from "loglevel";
import prefix from "loglevel-plugin-prefix";
// Récupère les variables d'environnement au sein d'un objet.
const environment = import.meta.env;
const colors = {
DEBUG: chalk.cyan,
ERROR: chalk.red,
INFO: chalk.blue,
TRACE: chalk.magenta,
WARN: chalk.yellow,
};
export const logger: Logger = log.noConflict() as Logger;
logger.enableAll(true);
logger.setDefaultLevel("DEBUG");
prefix.reg(logger);
prefix.apply(logger, {
format(level, _, timestamp) {
return `${chalk.gray(`[${timestamp}]`)} ${colors[level.toUpperCase()](level)}`;
},
});
const HAIKU_ATELIER_LOGGER = "haiku-atelier";
configureSync({
loggers: [
{
category: HAIKU_ATELIER_LOGGER,
lowestLevel: environment.VITE_MODE === "production" ? "warning" : "debug",
sinks: ["console"],
},
],
sinks: { console: getConsoleSink() },
});
export const nuLogger = getLogger(HAIKU_ATELIER_LOGGER);

View file

@ -49,12 +49,7 @@ export const lanceAnimationCycleLoading = (element: HTMLElement, delai: number):
const animation = lanceAnimationCycleTexte({
attribut: ATTRIBUT_CHARGEMENT,
element: element,
etapes: [
"Loading",
"Loading.",
"Loading..",
"Loading...",
],
etapes: ["Loading", "Loading.", "Loading..", "Loading..."],
});
animation.callback();
animation.interval = setInterval(animation.callback, delai);

View file

@ -1,12 +1,18 @@
export const forEach = <T>(fn: (_1: T) => void) => (xs: Array<T>): void => {
xs.forEach(fn);
};
export const forEach =
<T>(fn: (_1: T) => void) =>
(xs: Array<T>): void => {
xs.forEach(fn);
};
export const forEachWithIndex = <T>(fn: (_1: T, _2: number) => void) => (xs: Array<T>): void => {
xs.forEach(fn);
};
export const forEachWithIndex =
<T>(fn: (_1: T, _2: number) => void) =>
(xs: Array<T>): void => {
xs.forEach(fn);
};
export const map = <T>(fn: (_1: T) => void) => (xs: Array<T>): Array<T> => {
xs.map(fn);
return xs;
};
export const map =
<T>(fn: (_1: T) => void) =>
(xs: Array<T>): Array<T> => {
xs.map(fn);
return xs;
};

View file

@ -4,7 +4,6 @@ import { Either, identity, Left, Right } from "purify-ts";
import type { ParentElement } from "./types/dom.d.ts";
import { ATTRIBUT_CHARGEMENT, ATTRIBUT_DESACTIVE } from "../constantes/dom.ts";
import { logger } from "../journalisation.ts";
import { lanceAnimationCycleLoading } from "./animations.ts";
import {
BadRequestError,
@ -19,24 +18,28 @@ import {
} from "./erreurs";
export const recupereElementAvecSelecteur =
(parent: ParentElement) => <E extends Element = Element>(selecteur: string): Either<SyntaxError, E> =>
(parent: ParentElement) =>
<E extends Element = Element>(selecteur: string): Either<SyntaxError, E> =>
Either
// Retourne une SyntaxError dans un Left si le sélecteur est invalide
.encase(() => parent.querySelector<E>(selecteur))
// Transforme le Left en une erreur plus sympathique
.mapLeft(_ => creeSyntaxError(ERREUR_SYNTAXE_INVALIDE(selecteur)))
.mapLeft((_) => creeSyntaxError(ERREUR_SYNTAXE_INVALIDE(selecteur)))
// Retourne une SyntaxError si l'Élément est null
.chain((e: E | null) => G.isNotNullable(e) ? Right(e) : Left(creeSyntaxError(ERREUR_DOM_INEXISTANT(selecteur))));
.chain((e: E | null) =>
G.isNotNullable(e) ? Right(e) : Left(creeSyntaxError(ERREUR_DOM_INEXISTANT(selecteur))),
);
export const getDOMElementsWithSelector =
(parent: ParentElement) => <E extends Element = Element>(selecteur: string): Either<SyntaxError, Array<E>> =>
(parent: ParentElement) =>
<E extends Element = Element>(selecteur: string): Either<SyntaxError, Array<E>> =>
Either
// Retourne une SyntaxError dans un Left si le sélecteur est invalide
.encase(() => pipe(parent.querySelectorAll<E>(selecteur), Array.from<E>))
// Transforme le Left en une erreur plus sympathique
.mapLeft(_ => creeSyntaxError(ERREUR_SYNTAXE_INVALIDE(selecteur)))
.mapLeft((_) => creeSyntaxError(ERREUR_SYNTAXE_INVALIDE(selecteur)))
// Retourne une SyntaxError si le tableau est vide
.chain((e: Array<E>) => A.isEmpty(e) ? Left(creeSyntaxError(ERREUR_DOM_INEXISTANT(selecteur))) : Right(e));
.chain((e: Array<E>) => (A.isEmpty(e) ? Left(creeSyntaxError(ERREUR_DOM_INEXISTANT(selecteur))) : Right(e)));
export const recupereElementOuLeve = <E extends Element = Element>(elementOuErreur: Either<SyntaxError, E>): E =>
elementOuErreur.caseOf({
@ -52,18 +55,20 @@ export const recupereElementsOuLeve = <E extends Element = Element>(
Right: identity,
});
export const majElementInnerHtml = <T extends HTMLElement>(element: T) => (innerHtml: string) => {
element.innerHTML = innerHtml;
return element;
};
export const majElementInnerHtml =
<T extends HTMLElement>(element: T) =>
(innerHtml: string) => {
element.innerHTML = innerHtml;
return element;
};
// Merci facon (https://github.com/terkelg/facon)
export const html = (strings: TemplateStringsArray, ...args: Array<string>) =>
pipe(
document.createElement("template"),
template =>
(template) =>
majElementInnerHtml(template)(args.reduce((prev, value, i) => prev + value + strings[i + 1], strings[0])),
template => template.content,
(template) => template.content,
);
/**
@ -90,9 +95,8 @@ export const recupereElementsDocumentEither: <E extends Element = Element>(
selecteur: string,
) => Either<SyntaxError, Array<E>> = getDOMElementsWithSelector(document);
export const recupereElementDocumentEither: <E extends Element = Element>(
selecteur: string,
) => Either<SyntaxError, E> = recupereElementAvecSelecteur(document);
export const recupereElementDocumentEither: <E extends Element = Element>(selecteur: string) => Either<SyntaxError, E> =
recupereElementAvecSelecteur(document);
/**
* Fonction utilitaire pour récupérer un Élément selon un sélecteur au sein du Document.
@ -102,13 +106,12 @@ export const recupereElementDocumentEither: <E extends Element = Element>(
* @returns Un Élément.
*/
export const mustGetEleInDocument = <E extends Element = Element>(selecteur: string): E =>
pipe(
recupereElementDocumentEither<E>(selecteur),
recupereElementOuLeve,
);
pipe(recupereElementDocumentEither<E>(selecteur), recupereElementOuLeve);
export const mustGetEleInParent = (parent: ParentElement) => <E extends HTMLElement>(selector: string) =>
pipe(recupereElementAvecSelecteur(parent)<E>(selector), recupereElementOuLeve);
export const mustGetEleInParent =
(parent: ParentElement) =>
<E extends HTMLElement>(selector: string) =>
pipe(recupereElementAvecSelecteur(parent)<E>(selector), recupereElementOuLeve);
/**
* Fonction utilitaire pour récupérer des Éléments selon un sélecteur au sein du Document.
@ -118,13 +121,9 @@ export const mustGetEleInParent = (parent: ParentElement) => <E extends HTMLElem
* @returns Un tableau d'Éléments.
*/
export const mustGetElesInDocument = <E extends Element = Element>(selecteur: string): Array<E> =>
pipe(
recupereElementsDocumentEither<E>(selecteur),
recupereElementsOuLeve,
);
pipe(recupereElementsDocumentEither<E>(selecteur), recupereElementsOuLeve);
export const setButtonLoadingState = (button: HTMLButtonElement, isLoading: boolean): void => {
logger.debug("majEtatChargementBouton", button, isLoading);
if (isLoading) {
// Désactive le Bouton pour empêcher des requêtes concurrentes
button.setAttribute(ATTRIBUT_DESACTIVE, "");
@ -139,13 +138,11 @@ export const setButtonLoadingState = (button: HTMLButtonElement, isLoading: bool
};
export const estErreurHttp = (erreur: unknown) =>
erreur instanceof BadRequestError
|| erreur instanceof ForbiddenError
|| erreur instanceof NotFoundError
|| erreur instanceof ServerError
|| erreur instanceof UnauthorizedError;
erreur instanceof BadRequestError ||
erreur instanceof ForbiddenError ||
erreur instanceof NotFoundError ||
erreur instanceof ServerError ||
erreur instanceof UnauthorizedError;
export const estErreurFetch = (erreur: unknown) =>
erreur instanceof DOMException
|| erreur instanceof TypeError
|| erreur instanceof Error;
erreur instanceof DOMException || erreur instanceof TypeError || erreur instanceof Error;

View file

@ -1,7 +1,9 @@
import type { Constructor } from "./types/classes";
const estElement = <T extends HTMLElement>(typeElement: Constructor<T>) => (element: unknown): element is T =>
element instanceof typeElement;
const estElement =
<T extends HTMLElement>(typeElement: Constructor<T>) =>
(element: unknown): element is T =>
element instanceof typeElement;
export const estHTMLSelectElement = estElement<HTMLSelectElement>(HTMLSelectElement);

View file

@ -55,29 +55,29 @@ export const emetMessageMajContenuPanier = (args: MessageMajContenuPanierDonnees
* @return void
*/
export const emetUniqueMessageBroadcastChannel = <M>(nomCanal: string, message: M): void =>
pipe(new BroadcastChannel(nomCanal), canal => canalPostMessage(canal, message), canal => canal.close());
pipe(
new BroadcastChannel(nomCanal),
(canal) => canalPostMessage(canal, message),
(canal) => canal.close(),
);
// Validations
export const valideMessageMajBoutonPanier = (
evenementMessage: MessageEvent<unknown>,
): Either<ValiError<typeof MessageMajBoutonPanierSchema>, MessageMajBoutonPanier> =>
Either
.of<ValiError<typeof MessageMajBoutonPanierSchema>, MessageMajBoutonPanier>(
parse(MessageMajBoutonPanierSchema, evenementMessage.data),
)
.ifLeft(erreur => reporteErreur(erreur));
Either.of<ValiError<typeof MessageMajBoutonPanierSchema>, MessageMajBoutonPanier>(
parse(MessageMajBoutonPanierSchema, evenementMessage.data),
).ifLeft((erreur) => reporteErreur(erreur));
export const valideMessageMajContenuPanier = (
evenementMessage: MessageEvent<unknown>,
): Either<ValiError<typeof MessageMajContenuPanierSchema>, MessageMajContenuPanier> =>
Either
.of<ValiError<typeof MessageMajContenuPanierSchema>, MessageMajContenuPanier>(
parse(MessageMajContenuPanierSchema, evenementMessage.data),
)
.ifLeft(erreur => reporteErreur(erreur));
Either.of<ValiError<typeof MessageMajContenuPanierSchema>, MessageMajContenuPanier>(
parse(MessageMajContenuPanierSchema, evenementMessage.data),
).ifLeft((erreur) => reporteErreur(erreur));
// Correspondances
export const reponseEstCodeErreurWC = (reponse: SimplifiedResponse, codeErreurWC: string): boolean =>
safeSchemaParse(reponse, WCErrorSchema)
.map(v => v.body.code === codeErreurWC)
.map((v) => v.body.code === codeErreurWC)
.orDefault(false);

View file

@ -5,10 +5,10 @@ export const estEntreDeuxNombres = (nombre: number, min: number, max: number): b
export const diviseParCent = (nombre: number | string): number => Number(nombre) / 100;
export const arrondisADeuxDecimales = (nombre: number | string) => pipe(Number(nombre), n => n.toFixed(2));
export const arrondisADeuxDecimales = (nombre: number | string) => pipe(Number(nombre), (n) => n.toFixed(2));
export const arrondisAZeroOuDeuxDecimales = (nombre: number | string): string =>
pipe(Number(nombre), n => (n / Math.round(n)) === 1 ? n.toFixed(0) : n.toFixed(2));
pipe(Number(nombre), (n) => (n / Math.round(n) === 1 ? n.toFixed(0) : n.toFixed(2)));
export const inverseNombre = (nombre: number | string): number => Number(nombre) * -1;

View file

@ -4,7 +4,13 @@ import { match } from "ts-pattern";
import type { HttpCodeErrors, SimplifiedResponse } from "./types/reseau";
import { ENTETE_WC_NONCE } from "../constantes/api.ts";
import { BadRequestError, ForbiddenError, NotFoundError, ServerError, UnauthorizedError } from "./erreurs.ts";
import {
BadRequestError,
ForbiddenError,
NotFoundError,
ServerError,
UnauthorizedError,
} from "./erreurs.ts";
// Types
@ -39,115 +45,115 @@ type ArgumentsPostBackendWC = {
// fetch
export const getBackend = (args: ArgumentsGetBackendWC): Promise<Response> =>
fetch(
args.route,
{
credentials: "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
[ENTETE_WC_NONCE]: args.nonce,
// Ajoute conditionnellement l'en-tête « Authorization »
...(args.authString && { Authorization: `Basic ${args.authString}` }),
},
method: "GET",
mode: "same-origin",
signal: AbortSignal.timeout(5000),
fetch(args.route, {
credentials: "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
[ENTETE_WC_NONCE]: args.nonce,
// Ajoute conditionnellement l'en-tête « Authorization »
...(args.authString && { Authorization: `Basic ${args.authString}` }),
},
);
method: "GET",
mode: "same-origin",
signal: AbortSignal.timeout(5000),
});
export const getBackendAvecParametresUrl = (args: ArgumentsGetBackendWC): Promise<Response> =>
fetch(
`${args.route}?${args.searchParams}`,
{
credentials: "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
[ENTETE_WC_NONCE]: args.nonce,
// Ajoute conditionnellement l'en-tête « Authorization »
...(args.authString && { Authorization: `Basic ${args.authString}` }),
},
method: "GET",
mode: "same-origin",
signal: AbortSignal.timeout(5000),
export const getBackendAvecParametresUrl = (
args: ArgumentsGetBackendWC,
): Promise<Response> =>
fetch(`${args.route}?${args.searchParams}`, {
credentials: "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
[ENTETE_WC_NONCE]: args.nonce,
// Ajoute conditionnellement l'en-tête « Authorization »
...(args.authString && { Authorization: `Basic ${args.authString}` }),
},
);
method: "GET",
mode: "same-origin",
signal: AbortSignal.timeout(5000),
});
export const deleteBackend = (args: ArgumentsDeleteBackendWC): Promise<Response> =>
fetch(
args.route,
{
credentials: "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
[ENTETE_WC_NONCE]: args.nonce,
// Ajoute conditionnellement l'en-tête « Authorization »
...(args.authString && { Authorization: `Basic ${args.authString}` }),
},
method: "DELETE",
mode: "same-origin",
signal: AbortSignal.timeout(5000),
export const deleteBackend = (
args: ArgumentsDeleteBackendWC,
): Promise<Response> =>
fetch(args.route, {
credentials: "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
[ENTETE_WC_NONCE]: args.nonce,
// Ajoute conditionnellement l'en-tête « Authorization »
...(args.authString && { Authorization: `Basic ${args.authString}` }),
},
);
method: "DELETE",
mode: "same-origin",
signal: AbortSignal.timeout(5000),
});
export const postBackend = (args: ArgumentsPostBackendWC): Promise<Response> =>
fetch(
args.route,
{
body: args.corps,
fetch(args.route, {
body: args.corps,
credentials: "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
[ENTETE_WC_NONCE]: args.nonce,
// Ajoute conditionnellement l'en-tête « Authorization »
...(args.authString && { Authorization: `Basic ${args.authString}` }),
},
method: "POST",
mode: "same-origin",
signal: AbortSignal.timeout(5000),
});
export const prefilledPostBackend =
(nonce: string, authString?: string) =>
(
route: string,
body: BodyInit,
needsAuthString: boolean,
): Promise<Response> =>
fetch(route, {
body: body,
credentials: "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
[ENTETE_WC_NONCE]: args.nonce,
// Ajoute conditionnellement l'en-tête « Authorization »
...(args.authString && { Authorization: `Basic ${args.authString}` }),
[ENTETE_WC_NONCE]: nonce,
...(authString &&
needsAuthString && { Authorization: `Basic ${authString}` }),
},
method: "POST",
mode: "same-origin",
signal: AbortSignal.timeout(5000),
},
);
});
export const prefilledPostBackend =
(nonce: string, authString?: string) =>
(route: string, body: BodyInit, needsAuthString: boolean): Promise<Response> =>
fetch(
route,
{
body: body,
credentials: "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
[ENTETE_WC_NONCE]: nonce,
...(authString && needsAuthString && { Authorization: `Basic ${authString}` }),
},
method: "POST",
mode: "same-origin",
signal: AbortSignal.timeout(5000),
},
);
export const safeFetch = (f: Promise<Response>): EitherAsync<DOMException | TypeError, Response> =>
export const safeFetch = (
f: Promise<Response>,
): EitherAsync<DOMException | TypeError, Response> =>
EitherAsync<DOMException | TypeError, Response>(async () => await f);
// Réponses Simplifiées
export const newPartialResponse = async (reponse: Response): Promise<SimplifiedResponse> => {
export const newPartialResponse = async (
reponse: Response,
): Promise<SimplifiedResponse> => {
return {
body: await reponse.json(),
status: reponse.status,
};
};
export const traiteErreursBackendWooCommerce = (rs: SimplifiedResponse): HttpCodeErrors => {
export const traiteErreursBackendWooCommerce = (
rs: SimplifiedResponse,
): HttpCodeErrors => {
return match(rs)
.with({ status: 400 }, () => new BadRequestError())
.with({ status: 401 }, () => new UnauthorizedError())
.with({ status: 403 }, () => new ForbiddenError())
.with({ status: 404 }, () => new NotFoundError())
.with({ status: 500 }, () => new ServerError())
.otherwise(rs => new Error(String(rs.status)));
.otherwise((rs) => new Error(String(rs.status)));
};

View file

@ -7,5 +7,7 @@ import { Maybe } from "purify-ts";
*/
export const first = <T>(xs: Array<T>): Maybe<T> => Maybe.fromNullable(xs.at(0));
export const find = <T>(predicateFn: (_1: T) => boolean) => (xs: Array<T>): Maybe<T> =>
Maybe.fromNullable(xs.find(predicateFn));
export const find =
<T>(predicateFn: (_1: T) => boolean) =>
(xs: Array<T>): Maybe<T> =>
Maybe.fromNullable(xs.find(predicateFn));

View file

@ -52,25 +52,16 @@ export const WCStoreCartTotalsSchema = v.object({
currency_symbol: v.string(),
currency_thousand_separator: v.string(),
tax_lines: v.array(v.unknown()),
total_discount: v.pipe(
v.union([v.string(), v.number()]),
v.transform(Number),
),
total_discount: v.pipe(v.union([v.string(), v.number()]), v.transform(Number)),
total_discount_tax: v.string(),
total_fees: v.string(),
total_fees_tax: v.string(),
total_items: v.pipe(
v.union([v.string(), v.number()]),
v.transform(Number),
),
total_items: v.pipe(v.union([v.string(), v.number()]), v.transform(Number)),
total_items_tax: v.string(),
total_price: v.pipe(
v.union([v.string(), v.number()]),
v.transform(Number),
),
total_price: v.pipe(v.union([v.string(), v.number()]), v.transform(Number)),
total_shipping: v.pipe(
v.union([v.string(), v.number(), v.null()]),
v.transform(n => n ? Number(n) : 0),
v.transform((n) => (n ? Number(n) : 0)),
),
total_shipping_tax: v.union([v.string(), v.null()]),
total_tax: v.string(),

View file

@ -24,10 +24,7 @@ export const WCStoreShippingRateShippingRateSchema = v.object({
meta_data: v.array(v.unknown()),
method_id: v.string(),
name: v.string(),
price: v.pipe(
v.union([v.string(), v.number()]),
v.transform(Number),
),
price: v.pipe(v.union([v.string(), v.number()]), v.transform(Number)),
rate_id: v.string(),
selected: v.boolean(),
taxes: v.string(),

View file

@ -21,16 +21,20 @@ export const WCAddressErrorSchema = v.object({
code: v.literal("rest_invalid_param"),
data: v.object({
details: v.object({
billing: v.optional(v.object({
code: v.string(),
data: v.union([v.null(), v.string()]),
message: v.string(),
})),
shipping: v.optional(v.object({
code: v.string(),
data: v.union([v.null(), v.string()]),
message: v.string(),
})),
billing: v.optional(
v.object({
code: v.string(),
data: v.union([v.null(), v.string()]),
message: v.string(),
}),
),
shipping: v.optional(
v.object({
code: v.string(),
data: v.union([v.null(), v.string()]),
message: v.string(),
}),
),
}),
params: v.object({
billing: v.optional(v.string()),

View file

@ -60,25 +60,29 @@ export const WCProductSchema = v.object({
}),
attributes: v.array(v.unknown()),
average_rating: v.string(),
categories: v.array(v.object({
id: v.number(),
link: v.string(),
name: v.string(),
slug: v.string(),
})),
categories: v.array(
v.object({
id: v.number(),
link: v.string(),
name: v.string(),
slug: v.string(),
}),
),
description: v.string(),
extensions: v.unknown(),
has_options: v.boolean(),
id: v.number(),
images: v.array(v.object({
alt: v.string(),
id: v.number(),
name: v.string(),
sizes: v.string(),
src: v.string(),
srcset: v.string(),
thumbnail: v.string(),
})),
images: v.array(
v.object({
alt: v.string(),
id: v.number(),
name: v.string(),
sizes: v.string(),
src: v.string(),
srcset: v.string(),
thumbnail: v.string(),
}),
),
is_in_stock: v.boolean(),
is_on_backorder: v.boolean(),
is_purchasable: v.boolean(),
@ -109,13 +113,17 @@ export const WCProductSchema = v.object({
tags: v.array(v.string()),
type: v.string(),
variation: v.unknown(),
variations: v.array(v.object({
attributes: v.array(v.object({
name: v.string(),
value: v.string(),
})),
id: v.number(),
})),
variations: v.array(
v.object({
attributes: v.array(
v.object({
name: v.string(),
value: v.string(),
}),
),
id: v.number(),
}),
),
});
export const WCProductsSchema = v.array(WCProductSchema);

View file

@ -7,10 +7,7 @@ import { ErreurEntreeInexistante, type NonExistingKeyError } from "./erreurs.ts"
import { safeSchemaParse, safeSchemaParseCurried } from "./validation.ts";
export type GetSessionStorage<S extends GenericSchema> = Either<ErreursGetSessionStorage<S>, InferOutput<S>>;
type ErreursGetSessionStorage<S extends GenericSchema> =
| NonExistingKeyError
| SyntaxError
| ValiError<S>;
type ErreursGetSessionStorage<S extends GenericSchema> = NonExistingKeyError | SyntaxError | ValiError<S>;
/**
* Récupère une entrée dans le Stockage Local (`sessionStorage`) sous forme d'`Either`.
@ -20,9 +17,9 @@ type ErreursGetSessionStorage<S extends GenericSchema> =
* valeur de l'entrée sinon (`Right`).
*/
export const eitherGetSessionStorage = (cle: string): Either<NonExistingKeyError, string> =>
Maybe
.fromNullable(sessionStorage.getItem(cle))
.toEither(ErreurEntreeInexistante(`Clé ${cle} absente dans le stockage de session.`));
Maybe.fromNullable(sessionStorage.getItem(cle)).toEither(
ErreurEntreeInexistante(`Clé ${cle} absente dans le stockage de session.`),
);
export const eitherSetSessionStorage = <V>(cle: string, valeur: V): Either<DOMException, V> =>
Either.encase<DOMException, V>(() => {
@ -32,11 +29,9 @@ export const eitherSetSessionStorage = <V>(cle: string, valeur: V): Either<DOMEx
});
export const getSessionStorageByKey = <S extends GenericSchema>(key: string, schema: S): GetSessionStorage<S> =>
eitherGetSessionStorage(key)
.chain(safeJsonParse)
.chain(safeSchemaParseCurried(schema));
eitherGetSessionStorage(key).chain(safeJsonParse).chain(safeSchemaParseCurried(schema));
export const setSessionStorageByKey =
<S extends GenericSchema>(key: string, schema: S) =>
(value: unknown): Either<DOMException | ValiError<S>, InferOutput<S>> =>
safeSchemaParse(value, schema).chain(v => eitherSetSessionStorage(key, v));
safeSchemaParse(value, schema).chain((v) => eitherSetSessionStorage(key, v));

View file

@ -3,12 +3,7 @@ import type { InferOutput } from "valibot";
import type { BadRequestError, NotFoundError, ServerError, UnauthorizedError, UnknownError } from "../../erreurs.ts";
import type { WCAddressErrorSchema, WCErrorBodySchema, WCErrorSchema } from "../../schemas/api/erreurs.ts";
export type APIFetchErrors =
| BadRequestError
| NotFoundError
| ServerError
| UnauthorizedError
| UnknownError;
export type APIFetchErrors = BadRequestError | NotFoundError | ServerError | UnauthorizedError | UnknownError;
export type WCAddressError = InferOutput<typeof WCAddressErrorSchema>;
export type WCError = InferOutput<typeof WCErrorSchema>;

View file

@ -1 +1 @@
export type Constructor<T> = new(...args: Array<unknown>) => T;
export type Constructor<T> = new (...args: Array<unknown>) => T;

View file

@ -2,13 +2,7 @@ import type { BadRequestError, ForbiddenError, NotFoundError, ServerError, Unaut
export type FetchErrors = DOMException | Error | TypeError;
export type HttpCodeErrors =
| BadRequestError
| Error
| ForbiddenError
| NotFoundError
| ServerError
| UnauthorizedError;
export type HttpCodeErrors = BadRequestError | Error | ForbiddenError | NotFoundError | ServerError | UnauthorizedError;
export interface SimplifiedResponse {
body: unknown;

View file

@ -6,9 +6,9 @@ import { CleNonTrouveError } from "./erreurs";
/**
* TODO
*/
export const propEither = <T, K extends keyof T>(cle: K) => (donnees: T): Either<CleNonTrouveError, T[K]> =>
Maybe
.fromNullable(D.getUnsafe(donnees, cle))
.toEither(
export const propEither =
<T, K extends keyof T>(cle: K) =>
(donnees: T): Either<CleNonTrouveError, T[K]> =>
Maybe.fromNullable(D.getUnsafe(donnees, cle)).toEither(
new CleNonTrouveError(`La clé « ${String(cle)} » n'a pas été trouvé dans l'objet.`),
);

View file

@ -11,5 +11,6 @@ export const safeSchemaParse = <Schema extends GenericSchema>(
): Either<ValiError<Schema>, InferOutput<Schema>> => Either.encase(() => parse(schema, valeur));
export const safeSchemaParseCurried =
<S extends GenericSchema>(schema: S) => (valeur: unknown): Either<ValiError<S>, InferOutput<S>> =>
<S extends GenericSchema>(schema: S) =>
(valeur: unknown): Either<ValiError<S>, InferOutput<S>> =>
Either.encase(() => parse(schema, valeur));

View file

@ -40,7 +40,6 @@ import { WCStoreCartUpdateCustomerArgsSchema } from "../lib/schemas/api/cart-upd
import { estWCAddressError } from "../lib/schemas/api/erreurs";
import { WCV3OrdersArgsSchema, WCV3OrderSchema } from "../lib/schemas/api/v3/orders";
import { safeSchemaParse } from "../lib/validation";
import { logger } from "../journalisation.ts";
import { E } from "./scripts-page-panier-elements";
import { getShippingRatesLS } from "./scripts-page-panier-local-storage";
@ -59,24 +58,21 @@ const postBackend = prefilledPostBackend(ETATS_PAGE.nonce, ETATS_PAGE.authString
* @returns void
*/
export const initCartFormEventEmitters = (): void => {
logger.debug("ADRESSES", "initCartFormEventEmitters");
E.FORMULAIRE_PANIER.addEventListener("change", (): void => {
logger.info("ADRESSES", "Changement du Formulaire Panier");
Maybe
.fromFalsy(E.FORMULAIRE_PANIER.checkValidity())
.ifJust((): boolean => window.dispatchEvent(ADRESSES_MAJ_EVENT));
Maybe.fromFalsy(E.FORMULAIRE_PANIER.checkValidity()).ifJust((): boolean =>
window.dispatchEvent(ADRESSES_MAJ_EVENT),
);
});
};
export const getAddressesFromForm = (formFields: Record<string, string>, areAddressesMerged: boolean): Addresses => {
logger.debug("ADDRESSES", "getAddressesFromForm");
return {
billing_address: {
address_1: formFields["facturation-adresse"] ?? formFields["livraison-adresse"] ?? "",
address_2: "",
city: formFields["facturation-ville"] ?? formFields["livraison-ville"] ?? "",
company: "",
country: areAddressesMerged ? formFields["facturation-pays"] ?? "" : formFields["livraison-pays"] ?? "",
country: areAddressesMerged ? (formFields["facturation-pays"] ?? "") : (formFields["livraison-pays"] ?? ""),
email: formFields["facturation-email"] ?? formFields["livraison-email"] ?? "",
first_name: formFields["facturation-prenom"] ?? formFields["livraison-prenom"] ?? "",
last_name: formFields["facturation-nom"] ?? formFields["livraison-nom"] ?? "",
@ -100,16 +96,14 @@ export const getAddressesFromForm = (formFields: Record<string, string>, areAddr
};
export const initShippingCalculationButton = (): void => {
logger.debug("ADRESSES", "initShippingCalculationButton");
// Déclenche au clic sur le Bouton de soumission du Formulaire la requête pour le calcul des frais de livraison
E.BOUTON_ACTIONS_FORMULAIRE.addEventListener("click", (event: Event): void => {
logger.info("ADRESSES", "Demande de calcul des frais de livraison de la commande");
Maybe
// Ne fais rien si le Formulaire n'est pas valide
.fromFalsy(E.FORMULAIRE_PANIER.checkValidity())
// Ne fais rien si la livraison a déjà été validée
.chainNullable((): boolean | undefined =>
E.BOUTON_ACTIONS_FORMULAIRE.hasAttribute(ATTRIBUT_LIVRAISON_VALIDEE) ? undefined : true
E.BOUTON_ACTIONS_FORMULAIRE.hasAttribute(ATTRIBUT_LIVRAISON_VALIDEE) ? undefined : true,
)
.ifJust((): void => {
event.preventDefault();
@ -117,40 +111,36 @@ export const initShippingCalculationButton = (): void => {
/** Les données du Formulaire transformées pour la requête vers le Backend. */
const formArgs: WCStoreCartUpdateCustomerArgs = pipe(
Object.fromEntries(new FormData(E.FORMULAIRE_PANIER)) as Record<string, string>,
fields => dictMap(fields, stringTrim),
fields => getAddressesFromForm(fields, E.BOUTON_SEPARATION_ADRESSES.checked),
(fields) => dictMap(fields, stringTrim),
(fields) => getAddressesFromForm(fields, E.BOUTON_SEPARATION_ADRESSES.checked),
);
logger.debug("ADRESSES", "initShippingCalculationButton", "formArgs", formArgs);
// Réalise la requête et traite sa réponse
void EitherAsync
.liftEither(safeSchemaParse(formArgs, WCStoreCartUpdateCustomerArgsSchema))
void EitherAsync.liftEither(safeSchemaParse(formArgs, WCStoreCartUpdateCustomerArgsSchema))
// Désactive le Bouton pour empêcher des requêtes concurrentes
.ifRight((): void => setButtonLoadingState(E.BOUTON_ACTIONS_FORMULAIRE, true))
.chain((args: WCStoreCartUpdateCustomerArgs) => {
logger.debug("ADRESSES", "args", args);
return safeFetch(postBackend(ROUTE_API_MAJ_CLIENT, JSON.stringify(args), false));
})
.chain((rs: Response) => {
logger.debug("ADRESSES", "initShippingCalculationButton", "rs", rs);
return EitherAsync<ErreurAdresseInvalide | HttpCodeErrors, unknown>(async ({ throwE }): Promise<unknown> =>
match(await newPartialResponse(rs))
.with({ status: 200 }, (rs): unknown => rs.body)
.with(
{ body: P.when(body => estWCAddressError(body)), status: 400 },
(rs): never => throwE(new ErreurAdresseInvalide(rs.body.data.params)),
)
.otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs)))
return EitherAsync<ErreurAdresseInvalide | HttpCodeErrors, unknown>(
async ({ throwE }): Promise<unknown> =>
match(await newPartialResponse(rs))
.with({ status: 200 }, (rs): unknown => rs.body)
.with(
{
body: P.when((body) => estWCAddressError(body)),
status: 400,
},
(rs): never => throwE(new ErreurAdresseInvalide(rs.body.data.params)),
)
.otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs))),
);
})
.chain((b: unknown) => EitherAsync.liftEither(safeSchemaParse(b, WCStoreCartSchema)))
.ifRight((cart: WCStoreCart): void => {
logger.debug("ADRESSES", "initShippingCalculationButton", "cart", cart);
/** La méthode de livraison sélectionnée dans le SessionStorage */
const oldSelectedRateLS = getShippingRatesLS()
.chain(find(sr => sr.selected))
.ifJust(sr => logger.debug("ADRESSES", "initShippingCalculationButton", "oldSelectedRateLS", sr));
const oldSelectedRateLS = getShippingRatesLS().chain(find((sr) => sr.selected));
/* Les méthodes de livraison mises à jour avec le nouveau choix de l'Utilisateur. */
const updatedRates = first(cart.shipping_rates)
@ -159,7 +149,7 @@ export const initShippingCalculationButton = (): void => {
srs.map((sr: WCStoreShippingRateShippingRate, index: number) => {
// Sélectionne la nouvelle méthode demandée OU la première si le SessionStorage n'a pas été défini
oldSelectedRateLS.caseOf({
Just: sm => {
Just: (sm) => {
sr.selected = sr.method_id === sm.method_id;
},
Nothing: () => {
@ -171,24 +161,24 @@ export const initShippingCalculationButton = (): void => {
sr.price = diviseParCent(sr.price);
return sr;
})
}),
)
.orDefault([]);
logger.debug("ADRESSES", "initShippingCalculationButton", "updatedRates", updatedRates);
// Met à jour les Méthodes de livraison dans le SessionStorage et le DOM
window.dispatchEvent(createUpdatedShippingRatesEvent(updatedRates, true));
// Met à jour les Totaux
const newShippingPrice = updatedRates.find(m => m.selected)?.price ?? 0;
const newShippingPrice = updatedRates.find((m) => m.selected)?.price ?? 0;
const newTotals = {
...cart.totals,
total_discount: diviseParCent(cart.totals.total_discount),
total_items: diviseParCent(cart.totals.total_items),
total_price: diviseParCent(cart.totals.total_items) - diviseParCent(cart.totals.total_discount)
+ newShippingPrice,
total_price:
diviseParCent(cart.totals.total_items) - diviseParCent(cart.totals.total_discount) + newShippingPrice,
total_shipping: newShippingPrice,
};
logger.debug("ADRESSES", "initShippingCalculationButton", "newTotals", newTotals);
window.dispatchEvent(createUpdatedTotalsEvent(newTotals));
// Réinitialise le Message affiché à l'Utilisateur
@ -197,43 +187,45 @@ export const initShippingCalculationButton = (): void => {
E.BOUTON_ACTIONS_FORMULAIRE.textContent = "Check-out";
E.BOUTON_ACTIONS_FORMULAIRE.setAttribute(ATTRIBUT_LIVRAISON_VALIDEE, "");
})
.ifLeft(
(err: ErreurAdresseInvalide | FetchErrors | HttpCodeErrors | ValiError<AnySchema>): void => {
match(err)
.with(P.instanceOf(ValiError), (e: ValiError<AnySchema>): void => {
reporteEtJournaliseErreur(e);
console.error(e.issues);
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(ErreurAdresseInvalide), (e: ErreurAdresseInvalide): void => {
reporteEtJournaliseErreur(e);
// TODO: Créer une fonction pour traiter les cas d'erreurs spécifiques
match(e.problemes)
.when(
// TODO: Créer une fonction utilitaire
p => pipe(dictValues(p), arrayFind(c => c === "The provided postcode is not valid")),
// TODO: Créer une fonction utilitaire pour fixer le texte d'un message
(): void => {
E.MESSAGE_ADRESSES.textContent = ERREUR_ADRESSE_MAUVAIS_CODE_POSTAL;
},
)
.otherwise((): void => {
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
});
})
.when(estErreurHttp, (e): void => {
reporteEtJournaliseErreur(e);
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.when(estErreurFetch, (e): void => {
reporteEtJournaliseErreur(e);
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
})
.exhaustive();
.ifLeft((err: ErreurAdresseInvalide | FetchErrors | HttpCodeErrors | ValiError<AnySchema>): void => {
match(err)
.with(P.instanceOf(ValiError), (e: ValiError<AnySchema>): void => {
reporteEtJournaliseErreur(e);
console.error(e.issues);
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(ErreurAdresseInvalide), (e: ErreurAdresseInvalide): void => {
reporteEtJournaliseErreur(e);
// TODO: Créer une fonction pour traiter les cas d'erreurs spécifiques
match(e.problemes)
.when(
// TODO: Créer une fonction utilitaire
(p) =>
pipe(
dictValues(p),
arrayFind((c) => c === "The provided postcode is not valid"),
),
// TODO: Créer une fonction utilitaire pour fixer le texte d'un message
(): void => {
E.MESSAGE_ADRESSES.textContent = ERREUR_ADRESSE_MAUVAIS_CODE_POSTAL;
},
)
.otherwise((): void => {
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
});
})
.when(estErreurHttp, (e): void => {
reporteEtJournaliseErreur(e);
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.when(estErreurFetch, (e): void => {
reporteEtJournaliseErreur(e);
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
})
.exhaustive();
E.BOUTON_ACTIONS_FORMULAIRE.textContent = "Submit your addresses";
},
)
E.BOUTON_ACTIONS_FORMULAIRE.textContent = "Submit your addresses";
})
// Désactive l'animation de chargement et rend le Bouton de nouveau cliquable
.finally((): void => setButtonLoadingState(E.BOUTON_ACTIONS_FORMULAIRE, false))
.run();
@ -247,10 +239,8 @@ export const initShippingCalculationButton = (): void => {
};
export const initOrderCreationButton = (): void => {
logger.debug("ADRESSES", "initOrderCreationButton");
// Créé la Commande au clic sur le Bouton de soumission du Formulaire
E.BOUTON_ACTIONS_FORMULAIRE.addEventListener("click", (event: Event): void => {
logger.info("ADRESSES", "Demande de création de commande");
Maybe
// Ne fais rien si le Formulaire n'est pas valide
.fromFalsy(
@ -275,19 +265,15 @@ export const initOrderCreationButton = (): void => {
})
.chain(first)
.orDefault({});
logger.debug("ADRESSES", "initOrderCreationButton", "selectedRateLS", selectedRateLS);
/** Les Produits du Panier. */
const cartProducts = E.ENTREES_PANIER
.orDefault([])
.map((entry: HTMLElement) => ({
product_id: Number(entry.getAttribute("data-id-produit")),
quantity: Number(entry.getAttribute("data-quantite")),
...(entry.getAttribute("data-id-variation") && {
variation_id: Number(entry.getAttribute("data-id-variation")),
}),
}));
logger.debug("ADRESSES", "initOrderCreationButton", "cartProducts", cartProducts);
const cartProducts = E.ENTREES_PANIER.orDefault([]).map((entry: HTMLElement) => ({
product_id: Number(entry.getAttribute("data-id-produit")),
quantity: Number(entry.getAttribute("data-quantite")),
...(entry.getAttribute("data-id-variation") && {
variation_id: Number(entry.getAttribute("data-id-variation")),
}),
}));
const addresses = getAddressesFromForm(formFields, E.BOUTON_SEPARATION_ADRESSES.checked);
/** Les données du Formulaire transformées pour la requête vers le Backend. */
@ -305,26 +291,24 @@ export const initOrderCreationButton = (): void => {
},
],
};
logger.debug("ADRESSES", "initOrderCreationButton", "formArgs", formArgs);
// Retire toute méthode de livraison invalide.
formArgs.shipping_lines = formArgs.shipping_lines.filter(line => line.method_id !== undefined);
formArgs.shipping_lines = formArgs.shipping_lines.filter((line) => line.method_id !== undefined);
// Réalise la requête et traite sa réponse
void EitherAsync
.liftEither(safeSchemaParse(formArgs, WCV3OrdersArgsSchema))
void EitherAsync.liftEither(safeSchemaParse(formArgs, WCV3OrdersArgsSchema))
// Désactive le Bouton pour empêcher des requêtes concurrentes
.ifRight((): void => setButtonLoadingState(E.BOUTON_ACTIONS_FORMULAIRE, true))
.chain((args: WCV3OrdersArgs) => {
logger.debug("ADRESSES", "args commande", args);
return safeFetch(postBackend(ROUTE_API_NOUVELLE_COMMANDES, JSON.stringify(args), true));
})
.chain((rs: Response) =>
EitherAsync<HttpCodeErrors, unknown>(async ({ throwE }): Promise<unknown> =>
match(await newPartialResponse(rs))
.with({ status: 201 }, (rs): unknown => rs.body)
.otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs)))
)
EitherAsync<HttpCodeErrors, unknown>(
async ({ throwE }): Promise<unknown> =>
match(await newPartialResponse(rs))
.with({ status: 201 }, (rs): unknown => rs.body)
.otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs))),
),
)
.chain((b: unknown) => EitherAsync.liftEither(safeSchemaParse(b, WCV3OrderSchema)))
.ifRight((order: WCV3Order): void => {
@ -335,11 +319,10 @@ export const initOrderCreationButton = (): void => {
event.preventDefault();
// Redirige vers Stripe
Maybe
.fromNullable(new URL(`https://${window.location.host}/checkout`))
.ifJust(url => url.searchParams.append("order_key", order.order_key))
.ifJust(url => url.searchParams.append("order_id", String(order.id)))
.ifJust(url => location.assign(url));
Maybe.fromNullable(new URL(`https://${window.location.host}/checkout`))
.ifJust((url) => url.searchParams.append("order_key", order.order_key))
.ifJust((url) => url.searchParams.append("order_id", String(order.id)))
.ifJust((url) => location.assign(url));
})
.ifLeft((err: FetchErrors | HttpCodeErrors | ValiError<AnySchema>): void => {
match(err)

View file

@ -59,7 +59,7 @@ export const initialiseElementsCodePromo = (): void => {
.with(
{
cible: P.when((cible: EventTarget | null) =>
targetMatchesSelector<HTMLButtonElement>(cible, DOM_BOUTON_CODE_PROMO)
targetMatchesSelector<HTMLButtonElement>(cible, DOM_BOUTON_CODE_PROMO),
),
codePromoPresent: false,
valeurCodePromo: P.string,
@ -84,7 +84,7 @@ export const initialiseElementsCodePromo = (): void => {
corps: JSON.stringify(args),
nonce: ETATS_PAGE.nonce,
route: ROUTE_API_APPLIQUE_COUPON,
})
}),
)
// Traite les cas d'Erreur
.chain((reponse: Response) =>
@ -96,13 +96,16 @@ export const initialiseElementsCodePromo = (): void => {
return match(reponseSimplifiee)
.with({ status: 500 }, () => throwE(new ServerError("500 Server Error")))
.with({
body: P.when(() => reponseEstCodeErreurWC(reponseSimplifiee, ERREUR_CODE_PROMO_INVALIDE)),
status: 400,
}, () => throwE(new ErreurCodePromoInvalide(recupereValeurCodePromo() ?? "")))
.with(
{
body: P.when(() => reponseEstCodeErreurWC(reponseSimplifiee, ERREUR_CODE_PROMO_INVALIDE)),
status: 400,
},
() => throwE(new ErreurCodePromoInvalide(recupereValeurCodePromo() ?? "")),
)
.with({ status: 200 }, () => reponseSimplifiee.body)
.run();
})
}),
)
// Vérifie le Schéma de la Réponse du backend
.chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCStoreCartSchema)))
@ -129,28 +132,28 @@ export const initialiseElementsCodePromo = (): void => {
window.dispatchEvent(CODE_PROMO_MAJ_EVENT);
// emetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true);
})
.ifLeft(erreur => {
.ifLeft((erreur) => {
// Rétablis le texte d'origine
E.BOUTON_CODE_PROMO.textContent = "Apply";
// Traite les Erreurs et affiche un Message à l'Utilisateur
match(erreur)
.with(P.instanceOf(ValiError), e => {
.with(P.instanceOf(ValiError), (e) => {
reporteErreur(e);
console.error("ValiError", e.issues);
})
.with(P.instanceOf(ErreurCodePromoInvalide), e => {
.with(P.instanceOf(ErreurCodePromoInvalide), (e) => {
E.MESSAGE_CODE_PROMO.textContent = "This promo code does not exist.";
reporteErreur(e);
console.error(e);
})
.with(P.instanceOf(ServerError), e => {
.with(P.instanceOf(ServerError), (e) => {
E.MESSAGE_CODE_PROMO.textContent =
"Sorry, something went wrong! Please refresh the page and try again.";
reporteErreur(e);
console.error(e);
})
.with(P.instanceOf(TypeError), e => {
.with(P.instanceOf(TypeError), (e) => {
E.MESSAGE_CODE_PROMO.textContent =
"Sorry, something went wrong! Please refresh the page and try again.";
reporteErreur(e);
@ -170,13 +173,12 @@ export const initialiseElementsCodePromo = (): void => {
// Un code promo est présent sous forme de chaîne
.with(
{
cible: P.when(cible => targetMatchesSelector<HTMLButtonElement>(cible, DOM_BOUTON_CODE_PROMO)),
cible: P.when((cible) => targetMatchesSelector<HTMLButtonElement>(cible, DOM_BOUTON_CODE_PROMO)),
codePromoPresent: true,
valeurCodePromo: P.string,
},
({ valeurCodePromo }) =>
void EitherAsync
.liftEither(safeSchemaParse({ code: valeurCodePromo }, WCStoreCartRemoveCouponArgsSchema))
void EitherAsync.liftEither(safeSchemaParse({ code: valeurCodePromo }, WCStoreCartRemoveCouponArgsSchema))
.ifRight(() => {
E.BOUTON_CODE_PROMO.setAttribute(ATTRIBUT_DESACTIVE, "");
E.BOUTON_CODE_PROMO.setAttribute(ATTRIBUT_CHARGEMENT, "");
@ -188,13 +190,13 @@ export const initialiseElementsCodePromo = (): void => {
corps: JSON.stringify(args),
nonce: ETATS_PAGE.nonce,
route: ROUTE_API_RETIRE_COUPON,
})
}),
)
.chain((reponse: Response) =>
EitherAsync<ServerError, unknown>(async ({ throwE }) => {
if (estReponse500(reponse)) throwE(new ServerError("500 server Error"));
return await reponse.json();
})
}),
)
.chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCStoreCartSchema)))
.ifRight((panier: WCStoreCart) => {
@ -214,21 +216,21 @@ export const initialiseElementsCodePromo = (): void => {
emetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true);
})
.ifLeft(erreur =>
.ifLeft((erreur) =>
match(erreur)
.with(P.instanceOf(ValiError), e => {
.with(P.instanceOf(ValiError), (e) => {
reporteErreur(e);
console.error("retour ajout code promo", e.issues);
})
.with(P.instanceOf(ServerError), e => {
.with(P.instanceOf(ServerError), (e) => {
reporteErreur(e);
console.error("retour ajout code promo", e);
})
.with(P.instanceOf(TypeError), e => {
.with(P.instanceOf(TypeError), (e) => {
reporteErreur(e);
console.error("retour ajout code promo", e);
})
.exhaustive()
.exhaustive(),
)
.finally(() => {
E.BOUTON_CODE_PROMO.removeAttribute(ATTRIBUT_CHARGEMENT);
@ -237,5 +239,6 @@ export const initialiseElementsCodePromo = (): void => {
.run(),
)
// Ne rien faire en dehors de ces deux situations
.with(P._, identity));
.with(P._, identity),
);
};

View file

@ -28,9 +28,7 @@ export const E = {
CONTENEUR_METHODES_LIVRAISON: mustGetEleInDocument<HTMLFieldSetElement>(DOM_CONTENEUR_METHODES_LIVRAISON),
CONTENEUR_PANIER: mustGetEleInDocument<HTMLElement>(DOM_CONTENEUR_PANIER),
ENSEMBLE_CODE_PROMO: mustGetEleInDocument<HTMLFormElement>(DOM_ENSEMBLE_CODE_PROMO),
ENTREES_PANIER: recupereElementsDocumentEither<HTMLElement>(
DOM_ENTREES_PANIER,
),
ENTREES_PANIER: recupereElementsDocumentEither<HTMLElement>(DOM_ENTREES_PANIER),
FORMULAIRE_FACTURATION: mustGetEleInDocument<HTMLDivElement>(DOM_FORMULAIRE_FACTURATION),
FORMULAIRE_PANIER: mustGetEleInDocument<HTMLFormElement>(DOM_FORMULAIRE_PANIER),
INSTRUCTIONS_CLIENT: mustGetEleInDocument<HTMLTextAreaElement>(DOM_INSTRUCTIONS_CLIENT),

View file

@ -7,7 +7,6 @@ import { ADRESSES_MAJ, CODE_PROMO_MAJ, SHIPPING_RATES_UPDATED, TOTALS_UPDATED }
import { reporteEtJournaliseErreur } from "../lib/erreurs";
import { formateEnEuros } from "../lib/nombres";
import { eitherSetSessionStorage } from "../lib/session-storage";
import { logger } from "../journalisation.ts";
import { E } from "./scripts-page-panier-elements";
import { generateShippingRatesHTML } from "./scripts-page-panier-methodes-livraison";
@ -40,8 +39,7 @@ export const souscrisEvenementsPanier = (): void => {
// La vérification du schéma se fait à l'émission
.encase(() => (event as UpdatedShippingRatesEvent).detail)
// Met à jour le DOM
.ifRight(event => {
logger.info("ShippingRatesUpdatedEvent", "shipping_rates", event);
.ifRight((event) => {
// Met à jour les Méthodes à l'Utilisateur si demandé
// Il peut y en avoir aucune
if (event.refresh_methods) {
@ -49,7 +47,7 @@ export const souscrisEvenementsPanier = (): void => {
}
})
// Met à jour le SessionStorage
.chain(event => eitherSetSessionStorage("shipping_rates", event.shipping_rates))
.chain((event) => eitherSetSessionStorage("shipping_rates", event.shipping_rates))
.ifLeft(reporteEtJournaliseErreur);
});
@ -57,10 +55,10 @@ export const souscrisEvenementsPanier = (): void => {
Either
// La vérification du Schéma se fait à l'émission
.encase(() => (event as UpdatedTotalsEvent).detail.totals)
.chain(ts => eitherSetSessionStorage("totals", ts))
.chain((ts) => eitherSetSessionStorage("totals", ts))
.ifLeft(reporteEtJournaliseErreur)
// Met à jour le DOM
.ifRight(ts => {
.ifRight((ts) => {
E.SOUS_TOTAL_LIVRAISON_VALEUR.textContent = formateEnEuros(ts.total_shipping);
E.SOUS_TOTAL_PRODUITS_VALEUR.textContent = formateEnEuros(ts.total_items);
E.SOUS_TOTAL_REDUCTION_VALEUR.textContent = formateEnEuros(ts.total_discount * -1);

View file

@ -16,6 +16,9 @@ export const getShippingRatesLS = (): Maybe<WCStoreShippingRateShippingRates> =>
export const setShippingRatesLS = (
shippingRates: WCStoreShippingRateShippingRates,
): Maybe<WCStoreShippingRateShippingRates> =>
setSessionStorageByKey("shipping_rates", WCStoreShippingRateShippingRatesSchema)(shippingRates)
setSessionStorageByKey(
"shipping_rates",
WCStoreShippingRateShippingRatesSchema,
)(shippingRates)
.ifLeft(reporteEtJournaliseErreur)
.toMaybe();

View file

@ -13,30 +13,28 @@ import { formateEnEuros } from "../lib/nombres";
import { find } from "../lib/safe-arrays";
import { WCStoreCartTotalsSchema } from "../lib/schemas/api/cart";
import { getSessionStorageByKey } from "../lib/session-storage";
import { logger } from "../journalisation.ts";
import { E } from "./scripts-page-panier-elements";
import { getShippingRatesLS } from "./scripts-page-panier-local-storage";
export const initShippingRatesChoicesActions = (): void => {
logger.debug("METHODES_LIVRAISON", "initShippingRatesChoicesActions");
getDOMElementsWithSelector(E.CONTENEUR_METHODES_LIVRAISON)<HTMLInputElement>("input")
.ifRight(forEach((el: HTMLInputElement): void =>
getDOMElementsWithSelector(E.CONTENEUR_METHODES_LIVRAISON)<HTMLInputElement>("input").ifRight(
forEach((el: HTMLInputElement): void =>
el.addEventListener("click", (event: MouseEvent): void => {
logger.info("METHODES_LIVRAISON", "Clic sur un choix de méthode de livraison");
// Récupère les méthodes du SessionStorage et les met à jour avec le nouveau choix
getShippingRatesLS()
// Met à jour la sélection de la Méthode
.map(map((sr: WCStoreShippingRateShippingRate) => {
sr.selected = sr.method_id === (event.target as HTMLInputElement).value;
return sr;
}))
.map(
map((sr: WCStoreShippingRateShippingRate) => {
sr.selected = sr.method_id === (event.target as HTMLInputElement).value;
return sr;
}),
)
// Met à jour les Méthodes de livraison dans le SessionStorage et le DOM
.ifJust((srs: WCStoreShippingRateShippingRates): void => {
window.dispatchEvent(createUpdatedShippingRatesEvent(srs, false));
})
// Met à jour les totaux dans le SessionStorage et le DOM
.chain(find(sr => sr.selected))
.chain(find((sr) => sr.selected))
.ifJust((sr: WCStoreShippingRateShippingRate): void => {
getSessionStorageByKey("totals", WCStoreCartTotalsSchema)
.ifLeft(reporteEtJournaliseErreur)
@ -49,8 +47,9 @@ export const initShippingRatesChoicesActions = (): void => {
window.dispatchEvent(createUpdatedTotalsEvent(ts));
});
});
})
));
}),
),
);
};
export const generateShippingRatesHTML = (
@ -64,20 +63,21 @@ export const generateShippingRatesHTML = (
}
// Retire les méthodes de livraison initiales
getDOMElementsWithSelector(container)("div[data-methode-initiale]").ifRight(arrayForEach(div => div.remove()));
getDOMElementsWithSelector(container)("div[data-methode-initiale]").ifRight(arrayForEach((div) => div.remove()));
const selectedShippingRate: string = shippingRates.find(sr => sr.selected)?.method_id ?? "";
const shippingRatesHTML: ReadonlyArray<TemplateResult> = arrayMap(shippingRates, methode => {
return html`
<div>
const selectedShippingRate: string = shippingRates.find((sr) => sr.selected)?.method_id ?? "";
const shippingRatesHTML: ReadonlyArray<TemplateResult> = arrayMap(shippingRates, (methode) => {
return html` <div>
<input
id="methode-livraison-${methode.method_id}"
name="choix-methode-livraison"
type="radio"
value="${methode.method_id}"
.checked="${methode.method_id === selectedShippingRate}"
/>
<label for="methode-livraison-${methode.method_id}"
>${methode.name} (${formateEnEuros(methode.price)})</label
>
<label for="methode-livraison-${methode.method_id}">${methode.name} (${formateEnEuros(methode.price)})</label>
</div>`;
});

View file

@ -65,7 +65,8 @@ const getCartEntryInteractiveEles = (entree: HTMLElement): CartEntryInteractiveE
* @returns Rien.
*/
export const toggleCartEntryButtons =
(activated: boolean) => (cartEntries: ReadonlyArray<CartEntryInteractiveElements>): void =>
(activated: boolean) =>
(cartEntries: ReadonlyArray<CartEntryInteractiveElements>): void =>
arrayForEach(cartEntries, (e: CartEntryInteractiveElements): void => {
if (activated) {
// Active les Boutons
@ -89,8 +90,7 @@ export const initialiseActionsEntreesPanier = (): void => {
E.ENTREES_PANIER.ifRight((cartEntries: Array<HTMLElement>) =>
arrayForEach(cartEntries, (entry: HTMLElement): void => {
// Retire l'entrée du DOM si la clé Panier n'existe pas puis arrête précocement
const entryKey: string = Maybe
.fromNullable(entry.getAttribute(ATTRIBUT_CLE_PANIER))
const entryKey: string = Maybe.fromNullable(entry.getAttribute(ATTRIBUT_CLE_PANIER))
.ifNothing(() => entry.remove())
.orDefault("CLE_PANIER_INEXISTANTE");
const entryButtons: CartEntryInteractiveElements = getCartEntryInteractiveEles(entry);
@ -104,32 +104,33 @@ export const initialiseActionsEntreesPanier = (): void => {
.when(
(target: EventTarget) => (target as HTMLElement).matches(DOM_BOUTON_ADDITION_QUANTITE),
(): void => {
void EitherAsync
.liftEither(
Maybe
// Une valeur à incrémenter doit exister
.fromNullable(entryButtons.quantityInput.valueAsNumber)
.toEither(new Error("Quantité manquante pour cette ligne du Panier !")),
)
.chain(q =>
void EitherAsync.liftEither(
Maybe
// Une valeur à incrémenter doit exister
.fromNullable(entryButtons.quantityInput.valueAsNumber)
.toEither(new Error("Quantité manquante pour cette ligne du Panier !")),
)
.chain((q) =>
EitherAsync.liftEither(
safeSchemaParse({ key: entryKey, quantity: q + 1 }, WCStoreCartUpdateItemArgsSchema),
)
),
)
.ifRight(() => pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(false)))
.chain((args: WCStoreCartUpdateItemArgs) =>
safeFetch(postBackend({
corps: JSON.stringify(args),
nonce: PAGE_STATE.nonce,
route: ROUTE_API_MAJ_ARTICLE_PANIER,
}))
safeFetch(
postBackend({
corps: JSON.stringify(args),
nonce: PAGE_STATE.nonce,
route: ROUTE_API_MAJ_ARTICLE_PANIER,
}),
),
)
.chain((r: Response) =>
EitherAsync<ServerError, unknown>(async ({ throwE }) =>
match(await newPartialResponse(r))
.with({ status: 200 }, r => r.body)
.otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs)))
)
.with({ status: 200 }, (r) => r.body)
.otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs))),
),
)
.chain((b: unknown) => EitherAsync.liftEither(safeSchemaParse(b, WCStoreCartSchema)))
.ifRight((c: WCStoreCart): void => {
@ -145,27 +146,25 @@ export const initialiseActionsEntreesPanier = (): void => {
// Émet un Message pour réinitialiser la validation de la livraison
emetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true);
})
.ifLeft(
(err: FetchErrors | HttpCodeErrors | ValiError<AnySchema>): void => {
match(err)
.with(P.instanceOf(ValiError), e => {
reporteErreur(e);
console.error(e.issues);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(ServerError), P.instanceOf(BadRequestError), e => {
reporteErreur(e);
console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), e => {
reporteErreur(e);
console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
})
.exhaustive();
},
)
.ifLeft((err: FetchErrors | HttpCodeErrors | ValiError<AnySchema>): void => {
match(err)
.with(P.instanceOf(ValiError), (e) => {
reporteErreur(e);
console.error(e.issues);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(ServerError), P.instanceOf(BadRequestError), (e) => {
reporteErreur(e);
console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), (e) => {
reporteErreur(e);
console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
})
.exhaustive();
})
.finally(() => {
pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(true));
})
@ -179,7 +178,7 @@ export const initialiseActionsEntreesPanier = (): void => {
Maybe
// Nécessaire pour que l'on ait une valeur à incrémenter
.fromNullable(entryButtons.quantityInput.valueAsNumber)
.filter(valeur => valeur > 1)
.filter((valeur) => valeur > 1)
.ifJust((valeur: number) => {
// Réalise la requête et traite sa réponse
void EitherAsync
@ -189,15 +188,17 @@ export const initialiseActionsEntreesPanier = (): void => {
)
// 2. Exécute un Effet pour empêcher les requêtes concurrentes
.ifRight(() =>
pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(false))
pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(false)),
)
// 3. Exécute la requête via fetch sous forme d'EitherAsync
.chain((args: WCStoreCartUpdateItemArgs) =>
safeFetch(postBackend({
corps: JSON.stringify(args),
nonce: PAGE_STATE.nonce,
route: ROUTE_API_MAJ_ARTICLE_PANIER,
}))
safeFetch(
postBackend({
corps: JSON.stringify(args),
nonce: PAGE_STATE.nonce,
route: ROUTE_API_MAJ_ARTICLE_PANIER,
}),
),
)
// 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse
.chain((reponse: Response) =>
@ -206,9 +207,9 @@ export const initialiseActionsEntreesPanier = (): void => {
match(await newPartialResponse(reponse))
.with({ status: 500 }, () => throwE(new ServerError("500 Server Error")))
.with({ status: 400 }, () => throwE(new BadRequestError("400 Bad Request Error")))
.with({ status: 200 }, r => r.body)
.otherwise(erreur => throwE(new Error(`Erreur inconnue ${String(erreur.status)}`)))
)
.with({ status: 200 }, (r) => r.body)
.otherwise((erreur) => throwE(new Error(`Erreur inconnue ${String(erreur.status)}`))),
),
)
// 5. Vérifie le Schéma de la Réponse
.chain((corps: unknown) => EitherAsync.liftEither(safeSchemaParse(corps, WCStoreCartSchema)))
@ -227,27 +228,25 @@ export const initialiseActionsEntreesPanier = (): void => {
emetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true);
})
// 7. Traite les Erreurs et affiche un message à l'Utilisateur
.ifLeft(
(erreur: BadRequestError | FetchErrors | ServerError | ValiError<AnySchema>): void => {
match(erreur)
.with(P.instanceOf(ValiError), e => {
reporteErreur(e);
console.error(e.issues);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(ServerError), P.instanceOf(BadRequestError), e => {
reporteErreur(e);
console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), e => {
reporteErreur(e);
console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
})
.exhaustive();
},
)
.ifLeft((erreur: BadRequestError | FetchErrors | ServerError | ValiError<AnySchema>): void => {
match(erreur)
.with(P.instanceOf(ValiError), (e) => {
reporteErreur(e);
console.error(e.issues);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(ServerError), P.instanceOf(BadRequestError), (e) => {
reporteErreur(e);
console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), (e) => {
reporteErreur(e);
console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
})
.exhaustive();
})
.finally(() => {
// Réactive les Boutons
pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(true));
@ -270,15 +269,17 @@ export const initialiseActionsEntreesPanier = (): void => {
.liftEither(safeSchemaParse({ key: entryKey }, WCStoreCartRemoveItemArgsSchema))
// 2. Exécute un Effet pour empêcher les requêtes concurrentes
.ifRight(() =>
pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(false))
pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(false)),
)
// 3. Exécute la requête via fetch sous forme d'EitherAsync
.chain((args: WCStoreCartRemoveItemArgs) =>
safeFetch(postBackend({
corps: JSON.stringify(args),
nonce: PAGE_STATE.nonce,
route: ROUTE_API_RETIRE_ARTICLE_PANIER,
}))
safeFetch(
postBackend({
corps: JSON.stringify(args),
nonce: PAGE_STATE.nonce,
route: ROUTE_API_RETIRE_ARTICLE_PANIER,
}),
),
)
// 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse
.chain((reponse: Response) =>
@ -287,9 +288,9 @@ export const initialiseActionsEntreesPanier = (): void => {
match(await newPartialResponse(reponse))
.with({ status: 500 }, () => throwE(new ServerError("500 Server Error")))
.with({ status: 400 }, () => throwE(new BadRequestError("400 Bad Request Error")))
.with({ status: 200 }, r => r.body)
.otherwise(erreur => throwE(new Error(`Erreur inconnue ${String(erreur.status)}`)))
)
.with({ status: 200 }, (r) => r.body)
.otherwise((erreur) => throwE(new Error(`Erreur inconnue ${String(erreur.status)}`))),
),
)
// 5. Vérifie le Schéma de la Réponse
.chain((corps: unknown) => EitherAsync.liftEither(safeSchemaParse(corps, WCStoreCartSchema)))
@ -311,27 +312,25 @@ export const initialiseActionsEntreesPanier = (): void => {
entry.remove();
})
// 7. Traite les Erreurs et affiche un message à l'Utilisateur
.ifLeft(
(erreur: BadRequestError | FetchErrors | ServerError | ValiError<AnySchema>): void => {
match(erreur)
.with(P.instanceOf(ValiError), e => {
reporteErreur(e);
console.error(e.issues);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(ServerError), P.instanceOf(BadRequestError), e => {
reporteErreur(e);
console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), e => {
reporteErreur(e);
console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
})
.exhaustive();
},
)
.ifLeft((erreur: BadRequestError | FetchErrors | ServerError | ValiError<AnySchema>): void => {
match(erreur)
.with(P.instanceOf(ValiError), (e) => {
reporteErreur(e);
console.error(e.issues);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(ServerError), P.instanceOf(BadRequestError), (e) => {
reporteErreur(e);
console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), (e) => {
reporteErreur(e);
console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
})
.exhaustive();
})
.finally(() => {
// Réactive les Boutons
pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(true));
@ -340,8 +339,8 @@ export const initialiseActionsEntreesPanier = (): void => {
});
},
)
.otherwise(_ => {});
.otherwise((_) => {});
});
})
}),
);
};

View file

@ -65,7 +65,7 @@ const initialiseObservationFenetre = (): void => {
etapePlanifiee = true;
requestAnimationFrame((): void =>
majVisibiliteBouton(defilementY > (window.innerHeight * RATIO_MINIMUM_PAGE_PAR_FENETRE))
majVisibiliteBouton(defilementY > window.innerHeight * RATIO_MINIMUM_PAGE_PAR_FENETRE),
);
});

View file

@ -2,34 +2,61 @@
import { Array as EffectArray, Match, Predicate } from "effect";
import { DOM_ENTREES_MENU_CATEGORIES_PRODUITS, DOM_MENU_CATEGORIES_PRODUITS } from "./constantes/dom.ts";
import { getAllSelectorFromDocumentOrThrow, getFirstSelectorFromDocumentOrThrow } from "../scripts-effect/lib/dom.ts";
import {
DOM_ENTREES_MENU_CATEGORIES_PRODUITS,
DOM_MENU_CATEGORIES_PRODUITS,
} from "./constantes/dom.ts";
import {
getAllSelectorFromDocumentOrThrow,
getFirstSelectorFromDocumentOrThrow,
} from "../scripts-effect/lib/dom.ts";
// Initialise les attributs HTML pour l'affichage initiale des flèches de défilement du menu de catégories de Produits.
document.addEventListener("DOMContentLoaded", (): void => {
const productsCategoriesMenu: HTMLElement = getFirstSelectorFromDocumentOrThrow<HTMLElement>(
DOM_MENU_CATEGORIES_PRODUITS,
);
const menuEntries: ReadonlyArray<HTMLAnchorElement> = getAllSelectorFromDocumentOrThrow(
DOM_ENTREES_MENU_CATEGORIES_PRODUITS,
);
const productsCategoriesMenu: HTMLElement =
getFirstSelectorFromDocumentOrThrow<HTMLElement>(
DOM_MENU_CATEGORIES_PRODUITS,
);
const menuEntries: ReadonlyArray<HTMLAnchorElement> =
getAllSelectorFromDocumentOrThrow(DOM_ENTREES_MENU_CATEGORIES_PRODUITS);
const firstAndLastEntries: Array<(HTMLAnchorElement | undefined)> = [menuEntries.at(0), menuEntries.at(-1)];
const firstAndLastEntries: Array<HTMLAnchorElement | undefined> = [
menuEntries.at(0),
menuEntries.at(-1),
];
// Créé un nouvel Observer pour la première et dernière entrée.
EffectArray.forEach(firstAndLastEntries, (menuEntry, _index) => {
if (Predicate.isUndefined(menuEntry)) return;
new IntersectionObserver(
EffectArray.forEach(intersectionEntry => {
EffectArray.forEach((intersectionEntry) => {
// Ne déclenche rien si le scroll n'est pas horizontal
if (intersectionEntry.boundingClientRect.top <= 0) return;
Match.value([intersectionEntry.isIntersecting]).pipe(
Match.when([true, 0], () => productsCategoriesMenu.removeAttribute("data-entrees-presentes-debut")),
Match.when([true, 1], () => productsCategoriesMenu.removeAttribute("data-entrees-presentes-fin")),
Match.when([false, 0], () => productsCategoriesMenu.setAttribute("data-entrees-presentes-debut", "")),
Match.when([false, 1], () => productsCategoriesMenu.setAttribute("data-entrees-presentes-fin", "")),
Match.when([true, 0], () =>
productsCategoriesMenu.removeAttribute(
"data-entrees-presentes-debut",
),
),
Match.when([true, 1], () =>
productsCategoriesMenu.removeAttribute(
"data-entrees-presentes-fin",
),
),
Match.when([false, 0], () =>
productsCategoriesMenu.setAttribute(
"data-entrees-presentes-debut",
"",
),
),
Match.when([false, 1], () =>
productsCategoriesMenu.setAttribute(
"data-entrees-presentes-fin",
"",
),
),
Match.orElse(() => {}),
);
}),

View file

@ -18,13 +18,13 @@ const E = {
const initialiseBoutonMenuMobile = (): void => {
const menuMobile = new A11yDialog(E.MENU_MOBILE);
new ResizeObserver(entrees =>
new ResizeObserver((entrees) =>
// Cache le Menu mobile pour les grandes tailles d'écrans
pipe(
A.head(entrees),
O.filter((entree: ResizeObserverEntry) => entree.borderBoxSize[0]!.inlineSize > 1000),
O.tap(_ => menuMobile.hide()),
)
O.tap((_) => menuMobile.hide()),
),
).observe(E.CORPS_HTML);
E.BOUTON_MENU_MOBILE.addEventListener("click", (): void => {

View file

@ -16,9 +16,7 @@ import {
import { mustGetEleInDocument, mustGetElesInDocument } from "./lib/dom.ts";
/** Le Conteneur des images du storytelling. */
const CONTENEUR_STORYTELLING = mustGetEleInDocument<HTMLElement>(
DOM_CONTENEUR_STORYTELLING_A_PROPOS,
);
const CONTENEUR_STORYTELLING = mustGetEleInDocument<HTMLElement>(DOM_CONTENEUR_STORYTELLING_A_PROPOS);
/** */
const EPINGLES = mustGetElesInDocument<HTMLButtonElement>(DOM_EPINGLE);
/** */
@ -50,7 +48,7 @@ document.addEventListener("DOMContentLoaded", (): void => {
O.tap((id: string) => {
beltPipe(
O.fromNullable(ENSEMBLES_EPINGLES_BOITES_TEXTE.get(id)),
O.tap(A.forEach(element => element.removeAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF))),
O.tap(A.forEach((element) => element.removeAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF))),
);
}),
);
@ -66,7 +64,7 @@ document.addEventListener("DOMContentLoaded", (): void => {
if (cible.hasAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF)) {
beltPipe(
O.fromNullable(ENSEMBLES_EPINGLES_BOITES_TEXTE.get(id)),
O.tap(A.forEach(element => element.removeAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF))),
O.tap(A.forEach((element) => element.removeAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF))),
);
return;
}
@ -75,12 +73,12 @@ document.addEventListener("DOMContentLoaded", (): void => {
beltPipe(
Array.from(ENSEMBLES_EPINGLES_BOITES_TEXTE.values()),
A.flat,
A.forEach(element => element.removeAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF)),
A.forEach((element) => element.removeAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF)),
);
// Active l'Attribut sur l'Ensemble
beltPipe(
O.fromNullable(ENSEMBLES_EPINGLES_BOITES_TEXTE.get(id)),
O.tap(A.forEach(element => element.toggleAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF))),
O.tap(A.forEach((element) => element.toggleAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF))),
);
}),
);

View file

@ -10,7 +10,6 @@ import {
DOM_GARDE_FOU_JS,
DOM_IMAGES_STORYTELLING,
} from "./constantes/dom.ts";
import { nuLogger } from "./journalisation.ts";
import { mustGetEleInDocument, mustGetElesInDocument } from "./lib/dom.ts";
import { estEntreDeuxNombres } from "./lib/nombres.ts";
@ -41,8 +40,6 @@ const initDefilementStorytelling = (): void => {
/** La position du défilement (en pixels) du Conteneur des images du storytelling. */
let positionDefilementConteneur = 0;
nuLogger.debug`initStorytellingScroll | dimensionsImages ${dimensionsImage.height}`;
/**
* Bascule la visibilité d'une image en
* @param image
@ -64,7 +61,6 @@ const initDefilementStorytelling = (): void => {
})),
O.getWithDefault({ height: 0, width: 0 }),
);
nuLogger.debug`majDimensions | dimensionsImage ${dimensionsImage}`;
// Adapte la longueur du conteneur d'animation à la nouvelle longueur d'une image.
E.CONTENEUR_ANIMATION.style.width = `${String(dimensionsImage.width)}px`;
@ -73,7 +69,6 @@ const initDefilementStorytelling = (): void => {
const nouvelleHauteurMax = `${String(dimensionsImage.height * E.IMAGES_STORYTELLING.length + 61)}px`;
E.CONTENEUR_STORYTELLING.style.minHeight = nouvelleHauteurMax;
E.CONTENEUR_STORYTELLING.style.maxHeight = nouvelleHauteurMax;
nuLogger.debug`majDimensions | nouvelleHauteurMax ${nouvelleHauteurMax}`;
};
/**
@ -105,19 +100,17 @@ const initDefilementStorytelling = (): void => {
const initGestionAnimation = (): void => {
pipe(
A.at(E.IMAGES_STORYTELLING, 0),
O.tap(img => {
O.tap((img) => {
const options: IntersectionObserverInit = {
root: null,
rootMargin: "0px",
threshold: 0,
};
const callback = (entries: Array<IntersectionObserverEntry>) => {
A.forEach(entries, e => {
A.forEach(entries, (e) => {
e.intersectionRatio >= 0.9
? E.CONTENEUR_ANIMATION.removeAttribute(ATTRIBUT_HIDDEN)
: E.CONTENEUR_ANIMATION.setAttribute(ATTRIBUT_HIDDEN, "");
nuLogger.debug`initGestionAnimation | estCache ${e.intersectionRatio >= 0.9} | ${e}`;
});
};

View file

@ -87,8 +87,8 @@ const initialisePageBoutique = (): void => {
nonce: ETATS_PAGE.nonce,
route: ROUTE_API_NOUVELLE_PRODUCTS,
searchParams: new URLSearchParams(args).toString(),
})
)
}),
),
)
// 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse
.chain((reponse: Response) =>
@ -96,9 +96,9 @@ const initialisePageBoutique = (): void => {
return match(await newPartialResponse(reponse))
.with({ status: 500 }, () => throwE(new ServerError("500 Server Error")))
.with({ status: 400 }, () => throwE(new BadRequestError("400 Server Error")))
.with({ status: 200 }, r => r.body)
.with({ status: 200 }, (r) => r.body)
.run();
})
}),
)
// 5. Vérifie le Schéma de la Réponse
.chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCV3ProductsSchema)))
@ -139,7 +139,7 @@ const initialisePageBoutique = (): void => {
</figure>
</article>
`,
tap(article => fragment.appendChild(article)),
tap((article) => fragment.appendChild(article)),
);
}
@ -152,11 +152,11 @@ const initialisePageBoutique = (): void => {
// 7. Traite les Erreurs et affiche un Message à l'Utilisateur
.ifLeft((erreur: APIProductsErrors) => {
match(erreur)
.with(P.instanceOf(ValiError), e => {
.with(P.instanceOf(ValiError), (e) => {
reporteErreur(e);
console.error("ValiError", e.issues);
})
.otherwise(e => {
.otherwise((e) => {
reporteErreur(e);
console.error("Erreur", e);
});

View file

@ -63,7 +63,8 @@ const ETATS_PAGE: EtatsPage = _etats;
* @throws Une SyntaxError si l'Élément n'est pas trouvé.
*/
const recupereElementDansEntreePanierOuLeve =
(entree: HTMLElement) => <E extends Element = Element>(selecteur: string) =>
(entree: HTMLElement) =>
<E extends Element = Element>(selecteur: string) =>
pipe(recupereElementAvecSelecteur(entree)<E>(selecteur), recupereElementOuLeve);
// NOTE: Nécessaire pour éviter une condition de course entre la réussite de la requête et l'émission effective du Message
@ -108,17 +109,14 @@ const initialiseMajContenuPanier = (): void => {
donnees.produits.forEach((ligne: WCStoreCartItem) => {
// Met à jour les entrées du Panier
E.ENTREES_PANIER.ifRight((entrees: Array<HTMLElement>) => {
Maybe
.fromNullable(entrees.find(entree => entree.getAttribute(ATTRIBUT_CLE_PANIER) === ligne.key))
.ifJust((entree: HTMLElement) => {
Maybe.fromNullable(entrees.find((entree) => entree.getAttribute(ATTRIBUT_CLE_PANIER) === ligne.key)).ifJust(
(entree: HTMLElement) => {
// Fonction utilitaire
const recupereElementDansEntree = recupereElementDansEntreePanierOuLeve(entree);
// Récupère les Éléments à mettre à jour
const prixLigne = recupereElementDansEntree<HTMLSpanElement>(DOM_PRIX_LIGNE_PANIER);
const champQuantite = recupereElementDansEntree<HTMLInputElement>(
DOM_CHAMP_QUANTITE_LIGNE_PANIER,
);
const champQuantite = recupereElementDansEntree<HTMLInputElement>(DOM_CHAMP_QUANTITE_LIGNE_PANIER);
// Met à jour les valeurs
entree.setAttribute("data-quantite", String(ligne.quantity));
@ -127,7 +125,8 @@ const initialiseMajContenuPanier = (): void => {
// Réactive les Boutons
majEtatsActivationBoutons(entrees);
});
},
);
// Met à jour les totaux du Panier
E.SOUS_TOTAL_PRODUITS.textContent = formateEnEuros(donnees.sousTotalProduits);
@ -143,21 +142,20 @@ const initialiseMajContenuPanier = (): void => {
// Reporte tout Erreur et réactive les Boutons
.ifLeft((erreur: CleNonTrouveError | ValiError<typeof MessageMajContenuPanierSchema>) => {
reporteErreur(erreur);
E.ENTREES_PANIER.ifRight(entrees => majEtatsActivationBoutons(entrees));
E.ENTREES_PANIER.ifRight((entrees) => majEtatsActivationBoutons(entrees));
});
};
};
const initialiseMajFormulairesPanier = (): void => {
E.BOUTON_SEPARATION_ADRESSES.addEventListener("click", (): void => {
Maybe
.fromFalsy(E.BOUTON_SEPARATION_ADRESSES.checked)
Maybe.fromFalsy(E.BOUTON_SEPARATION_ADRESSES.checked)
// Les Adresses sont séparées.
.ifJust((): void => {
// Rend visible le formulaire de facturation.
E.FORMULAIRE_FACTURATION.removeAttribute(ATTRIBUT_HIDDEN);
getDOMElementsWithSelector(E.FORMULAIRE_FACTURATION)("input, select").ifRight(
arrayForEach(champ => champ.removeAttribute(ATTRIBUT_DESACTIVE)),
arrayForEach((champ) => champ.removeAttribute(ATTRIBUT_DESACTIVE)),
);
})
// Les Adresses sont combinées.
@ -166,10 +164,12 @@ const initialiseMajFormulairesPanier = (): void => {
E.FORMULAIRE_FACTURATION.setAttribute(ATTRIBUT_HIDDEN, "");
getDOMElementsWithSelector(E.FORMULAIRE_FACTURATION)<HTMLInputElement | HTMLSelectElement>(
"input, select",
).ifRight(arrayForEach(champ => {
champ.setAttribute(ATTRIBUT_DESACTIVE, "");
champ.value = "";
}));
).ifRight(
arrayForEach((champ) => {
champ.setAttribute(ATTRIBUT_DESACTIVE, "");
champ.value = "";
}),
);
});
});
};

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