2024-09-06
This commit is contained in:
parent
5045ef25dc
commit
082202007b
58 changed files with 247957 additions and 494 deletions
|
|
@ -557,28 +557,43 @@ ul.avec-puce-cercle a {
|
|||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boîte flottante avec les informations Produit, le sélecteur de variation et de quantité pour le
|
||||
* Panier.
|
||||
*
|
||||
* 1. Flotte toujours en bas de la page et s'arrête avant les Produits de la même collection.
|
||||
* 2. Conteneur existant pour que le flottement sticky fonctionne ; n'a pas de dimensions.
|
||||
*/
|
||||
.informations-produit {
|
||||
position: sticky;
|
||||
bottom: 1rem;
|
||||
/* Variables */
|
||||
--boite-couleur-fond: rgb(255 255 255 / 90%);
|
||||
--boite-position-basse: 1rem;
|
||||
--boite-longueur: 70ch;
|
||||
--section-marges-internes: 1rem;
|
||||
position: sticky; /* 1 */
|
||||
bottom: var(--boite-position-basse); /* 1 */
|
||||
overflow: visible;
|
||||
width: 0;
|
||||
height: 0;
|
||||
width: 0; /* 2 */
|
||||
height: 0; /* 2 */
|
||||
/* Nom du Produit, sélecteur de variation et prix du Produit */
|
||||
/* Bouton « Ajouter au Panier » */
|
||||
}
|
||||
.informations-produit__conteneur {
|
||||
transform: translate(calc(50vw - 35ch), -100%);
|
||||
transform: translate(calc(50vw - var(--boite-longueur) / 2), -100%);
|
||||
display: grid;
|
||||
width: 70ch;
|
||||
max-width: 70ch;
|
||||
width: var(--boite-longueur);
|
||||
max-width: var(--boite-longueur);
|
||||
border: 1px solid var(--couleur-noir);
|
||||
/**
|
||||
* Définis les apparence et comportement de toutes les sections de la boîte.
|
||||
*/
|
||||
}
|
||||
.informations-produit__conteneur > section {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
height: 100%;
|
||||
padding: 1rem;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
padding: var(--section-marges-internes);
|
||||
background: var(--boite-couleur-fond);
|
||||
}
|
||||
.informations-produit__conteneur > section + section {
|
||||
border-top: 1px solid var(--couleur-noir);
|
||||
|
|
@ -586,12 +601,13 @@ ul.avec-puce-cercle a {
|
|||
.informations-produit .onglets-details-produit {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
grid-template-rows: 1fr min-content;
|
||||
grid-template-rows: auto min-content;
|
||||
padding: initial;
|
||||
}
|
||||
.informations-produit .onglets-details-produit > section {
|
||||
overflow-y: auto;
|
||||
grid-column: span 3;
|
||||
padding: 1rem;
|
||||
padding: var(--section-marges-internes);
|
||||
font-weight: 350;
|
||||
}
|
||||
.informations-produit .onglets-details-produit > section[hidden] {
|
||||
|
|
@ -616,24 +632,36 @@ ul.avec-puce-cercle a {
|
|||
.informations-produit .onglets-details-produit > ul li {
|
||||
width: 100%;
|
||||
}
|
||||
.informations-produit .onglets-details-produit > ul li:first-of-type a {
|
||||
border-right-color: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.informations-produit .onglets-details-produit > ul li:last-of-type a {
|
||||
border-right-color: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.informations-produit .onglets-details-produit > ul li a {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: var(--espace-xs) 0;
|
||||
border-top: 1px solid var(--couleur-noir);
|
||||
border-top: 1px solid transparent;
|
||||
border-right: 1px solid var(--couleur-noir);
|
||||
border-left: 1px solid var(--couleur-noir);
|
||||
}
|
||||
.informations-produit .onglets-details-produit > ul li a:first-of-type {
|
||||
border-left: initial;
|
||||
}
|
||||
.informations-produit .onglets-details-produit > ul li a:last-of-type {
|
||||
border-left: initial;
|
||||
/* Quand l'onglet est sélectionné */
|
||||
}
|
||||
.informations-produit .onglets-details-produit > ul li a[aria-selected=true] {
|
||||
border-top-color: transparent;
|
||||
}
|
||||
.informations-produit .onglets-details-produit > ul li a:focus, .informations-produit .onglets-details-produit > ul li a:focus-visible {
|
||||
outline-color: transparent;
|
||||
}
|
||||
.informations-produit .onglets-details-produit:has(section:not([hidden])) {
|
||||
grid-template-rows: 12lh min-content;
|
||||
}
|
||||
.informations-produit .onglets-details-produit:has(section:not([hidden])) > ul li a:not([aria-selected=true]) {
|
||||
border-top-color: var(--couleur-noir);
|
||||
}
|
||||
.informations-produit .selecteur-produit {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"version":3,"sourceRoot":"","sources":["../../src/sass/base/polices/_lato.scss","../../src/sass/base/polices/_myriad.scss","../../src/sass/abstracts/_variables.scss","../../src/sass/base/_base.scss","../../src/sass/base/_typographie.scss","../../src/sass/base/elements/_boutons.scss","../../src/sass/base/elements/_images.scss","../../src/sass/base/elements/_liens.scss","../../src/sass/base/elements/_listes.scss","../../src/sass/layouts/_en-tete.scss","../../src/sass/layouts/_menu-categories-produits.scss","../../src/sass/layouts/_colonnes-photos.scss","../../src/sass/layouts/_grille-produits.scss","../../src/sass/layouts/_informations-produit.scss","../../src/sass/layouts/_produits-similaires.scss","../../src/sass/layouts/_pied-de-page.scss"],"names":[],"mappings":";AAAA;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AChGJ;EACE;EACA;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA,KACE;;AChBJ;AACE;EACA;EACA;EACA;EACA;AAEA;EACA;EACA;AAEA;EACA;EACA;AAEA;EACA;EACA;EACA;EACA;EACA;;;AClBF;AAAA;AAAA;AAAA;AAAA;AAKA;EACE;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA;AAAA;AAAA;EAGE;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAIA;EACE;EACA;;;AAGF;AAAA;AAAA;AAGA;AAAA;AAAA;AAAA;EAIE;;;AAGF;AAAA;AAAA;AAGA;EACE;;;ACtDF;EACE;EACA;EACA;;;ACHF;AAAA;AAAA;AAGA;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;ACfJ;AAAA;AAAA;AAAA;AAAA;AAKA;AAAA;EAEE;EACA;;;AAGF;EACE;EACA;;;ACbF;AAAA;AAAA;AAAA;AAAA;AAKA;AACE;EACA;EAEA;EACA;EACA;EACA;EACA;EACA,YACE,kHAK4B;EAE9B;AAEA;AAMA;AAAA;AAAA;;AALA;EAEE;;AAMF;AACE;EACA;EACA;AAEA;EACA;EAEA;EACA;AAEA;AAMA;AAKA;;AAVA;EAEE;;AAIF;EACE;;AAIF;EACE;IACE;;;AAMJ;EACE;IACE;;;;AClER;AAAA;AAAA;AAAA;AAAA;AAKA;EACE;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAMA;AACE;EACA;AAEA;EACA;AAEA;EACA;;AAEA;EACE;EACA,qLAEkE;;;AC5BxE;AACE;EACA;EACA;AAEA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AAWA;;AATA;EACE;;AAEA;AAAA;EAEE;;AAKJ;EACE;EACA;EACA;EACA;EACA;AAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AARA;EACE;EACA;EACA;EACA;EACA;;AAYF;AACE;EACA;AAEA;EACA;EACA;EACA;AAEA;EACA;EAEA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;IACE;;;AAMR;EACE;EACA;EACA;EACA;EACA;AAEA;AAAA;AAAA;;AAGA;EACE;EACA;;AAEA;EACE;;AAGF;EACE;;;ACvGR;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA;AACE;EACA;EACA;AAEA;EACA;EACA;EAEA;EACA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAOA;EACE;EACA;EACA;AAEA;AAAA;AAAA;;AAGA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AAMA;AAAA;AAAA;AAAA;AAAA;;AAJA;EACE;;AAQF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEE;EACA;;AAGF;EACE;IACE;IACA;;;AAKN;EACE;;AAGF;EACE;;;AC/ER;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA;AACE;EACA;AAEA;EACA;EACA;AAAA;AAAA;AAIA;EACA;EAEA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGA;EACE;;AAMF;EACE;;;AC5CR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EAEI;IACE;IACA;IACA;;;AAMR;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;;AC9EV;EACE;EACA;EACA;EACA;EACA;AAoFA;AAyGA;;AA3LA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAKN;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAQV;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;AAEA;AAMA;AAwCA;AAqBA;;AAlEA;EACE;EACA;;AAIF;EACE;AAEA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEI;IACE;IACA;;;AAKN;EAEI;IACE;IACA;;;AAOR;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;IACE;;;AAKN;EACE;;AAeJ;EACE;;AAKJ;EACE;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAGE;EACE;IACE;;;;AAQZ;EACE;IACE;;EAGF;IACE;;;ACnOJ;EACE;EACA;EACA;EACA,qBACE;EAEF;EACA;AAEA;;AACA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EAEI;IACE;IACA;IACA;;;AAMR;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;;AC7FZ;AAAA;AAAA;AAGA;AACE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA","file":"main.css"}
|
||||
{"version":3,"sourceRoot":"","sources":["../../src/sass/base/polices/_lato.scss","../../src/sass/base/polices/_myriad.scss","../../src/sass/abstracts/_variables.scss","../../src/sass/base/_base.scss","../../src/sass/base/_typographie.scss","../../src/sass/base/elements/_boutons.scss","../../src/sass/base/elements/_images.scss","../../src/sass/base/elements/_liens.scss","../../src/sass/base/elements/_listes.scss","../../src/sass/layouts/_en-tete.scss","../../src/sass/layouts/_menu-categories-produits.scss","../../src/sass/layouts/_colonnes-photos.scss","../../src/sass/layouts/_grille-produits.scss","../../src/sass/layouts/_informations-produit.scss","../../src/sass/layouts/_produits-similaires.scss","../../src/sass/layouts/_pied-de-page.scss"],"names":[],"mappings":";AAAA;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,KACE;;AChGJ;EACE;EACA;EACA;EACA;EACA;EACA,KACE;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA,KACE;;AChBJ;AACE;EACA;EACA;EACA;EACA;AAEA;EACA;EACA;AAEA;EACA;EACA;AAEA;EACA;EACA;EACA;EACA;EACA;;;AClBF;AAAA;AAAA;AAAA;AAAA;AAKA;EACE;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA;AAAA;AAAA;EAGE;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAIA;EACE;EACA;;;AAGF;AAAA;AAAA;AAGA;AAAA;AAAA;AAAA;EAIE;;;AAGF;AAAA;AAAA;AAGA;EACE;;;ACtDF;EACE;EACA;EACA;;;ACHF;AAAA;AAAA;AAGA;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;ACfJ;AAAA;AAAA;AAAA;AAAA;AAKA;AAAA;EAEE;EACA;;;AAGF;EACE;EACA;;;ACbF;AAAA;AAAA;AAAA;AAAA;AAKA;AACE;EACA;EAEA;EACA;EACA;EACA;EACA;EACA,YACE,kHAK4B;EAE9B;AAEA;AAMA;AAAA;AAAA;;AALA;EAEE;;AAMF;AACE;EACA;EACA;AAEA;EACA;EAEA;EACA;AAEA;AAMA;AAKA;;AAVA;EAEE;;AAIF;EACE;;AAIF;EACE;IACE;;;AAMJ;EACE;IACE;;;;AClER;AAAA;AAAA;AAAA;AAAA;AAKA;EACE;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAMA;AACE;EACA;AAEA;EACA;AAEA;EACA;;AAEA;EACE;EACA,qLAEkE;;;AC5BxE;AACE;EACA;EACA;AAEA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AAWA;;AATA;EACE;;AAEA;AAAA;EAEE;;AAKJ;EACE;EACA;EACA;EACA;EACA;AAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AARA;EACE;EACA;EACA;EACA;EACA;;AAYF;AACE;EACA;AAEA;EACA;EACA;EACA;AAEA;EACA;EAEA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;IACE;;;AAMR;EACE;EACA;EACA;EACA;EACA;AAEA;AAAA;AAAA;;AAGA;EACE;EACA;;AAEA;EACE;;AAGF;EACE;;;ACvGR;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA;AACE;EACA;EACA;AAEA;EACA;EACA;EAEA;EACA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAOA;EACE;EACA;EACA;AAEA;AAAA;AAAA;;AAGA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AAMA;AAAA;AAAA;AAAA;AAAA;;AAJA;EACE;;AAQF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEE;EACA;;AAGF;EACE;IACE;IACA;;;AAKN;EACE;;AAGF;EACE;;;AC/ER;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA;AACE;EACA;AAEA;EACA;EACA;AAAA;AAAA;AAIA;EACA;EAEA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGA;EACE;;AAMF;EACE;;;AC5CR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EAEI;IACE;IACA;IACA;;;AAMR;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;;AC9EV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA;AACE;EAEA;EAGA;EACA;EAGA;EAEA;EACA;EACA;EACA;EACA;AAuGA;AAyGA;;AA9MA;EACE;EACA;EACA;EACA;EACA;AAEA;AAAA;AAAA;;AAGA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAKN;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;;AACA;EACE;;AAGF;EACE;;AAMR;EACE;;AAEA;EACE;;AAMN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;AAEA;AAMA;AAwCA;AAqBA;;AAlEA;EACE;EACA;;AAIF;EACE;AAEA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEI;IACE;IACA;;;AAKN;EAEI;IACE;IACA;;;AAOR;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;IACE;;;AAKN;EACE;;AAeJ;EACE;;AAKJ;EACE;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAGE;EACE;IACE;;;;AAQZ;EACE;IACE;;EAGF;IACE;;;ACxQJ;EACE;EACA;EACA;EACA,qBACE;EAEF;EACA;AAEA;;AACA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EAEI;IACE;IACA;IACA;;;AAMR;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;;AC7FZ;AAAA;AAAA;AAGA;AACE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA","file":"main.css"}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,17 +1,97 @@
|
|||
{
|
||||
"_Either.js": {
|
||||
"file": "Either.js",
|
||||
"name": "Either"
|
||||
},
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/gaffe.ts": {
|
||||
"file": "gaffe.js",
|
||||
"name": "gaffe",
|
||||
"src": "web/app/themes/haiku-atelier-2024/src/scripts/gaffe.ts",
|
||||
"isEntry": true
|
||||
},
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/api.ts": {
|
||||
"file": "api.js",
|
||||
"name": "api",
|
||||
"src": "web/app/themes/haiku-atelier-2024/src/scripts/lib/api.ts",
|
||||
"isEntry": true,
|
||||
"imports": [
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/constantes.ts",
|
||||
"_Either.js"
|
||||
]
|
||||
},
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/constantes.ts": {
|
||||
"file": "constantes.js",
|
||||
"name": "constantes",
|
||||
"src": "web/app/themes/haiku-atelier-2024/src/scripts/lib/constantes.ts",
|
||||
"isEntry": true
|
||||
},
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/dom.ts": {
|
||||
"file": "dom.js",
|
||||
"name": "dom",
|
||||
"src": "web/app/themes/haiku-atelier-2024/src/scripts/lib/dom.ts",
|
||||
"isEntry": true,
|
||||
"imports": [
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/erreurs.ts",
|
||||
"_Either.js"
|
||||
]
|
||||
},
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/erreurs.ts": {
|
||||
"file": "erreurs.js",
|
||||
"name": "erreurs",
|
||||
"src": "web/app/themes/haiku-atelier-2024/src/scripts/lib/erreurs.ts",
|
||||
"isEntry": true
|
||||
},
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/gestion-panier.ts": {
|
||||
"file": "gestion-panier.js",
|
||||
"name": "gestion-panier",
|
||||
"src": "web/app/themes/haiku-atelier-2024/src/scripts/lib/gestion-panier.ts",
|
||||
"isEntry": true,
|
||||
"imports": [
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/constantes.ts",
|
||||
"_Either.js"
|
||||
]
|
||||
},
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/utils.ts": {
|
||||
"file": "utils.js",
|
||||
"name": "utils",
|
||||
"src": "web/app/themes/haiku-atelier-2024/src/scripts/lib/utils.ts",
|
||||
"isEntry": true,
|
||||
"imports": [
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/dom.ts",
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/erreurs.ts",
|
||||
"_Either.js"
|
||||
]
|
||||
},
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-produit.ts": {
|
||||
"file": "scripts-page-produit.js",
|
||||
"name": "scripts-page-produit",
|
||||
"src": "web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-produit.ts",
|
||||
"isEntry": true,
|
||||
"imports": [
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/constantes.ts",
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/erreurs.ts",
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/utils.ts",
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/types/cart-add-item.ts",
|
||||
"_Either.js",
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/lib/dom.ts"
|
||||
]
|
||||
},
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/types/cart-add-item.ts": {
|
||||
"file": "cart-add-item.js",
|
||||
"name": "cart-add-item",
|
||||
"src": "web/app/themes/haiku-atelier-2024/src/scripts/types/cart-add-item.ts",
|
||||
"isEntry": true
|
||||
},
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/types/cart.ts": {
|
||||
"file": "cart.js",
|
||||
"name": "cart",
|
||||
"src": "web/app/themes/haiku-atelier-2024/src/scripts/types/cart.ts",
|
||||
"isEntry": true
|
||||
},
|
||||
"web/app/themes/haiku-atelier-2024/src/scripts/vite.env.d.ts": {
|
||||
"file": "vite.env.d.js",
|
||||
"name": "vite.env.d",
|
||||
"src": "web/app/themes/haiku-atelier-2024/src/scripts/vite.env.d.ts",
|
||||
"isEntry": true
|
||||
}
|
||||
}
|
||||
2
web/app/themes/haiku-atelier-2024/assets/js/Either.js
Normal file
2
web/app/themes/haiku-atelier-2024/assets/js/Either.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
web/app/themes/haiku-atelier-2024/assets/js/api.js
Normal file
3
web/app/themes/haiku-atelier-2024/assets/js/api.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import{d as S}from"./constantes.js";import{r as F}from"./Either.js";const H="application/json",w="Content-Type",_=Symbol(),P=Symbol();function O(t={}){var e;return(e=Object.entries(t).find(([o])=>o.toLowerCase()===w.toLowerCase()))===null||e===void 0?void 0:e[1]}function R(t){return/^application\/.*json.*/.test(t)}const f=function(t,e,o=!1){return Object.entries(e).reduce((n,[i,l])=>{const h=t[i];return Array.isArray(h)&&Array.isArray(l)?n[i]=o?[...h,...l]:l:typeof h=="object"&&typeof l=="object"?n[i]=f(h,l,o):n[i]=l,n},{...t})},y={options:{},errorType:"text",polyfills:{},polyfill(t,e=!0,o=!1,...n){const i=this.polyfills[t]||(typeof self<"u"?self[t]:null)||(typeof global<"u"?global[t]:null);if(e&&!i)throw new Error(t+" is not defined");return o&&i?new i(...n):i}};function L(t,e=!1){y.options=e?t:f(y.options,t)}function N(t,e=!1){y.polyfills=e?t:f(y.polyfills,t)}function I(t){y.errorType=t}const J=t=>e=>t.reduceRight((o,n)=>n(o),e)||e;class x extends Error{}const U=t=>{const e=Object.create(null);t=t._addons.reduce((r,s)=>s.beforeRequest&&s.beforeRequest(r,t._options,e)||r,t);const{_url:o,_options:n,_config:i,_catchers:l,_resolvers:h,_middlewares:g,_addons:m}=t,p=new Map(l),D=f(i.options,n);let T=o;const j=J(g)((r,s)=>(T=r,i.polyfill("fetch")(r,s)))(o,D),b=new Error,v=j.catch(r=>{throw{[_]:r}}).then(r=>{if(!r.ok){const s=new x;if(s.cause=b,s.stack=s.stack+`
|
||||
CAUSE: `+b.stack,s.response=r,s.url=T,r.type==="opaque")throw s;return r.text().then(a=>{var c;if(s.message=a,i.errorType==="json"||((c=r.headers.get("Content-Type"))===null||c===void 0?void 0:c.split(";")[0])==="application/json")try{s.json=JSON.parse(a)}catch{}throw s.text=a,s.status=r.status,s})}return r}),A=r=>r.catch(s=>{const a=s.hasOwnProperty(_),c=a?s[_]:s,E=c?.status&&p.get(c.status)||p.get(c?.name)||a&&p.has(_)&&p.get(_);if(E)return E(c,t);const C=p.get(P);if(C)return C(c,t);throw c}),d=r=>s=>A(r?v.then(a=>a&&a[r]()).then(a=>s?s(a):a):v.then(a=>s?s(a):a)),M={_wretchReq:t,_fetchReq:j,_sharedState:e,res:d(null),json:d("json"),blob:d("blob"),formData:d("formData"),arrayBuffer:d("arrayBuffer"),text:d("text"),error(r,s){return p.set(r,s),this},badRequest(r){return this.error(400,r)},unauthorized(r){return this.error(401,r)},forbidden(r){return this.error(403,r)},notFound(r){return this.error(404,r)},timeout(r){return this.error(408,r)},internalError(r){return this.error(500,r)},fetchError(r){return this.error(_,r)}},q=m.reduce((r,s)=>({...r,...typeof s.resolver=="function"?s.resolver(r):s.resolver}),M);return h.reduce((r,s)=>s(r,t),q)},k={_url:"",_options:{},_config:y,_catchers:new Map,_resolvers:[],_deferred:[],_middlewares:[],_addons:[],addon(t){return{...this,_addons:[...this._addons,t],...t.wretch}},errorType(t){return{...this,_config:{...this._config,errorType:t}}},polyfills(t,e=!1){return{...this,_config:{...this._config,polyfills:e?t:f(this._config.polyfills,t)}}},url(t,e=!1){if(e)return{...this,_url:t};const o=this._url.split("?");return{...this,_url:o.length>1?o[0]+t+"?"+o[1]:this._url+t}},options(t,e=!1){return{...this,_options:e?t:f(this._options,t)}},headers(t){const e=t?Array.isArray(t)?Object.fromEntries(t):"entries"in t?Object.fromEntries(t.entries()):t:{};return{...this,_options:f(this._options,{headers:e})}},accept(t){return this.headers({Accept:t})},content(t){return this.headers({[w]:t})},auth(t){return this.headers({Authorization:t})},catcher(t,e){const o=new Map(this._catchers);return o.set(t,e),{...this,_catchers:o}},catcherFallback(t){return this.catcher(P,t)},resolve(t,e=!1){return{...this,_resolvers:e?[t]:[...this._resolvers,t]}},defer(t,e=!1){return{...this,_deferred:e?[t]:[...this._deferred,t]}},middlewares(t,e=!1){return{...this,_middlewares:e?t:[...this._middlewares,...t]}},fetch(t=this._options.method,e="",o=null){let n=this.url(e).options({method:t});const i=O(n._options.headers),l=this._config.polyfill("FormData",!1),h=typeof o=="object"&&!(l&&o instanceof l)&&(!n._options.headers||!i||R(i));return n=o?h?n.json(o,i):n.body(o):n,U(n._deferred.reduce((g,m)=>m(g,g._url,g._options),n))},get(t=""){return this.fetch("GET",t)},delete(t=""){return this.fetch("DELETE",t)},put(t,e=""){return this.fetch("PUT",e,t)},post(t,e=""){return this.fetch("POST",e,t)},patch(t,e=""){return this.fetch("PATCH",e,t)},head(t=""){return this.fetch("HEAD",t)},opts(t=""){return this.fetch("OPTIONS",t)},body(t){return{...this,_options:{...this._options,body:t}}},json(t,e){const o=O(this._options.headers);return this.content(e||R(o)&&o||H).body(JSON.stringify(t))}};function u(t="",e={}){return{...k,_url:t,_options:e}}u.default=u;u.options=L;u.errorType=I;u.polyfills=N;u.WretchError=x;fetch(S,{credentials:"same-origin",headers:{"Content-Type":"application/json"},method:"GET",mode:"same-origin",signal:AbortSignal.timeout(5e3)}).then(F);u(S).content("application/json").options({credentials:"same-origin",mode:"same-origin",signal:AbortSignal.timeout(5e3)}).get().json().catch();
|
||||
//# sourceMappingURL=api.js.map
|
||||
1
web/app/themes/haiku-atelier-2024/assets/js/api.js.map
Normal file
1
web/app/themes/haiku-atelier-2024/assets/js/api.js.map
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,2 @@
|
|||
var y;function g(e){return{lang:e?.lang??y?.lang,message:e?.message,abortEarly:e?.abortEarly??y?.abortEarly,abortPipeEarly:e?.abortPipeEarly??y?.abortPipeEarly}}var E;function d(e){return E?.get(e)}var k;function _(e){return k?.get(e)}var A;function I(e,s){return A?.get(e)?.get(s)}function S(e){const s=typeof e;return s==="string"?`"${e}"`:s==="number"||s==="bigint"||s==="boolean"?`${e}`:s==="object"||s==="function"?(e&&Object.getPrototypeOf(e)?.constructor?.name)??"null":s}function c(e,s,r,n,t){const i=r.value,o=e.expects??null,u=S(i),l={kind:e.kind,type:e.type,input:i,expected:o,received:u,message:`Invalid ${s}: ${o?`Expected ${o} but r`:"R"}eceived ${u}`,requirement:e.requirement,path:t?.path,issues:t?.issues,lang:n.lang,abortEarly:n.abortEarly,abortPipeEarly:n.abortPipeEarly},a=e.kind==="schema",f=e.message??I(e.reference,l.lang)??(a?_(l.lang):null)??n.message??d(l.lang);f&&(l.message=typeof f=="function"?f(l):f),a&&(r.typed=!1),r.issues?r.issues.push(l):r.issues=[l]}var j=class extends Error{issues;constructor(e){super(e[0].message),this.name="ValiError",this.issues=e}};function C(e,s,r){return typeof e.default=="function"?e.default(s,r):e.default}function b(e,s){return{kind:"schema",type:"array",reference:b,expects:"Array",async:!1,item:e,message:s,_run(r,n){const t=r.value;if(Array.isArray(t)){r.typed=!0,r.value=[];for(let i=0;i<t.length;i++){const o=t[i],u=this.item._run({typed:!1,value:o},n);if(u.issues){const l={type:"array",origin:"value",input:t,key:i,value:o};for(const a of u.issues)a.path?a.path.unshift(l):a.path=[l],r.issues?.push(a);if(r.issues||(r.issues=u.issues),n.abortEarly){r.typed=!1;break}}u.typed||(r.typed=!1),r.value.push(u.value)}}else c(this,"type",r,n);return r}}}function v(e){return{kind:"schema",type:"number",reference:v,expects:"number",async:!1,message:e,_run(s,r){return typeof s.value=="number"&&!isNaN(s.value)?s.typed=!0:c(this,"type",s,r),s}}}function m(e,s){return{kind:"schema",type:"object",reference:m,expects:"Object",async:!1,entries:e,message:s,_run(r,n){const t=r.value;if(t&&typeof t=="object"){r.typed=!0,r.value={};for(const i in this.entries){const o=t[i],u=this.entries[i]._run({typed:!1,value:o},n);if(u.issues){const l={type:"object",origin:"value",input:t,key:i,value:o};for(const a of u.issues)a.path?a.path.unshift(l):a.path=[l],r.issues?.push(a);if(r.issues||(r.issues=u.issues),n.abortEarly){r.typed=!1;break}}u.typed||(r.typed=!1),(u.value!==void 0||i in t)&&(r.value[i]=u.value)}}else c(this,"type",r,n);return r}}}function p(e,...s){const r={kind:"schema",type:"optional",reference:p,expects:`(${e.expects} | undefined)`,async:!1,wrapped:e,_run(n,t){return n.value===void 0&&("default"in this&&(n.value=C(this,n,t)),n.value===void 0)?(n.typed=!0,n):this.wrapped._run(n,t)}};return 0 in s&&(r.default=s[0]),r}function h(e){return{kind:"schema",type:"string",reference:h,expects:"string",async:!1,message:e,_run(s,r){return typeof s.value=="string"?s.typed=!0:c(this,"type",s,r),s}}}function $(e,s,r){const n=e._run({typed:!1,value:s},g(r));if(n.issues)throw new j(n.issues);return n.value}const P=m({attribute:h(),value:h()}),x=m({id:p(v()),quantity:p(v()),variation:p(b(P))}),W=e=>$(x,e);export{W};
|
||||
//# sourceMappingURL=cart-add-item.js.map
|
||||
File diff suppressed because one or more lines are too long
1
web/app/themes/haiku-atelier-2024/assets/js/cart.js
Normal file
1
web/app/themes/haiku-atelier-2024/assets/js/cart.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
//# sourceMappingURL=cart.js.map
|
||||
1
web/app/themes/haiku-atelier-2024/assets/js/cart.js.map
Normal file
1
web/app/themes/haiku-atelier-2024/assets/js/cart.js.map
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"cart.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
const t="aria-selected",T="hidden",a=".compte-panier a[rel='cart']",s="#selecteur-variation",_="#bouton-ajout-panier",E="wp-json",c=`/${E}/wc/store/cart`,o=`/${E}/wc/store/cart/add-item`;export{t as A,o as R,a as S,s as a,_ as b,T as c,c as d};
|
||||
//# sourceMappingURL=constantes.js.map
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"constantes.js","sources":["../../src/scripts/lib/constantes.ts"],"sourcesContent":["export const ATTRIBUT_ARIA_SELECTED = \"aria-selected\";\nexport const ATTRIBUT_ARIA_HIDDEN = \"aria-hidden\";\nexport const ATTRIBUT_HIDDEN = \"hidden\";\n\nexport const SELECTEUR_BOUTON_PANIER = \".compte-panier a[rel='cart']\";\nexport const SELECTEUR_SELECTEUR_QUANTITE = \"#selecteur-variation\";\nexport const SELECTEUR_BOUTON_AJOUT_PANIER = \"#bouton-ajout-panier\";\n\nexport const CHEMIN_API_REST = \"wp-json\";\nexport const ROUTE_API_PANIER = `/${CHEMIN_API_REST}/wc/store/cart`;\nexport const ROUTE_API_AJOUTE_ARTICLE_PANIER = `/${CHEMIN_API_REST}/wc/store/cart/add-item`;\n"],"names":["ATTRIBUT_ARIA_SELECTED","ATTRIBUT_HIDDEN","SELECTEUR_BOUTON_PANIER","SELECTEUR_SELECTEUR_QUANTITE","SELECTEUR_BOUTON_AJOUT_PANIER","CHEMIN_API_REST","ROUTE_API_PANIER","ROUTE_API_AJOUTE_ARTICLE_PANIER"],"mappings":"AAAO,MAAMA,EAAyB,gBAEzBC,EAAkB,SAElBC,EAA0B,+BAC1BC,EAA+B,uBAC/BC,EAAgC,uBAEhCC,EAAkB,UAClBC,EAAmB,IAAID,CAAe,iBACtCE,EAAkC,IAAIF,CAAe"}
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
const l=t=>r=>{const e=Array.from(t.querySelectorAll(r));if(!e||e.length===0)throw new Error(`La requête "${r}" n'a débouché sur aucun Élément.`);return e};export{l as s};
|
||||
import{c as u,E as c,a as h}from"./erreurs.js";import{E as p,r as y,l as E}from"./Either.js";var x={done:!1,hasNext:!1};function S(e,...r){let t=e,l=r.map(i=>"lazy"in i?A(i):void 0),n=0;for(;n<r.length;){if(l[n]===void 0||!d(t)){let a=r[n];t=a(t),n+=1;continue}let i=[];for(let a=n;a<r.length;a++){let o=l[a];if(o===void 0||(i.push(o),o.isSingle))break}let s=[];for(let a of t)if(g(a,s,i))break;let{isSingle:f}=i.at(-1);t=f?s[0]:s,n+=i.length}return t}function g(e,r,t){if(t.length===0)return r.push(e),!1;let l=e,n=x,i=!1;for(let[s,f]of t.entries()){let{index:a,items:o}=f;if(o.push(l),n=f(l,a,o),f.index+=1,n.hasNext){if(n.hasMany??!1){for(let m of n.next)if(g(m,r,t.slice(s+1)))return!0;return i}l=n.next}if(!n.hasNext)break;n.done&&(i=!0)}return n.hasNext&&r.push(l),i}function A(e){let{lazy:r,lazyArgs:t}=e,l=r(...t);return Object.assign(l,{isSingle:r.single??!1,index:0,items:[]})}function d(e){return typeof e=="string"||typeof e=="object"&&e!==null&&Symbol.iterator in e}function N(e){return e!==null}function b(e){return e===void 0?!0:typeof e=="string"||Array.isArray(e)?e.length===0:Object.keys(e).length===0}const _=e=>r=>p.encase(()=>e.querySelector(r)).mapLeft(t=>u(c(r))).chain(t=>N(t)?y(t):E(u(h(r)))),k=e=>r=>p.encase(()=>S(e.querySelectorAll(r),Array.from)).mapLeft(t=>u(c(r))).chain(t=>b(t)?E(u(h(r))):y(t));export{k as a,_ as r};
|
||||
//# sourceMappingURL=dom.js.map
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
2
web/app/themes/haiku-atelier-2024/assets/js/erreurs.js
Normal file
2
web/app/themes/haiku-atelier-2024/assets/js/erreurs.js
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
const r=e=>`Le selecteur "${e}" est invalide`,E=e=>`La requête "${e}" n'a retourné aucun Élément.`,t=e=>new SyntaxError(e),n=e=>{throw e};export{r as E,E as a,t as c,n as l};
|
||||
//# sourceMappingURL=erreurs.js.map
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"erreurs.js","sources":["../../src/scripts/lib/erreurs.ts"],"sourcesContent":["/**\n * Fonctions pour la création d'Erreurs.\n */\n\n/* Messages d'erreur */\nexport const ERREUR_SYNTAXE_INVALIDE: (selecteur: string) => string = (selecteur) =>\n `Le selecteur \"${selecteur}\" est invalide`;\nexport const ERREUR_SELECTEUR_INEXISTANT: (selecteur: string) => string = (selecteur) =>\n `La requête \"${selecteur}\" n'a retourné aucun Élément.`;\n\n/* Création d'erreurs */\nexport const creeSyntaxError: (message: string) => SyntaxError = (message) => new SyntaxError(message);\n\nexport const leveErreur: (erreur: Error) => never = (erreur) => {\n throw erreur;\n};\n"],"names":["ERREUR_SYNTAXE_INVALIDE","selecteur","ERREUR_SELECTEUR_INEXISTANT","creeSyntaxError","message","leveErreur","erreur"],"mappings":"AAKO,MAAMA,EAA0DC,GACrE,iBAAiBA,CAAS,iBACfC,EAA8DD,GACzE,eAAeA,CAAS,gCAGbE,EAAqDC,GAAY,IAAI,YAAYA,CAAO,EAExFC,EAAwCC,GAAW,CACxD,MAAAA,CACR"}
|
||||
9
web/app/themes/haiku-atelier-2024/assets/js/gaffe.js
Normal file
9
web/app/themes/haiku-atelier-2024/assets/js/gaffe.js
Normal file
File diff suppressed because one or more lines are too long
1
web/app/themes/haiku-atelier-2024/assets/js/gaffe.js.map
Normal file
1
web/app/themes/haiku-atelier-2024/assets/js/gaffe.js.map
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,2 @@
|
|||
import{d as g}from"./constantes.js";import{E as h,r as o,l as f,M,n as u,j as c}from"./Either.js";var l;const y={liftEither(i){if(i.isRight())return Promise.resolve(i.extract());throw i.extract()},fromPromise(i){return i.then(y.liftEither)},throwE(i){throw i}};class m{constructor(t){this.runPromise=t,this[l]="EitherAsync",this["fantasy-land/chain"]=this.chain,this["fantasy-land/alt"]=this.alt,this.then=(r,e)=>this.run().then(r,e)}leftOrDefault(t){return this.run().then(r=>r.leftOrDefault(t))}orDefault(t){return this.run().then(r=>r.orDefault(t))}join(){return n(async t=>{const r=await this;if(r.isRight()){const e=await r.extract();return t.liftEither(e)}return t.liftEither(r)})}ap(t){return n(async r=>{const e=await t;if(e.isRight()){const a=await this.run();return a.isRight()?e.extract()(a.extract()):r.liftEither(a)}return r.liftEither(e)})}alt(t){return n(async r=>{const e=await this.run();if(e.isRight())return e.extract();{const a=await t;return r.liftEither(a)}})}extend(t){return n(async r=>{const e=await this.run();if(e.isRight()){const a=n.liftEither(e);return r.liftEither(o(t(a)))}return r.liftEither(e)})}async run(){try{return o(await this.runPromise(y))}catch(t){return f(t)}}bimap(t,r){return n(async e=>{const a=await this.run();try{return await e.liftEither(a.bimap(t,r))}catch(P){throw await P}})}map(t){return n(r=>this.runPromise(r).then(t))}mapLeft(t){return n(async r=>{try{return await this.runPromise(r)}catch(e){throw await t(e)}})}chain(t){return n(async r=>{const e=await this.runPromise(r);return r.fromPromise(t(e))})}chainLeft(t){return n(async r=>{try{return await this.runPromise(r)}catch(e){return r.fromPromise(t(e))}})}toMaybeAsync(){return s(async({liftMaybe:t})=>{const r=await this.run();return t(r.toMaybe())})}swap(){return n(async t=>{const r=await this.run();return r.isRight()&&t.throwE(r.extract()),t.liftEither(o(r.extract()))})}ifLeft(t){return n(async r=>{const e=await this.run();return e.ifLeft(t),r.liftEither(e)})}ifRight(t){return n(async r=>{const e=await this.run();return e.ifRight(t),r.liftEither(e)})}void(){return this.map(t=>{})}caseOf(t){return this.run().then(r=>r.caseOf(t))}finally(t){return n(({fromPromise:r})=>r(this.run().finally(t)))}}l=Symbol.toStringTag;const n=Object.assign(i=>new m(i),{fromPromise:i=>n(({fromPromise:t})=>t(i())),liftEither:i=>n(({liftEither:t})=>t(i)),lefts:i=>Promise.all(i.map(t=>t.run())).then(h.lefts),rights:i=>Promise.all(i.map(t=>t.run())).then(h.rights),sequence:i=>n(async t=>{let r=[];for await(const e of i){if(e.isLeft())return t.liftEither(e);r.push(e.extract())}return t.liftEither(o(r))}),all:i=>n.fromPromise(async()=>Promise.all(i).then(h.sequence))});m.prototype.constructor=n;var w;const b={liftMaybe(i){if(i.isJust())return Promise.resolve(i.extract());throw u},fromPromise(i){return i.then(b.liftMaybe)}};class E{constructor(t){this.runPromise=t,this[w]="MaybeAsync",this["fantasy-land/chain"]=this.chain,this["fantasy-land/filter"]=this.filter,this["fantasy-land/alt"]=this.alt}orDefault(t){return this.run().then(r=>r.orDefault(t))}join(){return s(async t=>{const r=await this.run();if(r.isJust()){const e=await r.extract();return t.liftMaybe(e)}return t.liftMaybe(u)})}ap(t){return s(async r=>{const e=await t;if(e.isJust()){const a=await this.run();return a.isJust()?e.extract()(a.extract()):r.liftMaybe(u)}return r.liftMaybe(u)})}alt(t){return s(async r=>{const e=await this.run();if(e.isJust())return e.extract();{const a=await t;return r.liftMaybe(a)}})}extend(t){return s(async r=>{const e=await this.run();if(e.isJust()){const a=s.liftMaybe(e);return r.liftMaybe(c(t(a)))}return r.liftMaybe(u)})}filter(t){return s(async r=>{const e=await this.run();return r.liftMaybe(e.filter(t))})}async run(){try{return c(await this.runPromise(b))}catch{return u}}map(t){return s(r=>this.runPromise(r).then(t))}chain(t){return s(async r=>{const e=await this.runPromise(r);return r.fromPromise(t(e))})}toEitherAsync(t){return n(async({liftEither:r})=>{const e=await this.run();return r(e.toEither(t))})}ifJust(t){return s(async r=>{const e=await this.run();return e.ifJust(t),r.liftMaybe(e)})}ifNothing(t){return s(async r=>{const e=await this.run();return e.ifNothing(t),r.liftMaybe(e)})}void(){return this.map(t=>{})}caseOf(t){return this.run().then(r=>r.caseOf(t))}finally(t){return s(({fromPromise:r})=>r(this.run().finally(t)))}then(t,r){return this.run().then(t,r)}}w=Symbol.toStringTag;const s=Object.assign(i=>new E(i),{catMaybes:i=>Promise.all(i).then(M.catMaybes),fromPromise:i=>s(({fromPromise:t})=>t(i())),liftMaybe:i=>s(({liftMaybe:t})=>t(i))});E.prototype.constructor=s;const p=_etats,d=()=>fetch(g,{credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json","X-WC-Store-API-Nonce":p.nonce},method:"GET",mode:"same-origin",signal:AbortSignal.timeout(5e3)}).then(o).catch(f);n.fromPromise(d).map(i=>i.json()).ifLeft(i=>console.error(i));
|
||||
//# sourceMappingURL=gestion-panier.js.map
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,2 +1,2 @@
|
|||
import{s as a}from"./dom.js";const c=o=>{o.forEach(t=>{t[0].setAttribute("aria-selected","false"),t[1].setAttribute("hidden","true")})},d=()=>{const o=a(document)("a[role='tab']"),t=a(document)("section[role='tabpanel']"),r=new Map;o.forEach((e,s)=>{const n=e.getAttribute("id"),i=t[s];if(!n)throw new Error("Le lien ne dispose pas d'ID !");if(!i)throw new Error("Le lien ne dispose pas de section correspondante !");r.set(n,[e,i])}),Array.from(r.values()).forEach(e=>{e[0].addEventListener("click",s=>{s.preventDefault();const n=e[0].getAttribute("aria-selected")==="true";c(Array.from(r.values())),!n&&(e[0].setAttribute("aria-selected","true"),e[1].removeAttribute("hidden"))})}),console.debug(r)};document.addEventListener("DOMContentLoaded",()=>{d()});
|
||||
import{S as p,a as T,b as g,A as E,c as m,R as L}from"./constantes.js";import{l as a}from"./erreurs.js";import{r as d,a as f}from"./utils.js";import{W as O}from"./cart-add-item.js";import{E as h}from"./Either.js";import"./dom.js";const c=n=>n,A=_etats,R=n=>{n.forEach(t=>{t[0].setAttribute(E,"false"),t[1].setAttribute(m,"true")})},I=d(p),_=()=>{const n=f("a[role='tab']").caseOf({Left:a,Right:c}),t=f("section[role='tabpanel']").caseOf({Left:a,Right:c}),o=d(T).caseOf({Left:a,Right:c}),r=d(g).caseOf({Left:a,Right:c}),s=new Map;n.forEach((e,u)=>{const i=e.getAttribute("id"),l=t[u];if(!i)throw new Error("Le lien ne dispose pas d'ID !");if(!l)throw new Error("Le lien ne dispose pas de section correspondante !");s.set(i,[e,l])}),Array.from(s.values()).forEach(e=>{e[0].addEventListener("click",u=>{u.preventDefault();const i=e[0].getAttribute(E)==="true";R(Array.from(s.values())),!i&&(e[0].setAttribute(E,"true"),e[1].removeAttribute(m))})}),o.addEventListener("change",e=>{console.debug(o.value,e)}),r.addEventListener("click",e=>{e.preventDefault(),b()}),console.debug(s)},b=()=>{const n={quantity:1,id:A.idProduit};h.encase(()=>O(n)).ifLeft(t=>console.error(t)).map(t=>{fetch(L,{body:JSON.stringify(t),credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json","X-WC-Store-API-Nonce":A.nonce},method:"POST",mode:"same-origin",signal:AbortSignal.timeout(5e3)}).then(o=>o.json()).then(o=>{I.caseOf({Left:r=>console.error("Le bouton du Panier n'existe pas !",r),Right:r=>{console.debug(r),r.textContent=`cart ${o.items.length}`}})}).catch(o=>console.error(o))})};document.addEventListener("DOMContentLoaded",()=>{_()});
|
||||
//# sourceMappingURL=scripts-page-produit.js.map
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
2
web/app/themes/haiku-atelier-2024/assets/js/utils.js
Normal file
2
web/app/themes/haiku-atelier-2024/assets/js/utils.js
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
import{r as e,a as r}from"./dom.js";import"./erreurs.js";import"./Either.js";const o=r(document),n=e(document);export{o as a,n as r};
|
||||
//# sourceMappingURL=utils.js.map
|
||||
1
web/app/themes/haiku-atelier-2024/assets/js/utils.js.map
Normal file
1
web/app/themes/haiku-atelier-2024/assets/js/utils.js.map
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"utils.js","sources":["../../src/scripts/lib/utils.ts"],"sourcesContent":["import type { Either } from \"purify-ts\";\nimport { recupereElementAvecSelecteur, recupereElementsAvecSelecteur } from \"./dom\";\n\nexport const recupereElementsDocument: (selecteur: string) => Either<SyntaxError, Element[]> =\n recupereElementsAvecSelecteur(document);\n\nexport const recupereElementDocument: <E extends Element = Element>(selecteur: string) => Either<SyntaxError, E> =\n recupereElementAvecSelecteur(document);\n"],"names":["recupereElementAvecSelecteur","recupereElementsAvecSelecteur","recupereElementsDocument","recupereElementDocument"],"mappings":"AAGa,OAAA,KAAAA,EAAA,KAAAC,MAAA,WAAA,MAAA,eAAA,MAAA,cAAA,MAAAC,EACXD,EAA8B,QAAQ,EAE3BE,EACXH,EAA6B,QAAQ"}
|
||||
|
|
@ -0,0 +1 @@
|
|||
//# sourceMappingURL=vite.env.d.js.map
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"vite.env.d.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
||||
|
|
@ -19,23 +19,21 @@ $produits_collection = array_map(
|
|||
"recupere_informations_produit_page_produit",
|
||||
recupere_produits_meme_collection($produit["collection"])($produit["id"]),
|
||||
);
|
||||
$nonce = wp_create_nonce("wc_store_api");
|
||||
|
||||
$contexte["produit"] = $produit;
|
||||
$contexte["produits_collection"] = $produits_collection;
|
||||
|
||||
/* echo "<pre>";
|
||||
print_r($produit);
|
||||
echo "</pre>"; */
|
||||
$contexte["nonce"] = $nonce;
|
||||
|
||||
/**
|
||||
* 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 = [],
|
||||
$ver = filemtime(get_template_directory() . "/assets/js/scripts-page-produit.js"),
|
||||
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"),
|
||||
);
|
||||
}
|
||||
add_action("wp_enqueue_scripts", "charge_scripts_page_produit");
|
||||
|
|
|
|||
|
|
@ -1,25 +1,46 @@
|
|||
// Styles pour la boîte flottante des Informations sur le Produit
|
||||
|
||||
/**
|
||||
* Boîte flottante avec les informations Produit, le sélecteur de variation et de quantité pour le
|
||||
* Panier.
|
||||
*
|
||||
* 1. Flotte toujours en bas de la page et s'arrête avant les Produits de la même collection.
|
||||
* 2. Conteneur existant pour que le flottement sticky fonctionne ; n'a pas de dimensions.
|
||||
*/
|
||||
.informations-produit {
|
||||
position: sticky;
|
||||
bottom: 1rem;
|
||||
/* Variables */
|
||||
// Couleurs
|
||||
--boite-couleur-fond: rgb(255 255 255 / 90%);
|
||||
|
||||
// Dimensions et positions
|
||||
--boite-position-basse: 1rem;
|
||||
--boite-longueur: 70ch;
|
||||
|
||||
// Marges
|
||||
--section-marges-internes: 1rem;
|
||||
|
||||
position: sticky; /* 1 */
|
||||
bottom: var(--boite-position-basse); /* 1 */
|
||||
overflow: visible;
|
||||
width: 0;
|
||||
height: 0;
|
||||
width: 0; /* 2 */
|
||||
height: 0; /* 2 */
|
||||
|
||||
&__conteneur {
|
||||
transform: translate(calc(50vw - 35ch), -100%);
|
||||
transform: translate(calc(50vw - var(--boite-longueur) / 2), -100%);
|
||||
display: grid;
|
||||
width: 70ch;
|
||||
max-width: 70ch;
|
||||
width: var(--boite-longueur);
|
||||
max-width: var(--boite-longueur);
|
||||
border: 1px solid var(--couleur-noir);
|
||||
|
||||
/**
|
||||
* Définis les apparence et comportement de toutes les sections de la boîte.
|
||||
*/
|
||||
> section {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
height: 100%;
|
||||
padding: 1rem;
|
||||
background: rgb(255 255 255 / 90%);
|
||||
padding: var(--section-marges-internes);
|
||||
background: var(--boite-couleur-fond);
|
||||
|
||||
+ section {
|
||||
border-top: 1px solid var(--couleur-noir);
|
||||
|
|
@ -30,12 +51,13 @@
|
|||
.onglets-details-produit {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
grid-template-rows: 1fr min-content;
|
||||
grid-template-rows: auto min-content;
|
||||
padding: initial;
|
||||
|
||||
> section {
|
||||
overflow-y: auto;
|
||||
grid-column: span 3;
|
||||
padding: 1rem;
|
||||
padding: var(--section-marges-internes);
|
||||
font-weight: 350;
|
||||
|
||||
&[hidden] {
|
||||
|
|
@ -64,29 +86,44 @@
|
|||
li {
|
||||
width: 100%;
|
||||
|
||||
&:first-of-type a {
|
||||
border-right-color: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
&:last-of-type a {
|
||||
border-right-color: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: var(--espace-xs) 0;
|
||||
border-top: 1px solid var(--couleur-noir);
|
||||
border-top: 1px solid transparent;
|
||||
border-right: 1px solid var(--couleur-noir);
|
||||
border-left: 1px solid var(--couleur-noir);
|
||||
|
||||
&:first-of-type {
|
||||
border-left: initial;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
border-left: initial;
|
||||
}
|
||||
|
||||
/* Quand l'onglet est sélectionné */
|
||||
&[aria-selected="true"] {
|
||||
border-top-color: transparent;
|
||||
}
|
||||
|
||||
&:focus, &:focus-visible {
|
||||
outline-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:has(section:not([hidden])) {
|
||||
grid-template-rows: 12lh min-content;
|
||||
|
||||
> ul li a:not([aria-selected="true"]) {
|
||||
border-top-color: var(--couleur-noir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Nom du Produit, sélecteur de variation et prix du Produit */
|
||||
|
|
|
|||
67
web/app/themes/haiku-atelier-2024/src/scripts/gaffe.ts
Normal file
67
web/app/themes/haiku-atelier-2024/src/scripts/gaffe.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Initialise GlitchTip.
|
||||
*/
|
||||
|
||||
import {
|
||||
breadcrumbsIntegration,
|
||||
BrowserClient,
|
||||
createTransport,
|
||||
dedupeIntegration,
|
||||
defaultStackParser,
|
||||
functionToStringIntegration,
|
||||
getCurrentScope,
|
||||
globalHandlersIntegration,
|
||||
httpContextIntegration,
|
||||
linkedErrorsIntegration,
|
||||
} from "@sentry/browser";
|
||||
import type { Transport } from "@sentry/types";
|
||||
|
||||
const makeFetchTransport = (options): Transport => {
|
||||
const makeRequest = async (request) => {
|
||||
const requestOptions: RequestInit = {
|
||||
body: request.body,
|
||||
headers: options.headers,
|
||||
method: "POST",
|
||||
mode: "no-cors",
|
||||
referrerPolicy: "no-referrer",
|
||||
...options.fetchOptions,
|
||||
};
|
||||
|
||||
const response = await fetch(options.url, requestOptions);
|
||||
return ({
|
||||
headers: {
|
||||
"x-sentry-rate-limits": response.headers.get("X-Sentry-Rate-Limits"),
|
||||
"retry-after": response.headers.get("Retry-After"),
|
||||
},
|
||||
statusCode: response.status,
|
||||
});
|
||||
};
|
||||
|
||||
return createTransport(options, makeRequest);
|
||||
};
|
||||
|
||||
/* Créé la configuration Sentry */
|
||||
const client = new BrowserClient({
|
||||
dsn: import.meta.env.VITE_GLITCHTIP_NSD,
|
||||
environment: "local",
|
||||
integrations: [
|
||||
breadcrumbsIntegration(),
|
||||
dedupeIntegration(),
|
||||
functionToStringIntegration(),
|
||||
globalHandlersIntegration(),
|
||||
httpContextIntegration(),
|
||||
linkedErrorsIntegration(),
|
||||
],
|
||||
stackParser: defaultStackParser,
|
||||
tracesSampleRate: 0.01,
|
||||
transport: makeFetchTransport,
|
||||
});
|
||||
|
||||
/* Initialise la configuration */
|
||||
getCurrentScope().setClient(client);
|
||||
client.init();
|
||||
|
||||
/* TODO: Retirer une fois les tests réalisés */
|
||||
setTimeout(() => {
|
||||
throw new Error("Test GlitchTip !");
|
||||
}, 3000);
|
||||
65
web/app/themes/haiku-atelier-2024/src/scripts/lib/api.ts
Normal file
65
web/app/themes/haiku-atelier-2024/src/scripts/lib/api.ts
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import { Right } from "purify-ts";
|
||||
import wretch from "wretch";
|
||||
import { ROUTE_API_PANIER } from "./constantes";
|
||||
|
||||
export const get = async (
|
||||
url: string,
|
||||
input: Record<string, string>,
|
||||
) => {
|
||||
return fetch(
|
||||
`${url}?${new URLSearchParams(input).toString()}`,
|
||||
);
|
||||
};
|
||||
|
||||
export const post = async (
|
||||
url: string,
|
||||
input: Record<string, string>,
|
||||
) => {
|
||||
return fetch(url, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
};
|
||||
|
||||
type CreateAPIMethod = <
|
||||
Input extends Record<string, string>,
|
||||
Output,
|
||||
>(opts: {
|
||||
url: string;
|
||||
method: "GET" | "POST";
|
||||
}) => (input: Input) => Promise<Output>;
|
||||
|
||||
const createAPIMethod: CreateAPIMethod = (opts) => (input) => {
|
||||
const method = opts.method === "GET" ? get : post;
|
||||
|
||||
return (
|
||||
method(opts.url, input)
|
||||
// Imagine error handling here...
|
||||
.then((res) => res.json())
|
||||
);
|
||||
};
|
||||
const requeteRecuperationPanierUtilisateur = fetch(
|
||||
ROUTE_API_PANIER,
|
||||
{
|
||||
credentials: "same-origin",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
method: "GET",
|
||||
mode: "same-origin",
|
||||
signal: AbortSignal.timeout(5000),
|
||||
},
|
||||
).then(Right);
|
||||
|
||||
const recuperePanierUtilisateur = wretch(ROUTE_API_PANIER)
|
||||
.content("application/json")
|
||||
.options({
|
||||
credentials: "same-origin",
|
||||
mode: "same-origin",
|
||||
signal: AbortSignal.timeout(5000),
|
||||
})
|
||||
.get()
|
||||
.json()
|
||||
.catch();
|
||||
|
||||
/**
|
||||
* Récupération du Panier. Pas de paramètres, juste une requête GET.
|
||||
*/
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
export const ATTRIBUT_ARIA_SELECTED = "aria-selected";
|
||||
export const ATTRIBUT_ARIA_HIDDEN = "aria-hidden";
|
||||
export const ATTRIBUT_HIDDEN = "hidden";
|
||||
|
||||
export const SELECTEUR_BOUTON_PANIER = ".compte-panier a[rel='cart']";
|
||||
export const SELECTEUR_SELECTEUR_QUANTITE = "#selecteur-variation";
|
||||
export const SELECTEUR_BOUTON_AJOUT_PANIER = "#bouton-ajout-panier";
|
||||
|
||||
export const CHEMIN_API_REST = "wp-json";
|
||||
export const ROUTE_API_PANIER = `/${CHEMIN_API_REST}/wc/store/cart`;
|
||||
export const ROUTE_API_AJOUTE_ARTICLE_PANIER = `/${CHEMIN_API_REST}/wc/store/cart/add-item`;
|
||||
|
|
@ -1,16 +1,69 @@
|
|||
export const safeQuerySelector = (parent: Document | Element) => (query: string) => {
|
||||
const element: Element | null = parent.querySelector(query);
|
||||
if (!element) throw new Error(`La requête "${query}" n'a débouché sur aucun Élément.`);
|
||||
import { Either, Left, Right } from "purify-ts";
|
||||
import { isEmpty, isNonNull, isNullish, pipe } from "remeda";
|
||||
import { creeSyntaxError, ERREUR_SELECTEUR_INEXISTANT, ERREUR_SYNTAXE_INVALIDE } from "./erreurs";
|
||||
|
||||
/** Type union des parents possible pour un `querySelector`. */
|
||||
type ElementParent = Document | Element;
|
||||
|
||||
/**
|
||||
* @param parent L'Élément parent dans lequel l'Élément souhaité sera recherché.
|
||||
* @param selecteur Le sélecteur de l'Élément recherché.
|
||||
*
|
||||
* @throws Une Erreur si aucun Élément n'a été trouvé.
|
||||
* @returns Un Élément.
|
||||
*/
|
||||
export const safeQuerySelector: (parent: ElementParent) => (selecteur: string) => Element = (parent) => (selecteur) => {
|
||||
const element: Element | null = parent.querySelector(selecteur);
|
||||
|
||||
if (!element) throw new DOMException(ERREUR_SELECTEUR_INEXISTANT(selecteur));
|
||||
return element;
|
||||
};
|
||||
|
||||
export const safeQuerySelectorAll = (parent: Document | Element) => (query: string) => {
|
||||
const elements: Element[] = Array.from(parent.querySelectorAll(query));
|
||||
if (!elements || elements.length === 0) throw new Error(`La requête "${query}" n'a débouché sur aucun Élément.`);
|
||||
return elements;
|
||||
};
|
||||
/**
|
||||
* @param parent L'Élément parent dans lequel l'Élément souhaité sera recherché.
|
||||
* @param selecteur Le sélecteur de l'Élément recherché.
|
||||
*
|
||||
* @returns Un tableau pouvant être vide d'Éléments.
|
||||
*/
|
||||
export const safeQuerySelectorAll: (parent: ElementParent) => (selecteur: string) => Element[] =
|
||||
(parent) => (selecteur) => {
|
||||
const elements: Element[] = Array.from(parent.querySelectorAll(selecteur));
|
||||
|
||||
export const estDansLaVue = (element: Element) => {
|
||||
if (isEmpty(elements)) {
|
||||
throw new DOMException(ERREUR_SELECTEUR_INEXISTANT(selecteur));
|
||||
}
|
||||
return elements;
|
||||
};
|
||||
|
||||
// export const recupereElementAvecSelecteur: (
|
||||
// parent: ElementParent,
|
||||
// ) => <T extends Element = Element>(selecteur: string) => Either<SyntaxError, T> = (parent) => (selecteur) =>
|
||||
export const recupereElementAvecSelecteur =
|
||||
(parent: ElementParent) => <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)))
|
||||
// Retourne une SyntaxError si l'Élément est null
|
||||
.chain((e: E | null) => isNonNull(e) ? Right(e) : Left(creeSyntaxError(ERREUR_SELECTEUR_INEXISTANT(selecteur))));
|
||||
|
||||
export const recupereElementsAvecSelecteur: (
|
||||
parent: ElementParent,
|
||||
) => (selecteur: string) => Either<SyntaxError, Element[]> = (parent) => (selecteur) =>
|
||||
Either
|
||||
// Retourne une SyntaxError dans un Left si le sélecteur est invalide
|
||||
.encase(() => pipe(parent.querySelectorAll(selecteur), Array.from<Element>))
|
||||
// Transforme le Left en une erreur plus sympathique
|
||||
.mapLeft(_ => creeSyntaxError(ERREUR_SYNTAXE_INVALIDE(selecteur)))
|
||||
// Retourne une SyntaxError si le tableau est vide
|
||||
.chain(e => isEmpty(e) ? Left(creeSyntaxError(ERREUR_SELECTEUR_INEXISTANT(selecteur))) : Right(e));
|
||||
|
||||
/**
|
||||
* @param element
|
||||
* @returns Un booléen
|
||||
*/
|
||||
export const estDansLaVue: (element: Element) => boolean = (element) => {
|
||||
const rect: DOMRect = element.getBoundingClientRect();
|
||||
|
||||
return (
|
||||
|
|
|
|||
16
web/app/themes/haiku-atelier-2024/src/scripts/lib/erreurs.ts
Normal file
16
web/app/themes/haiku-atelier-2024/src/scripts/lib/erreurs.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Fonctions pour la création d'Erreurs.
|
||||
*/
|
||||
|
||||
/* Messages d'erreur */
|
||||
export const ERREUR_SYNTAXE_INVALIDE: (selecteur: string) => string = (selecteur) =>
|
||||
`Le selecteur "${selecteur}" est invalide`;
|
||||
export const ERREUR_SELECTEUR_INEXISTANT: (selecteur: string) => string = (selecteur) =>
|
||||
`La requête "${selecteur}" n'a retourné aucun Élément.`;
|
||||
|
||||
/* Création d'erreurs */
|
||||
export const creeSyntaxError: (message: string) => SyntaxError = (message) => new SyntaxError(message);
|
||||
|
||||
export const leveErreur: (erreur: Error) => never = (erreur) => {
|
||||
throw erreur;
|
||||
};
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Fonctions liées à la gestion du Panier.
|
||||
*/
|
||||
|
||||
import { Either, EitherAsync, identity, Left, Right } from "purify-ts";
|
||||
import { ROUTE_API_PANIER } from "./constantes";
|
||||
|
||||
/** États utiles pour les scripts. */
|
||||
type Etats = {
|
||||
/** Un nonce pour l'authentification de requêtes API */
|
||||
nonce: string;
|
||||
};
|
||||
|
||||
// @ts-expect-error - États injectés par le modèle PHP
|
||||
const ETATS: Etats = _etats;
|
||||
|
||||
const requeteRecuperePanier = (): Promise<Either<Error, Response>> =>
|
||||
fetch(
|
||||
ROUTE_API_PANIER,
|
||||
{
|
||||
credentials: "same-origin",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"X-WC-Store-API-Nonce": ETATS.nonce,
|
||||
},
|
||||
method: "GET",
|
||||
mode: "same-origin",
|
||||
signal: AbortSignal.timeout(5000),
|
||||
},
|
||||
)
|
||||
.then(Right)
|
||||
.catch(Left);
|
||||
|
||||
export const recuperePanier = EitherAsync
|
||||
.fromPromise(requeteRecuperePanier)
|
||||
.map(a => a.json())
|
||||
.ifLeft(e => console.error(e));
|
||||
109
web/app/themes/haiku-atelier-2024/src/scripts/lib/test.lol.ts
Normal file
109
web/app/themes/haiku-atelier-2024/src/scripts/lib/test.lol.ts
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import { Either, Left, Right } from "fp-ts/lib/Either";
|
||||
import { Errors, Type } from "io-ts";
|
||||
import { reporter } from "io-ts-reporters";
|
||||
|
||||
export async function fetchJson<T, O, I>(
|
||||
url: string,
|
||||
validator: Type<T, O, I>,
|
||||
init?: RequestInit,
|
||||
): Promise<Either<Error, T>> {
|
||||
try {
|
||||
const response = await fetch(url, init);
|
||||
const json: I = await response.json();
|
||||
const result = validator.decode(json);
|
||||
return result.fold<Either<Error, T>>(
|
||||
(errors: Errors) => {
|
||||
const messages = reporter(result);
|
||||
return new Left<Error, T>(new Error(messages.join("\n")));
|
||||
},
|
||||
(value: T) => {
|
||||
return new Right<Error, T>(value);
|
||||
},
|
||||
);
|
||||
} catch (err) {
|
||||
return Promise.resolve(new Left<Error, T>(err));
|
||||
}
|
||||
}
|
||||
|
||||
// the promise is never rejected
|
||||
// we handle the error with Either
|
||||
const readMailFromCli = async (): Promise<
|
||||
Either<{ errorReason: string }, string>
|
||||
> => {
|
||||
const rl = readline.createInterface({ input, output });
|
||||
return rl
|
||||
.question("Please enter your email \n")
|
||||
.then(Right)
|
||||
.catch((error) => Left({ errorReason: error.message }))
|
||||
.finally(() => {
|
||||
rl.close();
|
||||
});
|
||||
};
|
||||
|
||||
const validateEmail = (
|
||||
email: string,
|
||||
): Either<{ errorReason: string }, Email> => {
|
||||
if (!email.includes("@")) {
|
||||
return Left({ errorReason: "The email does not contain an @ character" });
|
||||
}
|
||||
|
||||
if (email.length < 3) {
|
||||
return Left({ errorReason: "The email be at least 3 characters long" });
|
||||
}
|
||||
|
||||
return Right(email);
|
||||
};
|
||||
|
||||
const getSessionIdFromEmail = (
|
||||
email: Email,
|
||||
): Promise<Either<{ errorReason: string }, SessionId>> => {
|
||||
// let’s simulate an API call
|
||||
return Promise.resolve(Right("12345"));
|
||||
};
|
||||
|
||||
const printInformations = ({
|
||||
email,
|
||||
sessionId,
|
||||
}: {
|
||||
email: Email;
|
||||
sessionId: SessionId;
|
||||
}): void => {
|
||||
console.log(`Email: ${email}; SessionId: ${sessionId}`);
|
||||
};
|
||||
|
||||
const main = async (): Promise<void> => {
|
||||
const eitherEmailFromInput = await readMailFromCli(); // Returns an Either type
|
||||
|
||||
const eitherEmail = eitherEmailFromInput.map(validateEmail); // map over the either to validate the email
|
||||
|
||||
eitherEmail.caseOf({
|
||||
Left: (error) => console.log(error.errorReason), // email is invalid
|
||||
Right: async (email) => {
|
||||
const eitherSessionId = await getSessionIdFromEmail(email);
|
||||
eitherSessionId.caseOf({
|
||||
Left: (error) => console.log(error.errorReason), // getting the sessionId failed
|
||||
Right: (sessionId) => {
|
||||
printInformations({ sessionId, email });
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const flow = EitherAsync<{ errorReason: string }, void>(
|
||||
async ({ liftEither, fromPromise }) => {
|
||||
const emailFromInput = await fromPromise(readMailFromCli());
|
||||
const email = await liftEither(validateEmail(emailFromInput));
|
||||
const sessionId = await fromPromise(getSessionIdFromEmail(email));
|
||||
printInformations({ sessionId, email });
|
||||
},
|
||||
);
|
||||
|
||||
const main2 = async () => {
|
||||
const result = await flow.run();
|
||||
result.ifLeft((error) => {
|
||||
console.log(error.errorReason);
|
||||
});
|
||||
};
|
||||
|
||||
main();
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import type { Either } from "purify-ts";
|
||||
import { recupereElementAvecSelecteur, recupereElementsAvecSelecteur } from "./dom";
|
||||
|
||||
export const recupereElementsDocument: (selecteur: string) => Either<SyntaxError, Element[]> =
|
||||
recupereElementsAvecSelecteur(document);
|
||||
|
||||
export const recupereElementDocument: <E extends Element = Element>(selecteur: string) => Either<SyntaxError, E> =
|
||||
recupereElementAvecSelecteur(document);
|
||||
|
|
@ -1,19 +1,68 @@
|
|||
// Scripts pour la Page Produit
|
||||
|
||||
import { safeQuerySelectorAll } from "./lib/dom.js";
|
||||
import { Either, identity } from "purify-ts";
|
||||
import {
|
||||
ATTRIBUT_ARIA_SELECTED,
|
||||
ATTRIBUT_HIDDEN,
|
||||
ROUTE_API_AJOUTE_ARTICLE_PANIER,
|
||||
SELECTEUR_BOUTON_AJOUT_PANIER,
|
||||
SELECTEUR_BOUTON_PANIER,
|
||||
SELECTEUR_SELECTEUR_QUANTITE,
|
||||
} from "./lib/constantes";
|
||||
import { leveErreur } from "./lib/erreurs";
|
||||
import { recupereElementDocument, recupereElementsDocument } from "./lib/utils";
|
||||
import { WCStoreCartAddItemArgs } from "./types/cart-add-item";
|
||||
|
||||
/** États utiles pour les scripts de la page. */
|
||||
type Etats = {
|
||||
/** L'ID en base de données du Produit. */
|
||||
idProduit: number;
|
||||
/** Un nonce pour l'authentification de requêtes API */
|
||||
nonce: string;
|
||||
};
|
||||
type EnsembleLienContenu = [Element, Element];
|
||||
|
||||
const fermeToutesSections = (ensembleLiensContenus: EnsembleLienContenu[]) => {
|
||||
ensembleLiensContenus.forEach((ensemble) => {
|
||||
ensemble[0].setAttribute("aria-selected", "false");
|
||||
ensemble[1].setAttribute("hidden", "true");
|
||||
// @ts-expect-error - États injectés par le modèle PHP
|
||||
const ETATS: Etats = _etats;
|
||||
|
||||
/**
|
||||
* Déplie toutes les sections de la Boîte des Informations Produit en ajustant les attributs
|
||||
* correspondants.
|
||||
*/
|
||||
const deplieToutesSections: (ensembleLiensContenus: EnsembleLienContenu[]) => void = (ensembleLiensContenus) => {
|
||||
ensembleLiensContenus.forEach(ensemble => {
|
||||
ensemble[0].setAttribute(ATTRIBUT_ARIA_SELECTED, "false");
|
||||
ensemble[1].setAttribute(ATTRIBUT_HIDDEN, "true");
|
||||
});
|
||||
};
|
||||
|
||||
// Éléments d'intérêt
|
||||
/** Le « Bouton » vers le Panier dont le texte est un indicateur du nombre de Produits dedans. */
|
||||
const BOUTON_PANIER: Either<SyntaxError, HTMLAnchorElement> = recupereElementDocument<HTMLAnchorElement>(
|
||||
SELECTEUR_BOUTON_PANIER,
|
||||
);
|
||||
|
||||
const gereBoiteInformationsProduit = () => {
|
||||
const liensOnglets: Element[] = safeQuerySelectorAll(document)("a[role='tab']");
|
||||
const sectionsContenus: Element[] = safeQuerySelectorAll(document)("section[role='tabpanel']");
|
||||
/* Récupère les Éléments intéressants */
|
||||
const liensOnglets: Element[] = recupereElementsDocument("a[role='tab']").caseOf({
|
||||
Left: leveErreur,
|
||||
Right: identity,
|
||||
});
|
||||
const sectionsContenus: Element[] = recupereElementsDocument("section[role='tabpanel']").caseOf({
|
||||
Left: leveErreur,
|
||||
Right: identity,
|
||||
});
|
||||
const selecteurQuantite: HTMLSelectElement = recupereElementDocument<HTMLSelectElement>(SELECTEUR_SELECTEUR_QUANTITE)
|
||||
.caseOf({
|
||||
Left: leveErreur,
|
||||
Right: identity,
|
||||
});
|
||||
const boutonAjoutPanier: HTMLButtonElement = recupereElementDocument<HTMLButtonElement>(SELECTEUR_BOUTON_AJOUT_PANIER)
|
||||
.caseOf({
|
||||
Left: leveErreur,
|
||||
Right: identity,
|
||||
});
|
||||
|
||||
const onglets = new Map<string, EnsembleLienContenu>();
|
||||
|
||||
/* Créé la Map avec les ensembles Lien-Contenu */
|
||||
|
|
@ -35,21 +84,74 @@ const gereBoiteInformationsProduit = () => {
|
|||
e.preventDefault();
|
||||
|
||||
/* Sauvegarde l'état d'ouverture de la section avant de toutes les fermer */
|
||||
const estAncienOngletCourant: boolean = v[0].getAttribute("aria-selected") === "true";
|
||||
fermeToutesSections(Array.from(onglets.values()));
|
||||
const estAncienOngletCourant: boolean = v[0].getAttribute(ATTRIBUT_ARIA_SELECTED) === "true";
|
||||
deplieToutesSections(Array.from(onglets.values()));
|
||||
|
||||
/* Ne fais rien de plus si l'onglet sélectionné était le courant */
|
||||
if (estAncienOngletCourant) return;
|
||||
|
||||
/* Ouvre le nouvel onglet sélectionné */
|
||||
v[0].setAttribute("aria-selected", "true");
|
||||
v[1].removeAttribute("hidden");
|
||||
v[0].setAttribute(ATTRIBUT_ARIA_SELECTED, "true");
|
||||
v[1].removeAttribute(ATTRIBUT_HIDDEN);
|
||||
});
|
||||
});
|
||||
|
||||
/* Ajout des Écouteurs d'Événements */
|
||||
selecteurQuantite.addEventListener("change", (e) => {
|
||||
/* e peut être null ou "--" ou autre chose */
|
||||
console.debug(selecteurQuantite.value, e);
|
||||
});
|
||||
boutonAjoutPanier.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
ajouteProduitAuPanier();
|
||||
});
|
||||
|
||||
console.debug(onglets);
|
||||
};
|
||||
|
||||
// TODO: Traiter le cas des Produits avec variations
|
||||
const ajouteProduitAuPanier = () => {
|
||||
const requeteInvalide: WCStoreCartAddItemArgs = {
|
||||
quantity: 1,
|
||||
id: ETATS.idProduit,
|
||||
};
|
||||
|
||||
// TODO: Traiter les cas d'erreurs avec ts-pattern
|
||||
/* Exécution de la requête */
|
||||
Either
|
||||
.encase<Error, WCStoreCartAddItemArgs>(() => WCStoreCartAddItemArgs(requeteInvalide))
|
||||
.ifLeft(e => console.error(e))
|
||||
.map(r => {
|
||||
fetch(
|
||||
ROUTE_API_AJOUTE_ARTICLE_PANIER,
|
||||
{
|
||||
body: JSON.stringify(r),
|
||||
credentials: "same-origin",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"X-WC-Store-API-Nonce": ETATS.nonce,
|
||||
},
|
||||
method: "POST",
|
||||
mode: "same-origin",
|
||||
signal: AbortSignal.timeout(5000),
|
||||
},
|
||||
)
|
||||
.then(a => a.json())
|
||||
.then(a => {
|
||||
BOUTON_PANIER
|
||||
.caseOf({
|
||||
Left: (e) => console.error("Le bouton du Panier n'existe pas !", e),
|
||||
Right: (r) => {
|
||||
console.debug(r);
|
||||
r.textContent = `cart ${a.items.length}`;
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch(b => console.error(b));
|
||||
});
|
||||
};
|
||||
|
||||
/* Fonctions utilitaires */
|
||||
|
||||
// const creeObservateurIntersection = (element: Element, options: IntersectionObserverInit, classe = "anime") => {
|
||||
|
|
@ -76,4 +178,5 @@ const gereBoiteInformationsProduit = () => {
|
|||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
gereBoiteInformationsProduit();
|
||||
// recuperePanierUtilisateur();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
import * as v from "valibot";
|
||||
|
||||
const WCStoreCartAddItemArgsItemsSchema = v.object({
|
||||
/** Variation attribute name. */
|
||||
attribute: v.string(),
|
||||
/** Variation attribute value. */
|
||||
value: v.string(),
|
||||
});
|
||||
|
||||
const WCStoreCartAddItemArgsSchema = v.object({
|
||||
/** The basket item product or variation ID. */
|
||||
id: v.optional(v.number()),
|
||||
/** Quantity of this item to add to the basket. */
|
||||
quantity: v.optional(v.number()),
|
||||
/** Chosen attributes (for variations). */
|
||||
variation: v.optional(v.array(WCStoreCartAddItemArgsItemsSchema)),
|
||||
});
|
||||
|
||||
export type WCStoreCartAddItemArgsItems = v.InferOutput<typeof WCStoreCartAddItemArgsItemsSchema>;
|
||||
export type WCStoreCartAddItemArgs = v.InferOutput<typeof WCStoreCartAddItemArgsSchema>;
|
||||
|
||||
export const WCStoreCartAddItemArgs: (args: unknown) => WCStoreCartAddItemArgs = (args) =>
|
||||
v.parse(WCStoreCartAddItemArgsSchema, args);
|
||||
12
web/app/themes/haiku-atelier-2024/src/scripts/vite.env.d.ts
vendored
Normal file
12
web/app/themes/haiku-atelier-2024/src/scripts/vite.env.d.ts
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
/** URL du site. */
|
||||
readonly VITE_URL: string;
|
||||
/** URL du endpoint pour le report d'Erreurs au service GlitchTip. */
|
||||
readonly VITE_GLITCHTIP_NSD: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|
||||
|
|
@ -69,7 +69,7 @@
|
|||
|
||||
<section class="actions-produit">
|
||||
{# TODO: Ajouter au Panier sans rafraîchir la Page #}
|
||||
<button class="bouton-case-pleine desactive" type="button">Add to cart</button>
|
||||
<button class="bouton-case-pleine desactive" id="bouton-ajout-panier" type="button">Add to cart</button>
|
||||
</section>
|
||||
</div>
|
||||
</aside>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,23 @@
|
|||
{% extends "base.twig" %}
|
||||
|
||||
{% block head %}
|
||||
<script>
|
||||
// Injection d'états pour les Scripts de la page.
|
||||
|
||||
/**
|
||||
* @typedef {Object} Etats - États utiles pour les scripts de la page.
|
||||
* @property {number} idProduit - L'ID en base de données du Produit.
|
||||
* @property {string} nonce - Un nonce pour l'authentification de requêtes API.
|
||||
*/
|
||||
|
||||
/** @type {Etats} */
|
||||
const _etats = {
|
||||
idProduit: {{ produit.id }},
|
||||
nonce: "{{ nonce }}",
|
||||
};
|
||||
</script>
|
||||
{% endblock head %}
|
||||
|
||||
{% block contenu %}
|
||||
{# Menu des catégories de Produits #}
|
||||
{% include "parts/menu-categories-produits.twig" %}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue