2024-08-09

This commit is contained in:
gcch 2024-08-09 18:47:38 +02:00
commit bd804e6083
20 changed files with 392 additions and 26 deletions

View file

@ -1 +0,0 @@
/var/www/html/web/app/plugins/query-monitor/wp-content/db.php

View file

@ -2,6 +2,9 @@
declare(strict_types=1);
use Carbon_Fields\Carbon_Fields;
use Carbon_Fields\Container\Container;
use Carbon_Fields\Field\Field;
use HaikuAtelier\StarterSite;
use Timber\Timber;
@ -31,6 +34,10 @@ add_action("wp_enqueue_scripts", "charge_styles_haiku_atelier_2024");
// Initialise les fonctionnalités du thème
new StarterSite();
/**
* Personnalisation du thème
*/
// Personnalisation du thème
function enregistre_personnalisation_theme($wp_customize) {
// Section « Réseaux sociaux »
@ -74,5 +81,50 @@ function enregistre_personnalisation_theme($wp_customize) {
}
add_action("customize_register", "enregistre_personnalisation_theme");
/**
* WooCommerce
*/
function retire_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);
}
add_action("after_setup_theme", "retire_images_produit_woocommerce");
function retire_champs_admin_images_produit_woocommerce(): void {
// Désactive le champ « Image Produit »
remove_meta_box("postimagediv", "product", "side");
// Désactive le champ « Galerie d'images du Produit »
remove_meta_box("woocommerce-product-images", "product", "side");
}
add_action("add_meta_boxes", "retire_champs_admin_images_produit_woocommerce", 40);
// Désactive les styles WooCommerce
add_filter("woocommerce_enqueue_styles", "__return_empty_array");
/**
* Carbon Fields
*/
function cree_galeries_photos_produit_woocommerce(): void {
Container::make("post_meta", "Photos Galleries")
->where("post_type", "=", "product")
->add_fields([
Field::make("media_gallery", "photos_colonne_gauche", __("Left Column Photos"))
->set_type(["image"])
->set_duplicates_allowed(false),
Field::make("media_gallery", "photos_colonne_droite", __("Right Column Photos"))
->set_type(["image"])
->set_duplicates_allowed(false),
]);
}
add_action("carbon_fields_register_fields", "cree_galeries_photos_produit_woocommerce");
// 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();
}
add_action("after_setup_theme", "charge_carbon_fields");

View file

@ -5,6 +5,6 @@ declare(strict_types=1);
use Timber\Timber;
$contexte = Timber::context();
$modeles = ["index.twig"];
$modeles = ["base.twig"];
Timber::render($filenames = $modeles, $data = $contexte);

View file

@ -9,26 +9,25 @@ use Timber\Timber;
// Contexte et modèles
$contexte = Timber::context();
$modeles = ["shop.twig"];
$modeles = ["boutique.twig"];
// Récupère les Produits
$recupere_informations_produit = fn($produit) => [
"id" => $produit->id,
"illustration" => [
"image" => wp_get_attachment_image(get_post_thumbnail_id($produit->id), "full"),
],
"nom" => $produit->name,
"prix" => $produit->price,
"slug" => $produit->slug,
"premiere_variation_image" => wp_get_attachment_image(
$attachment_id = $produit->get_available_variations()[0]["image_id"],
$size = "large",
$attr = ["loading" => false],
"id" => $produit->get_id(),
"nom" => $produit->get_name(),
"prix" => $produit->get_price(),
"slug" => $produit->get_slug(),
"premiere_photo_gauche" => wp_get_attachment_image(
get_post_meta($post_id = $produit->get_id(), $key = "_photos_colonne_gauche|||0|value")[0],
"full",
false,
["loading" => false],
),
"deuxieme_variation_image" => wp_get_attachment_image(
$attachment_id = $produit->get_available_variations()[1]["image_id"],
$size = "large",
$attr = ["loading" => false],
"premiere_photo_droite" => wp_get_attachment_image(
get_post_meta($post_id = $produit->get_id(), $key = "_photos_colonne_droite|||0|value")[0],
"full",
false,
["loading" => false],
),
"url" => $produit->get_permalink(),
];
@ -40,10 +39,10 @@ $informations_produits = wc_get_products([
$produits = array_map($callback = $recupere_informations_produit, $array = $informations_produits);
$contexte["produits"] = $produits;
echo "<pre>";
// echo "<pre>";
// print_r($informations_produits);
// print_r($produits);
echo "</pre>";
// echo "</pre>";
// Rendu
Timber::render($filenames = $modeles, $data = $contexte);

View file

@ -0,0 +1,52 @@
<?php
/**
* Le modèle de la Page d'un Produit.
*/
declare(strict_types=1);
use Timber\Timber;
// Contexte et modèles
$contexte = Timber::context();
$modeles = ["produit.twig"];
// Récupère les Produits
function genere_balise_img($id_image) {
return wp_get_attachment_image($attachment_id = $id_image, $size = "full");
}
function recupere_informations_produit($donnees_produit) {
return [
"id" => $donnees_produit->get_id(),
"nom" => $donnees_produit->get_name(),
"prix" => $donnees_produit->get_price(),
"photos_colonne_gauche" => array_map(
$callback = "genere_balise_img",
get_post_meta($post_id = $donnees_produit->get_id(), $key = "_photos_colonne_gauche|||0|value"),
),
"photos_colonne_droite" => array_map(
$callback = "genere_balise_img",
get_post_meta($post_id = $donnees_produit->get_id(), $key = "_photos_colonne_droite|||0|value"),
),
"slug" => $donnees_produit->get_slug(),
"url" => $donnees_produit->get_permalink(),
];
}
$produit = recupere_informations_produit(wc_get_product());
$contexte["produit"] = $produit;
// Charge les scripts de la Page
function charge_scripts_page_produit() {
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"),
);
}
add_action("wp_enqueue_scripts", "charge_scripts_page_produit");
// Rendu
Timber::render($filenames = $modeles, $data = $contexte);

View file

@ -11,6 +11,10 @@
--police-lato: "Lato", sans-serif;
--police-myriad: "Myriad", sans-serif;
/* Dimensions */
--en-tete-hauteur: 60px;
--menu-categories-produits-hauteur: 54.39px;
/* Espacements */
--espace-xs: 0.25rem; // 4px;
--espace-s: 0.5rem; // 8px

View file

@ -0,0 +1,71 @@
// Styles pour les colonnes de photos d'une Page Produit
.photos-produit {
/* Positions */
--colonne-gauche-position-haut: var(--menu-categories-produits-hauteur);
/* Dimensions */
--colonne-gauche-photo-hauteur: calc(100vh - var(--menu-categories-produits-hauteur));
--colonne-droite-photo-hauteur-minimale: calc(
100vh + var(--en-tete-hauteur) + var(--menu-categories-produits-hauteur)
);
/* Marges */
--section-marges-externes-bloc-fin: 1rem;
// position: relative;
display: flex;
flex-flow: column nowrap;
align-items: center;
width: 100%;
// margin-bottom: 1rem;
&__conteneur {
display: flex;
flex-flow: row wrap;
justify-content: center;
> section {
position: relative;
display: flex;
flex-flow: column nowrap;
width: 50%;
&.colonne-gauche {
position: sticky;
top: var(--colonne-gauche-position-haut);
height: var(--colonne-gauche-photo-hauteur);
figure {
height: 100%;
picture {
height: 100%;
img {
height: 100%;
}
}
}
}
&.colonne-droite {
figure {
picture {
img {
&:only-child {
min-height: var(--colonne-droite-photo-hauteur-minimale);
}
}
}
}
}
}
}
img {
height: 100%;
object-fit: cover;
}
}

View file

@ -6,13 +6,18 @@
--en-tete-marges-internes-bloc: var(--espace-m);
/* Dimensions */
--en-tete-hauteur: 80px;
--en-tete-logo-longueur: 100px;
--en-tete-section-hauteur: var(--en-tete-hauteur);
--en-tete-logo-longueur: 80px;
position: fixed;
z-index: 20;
top: 0;
display: flex;
flex-flow: row nowrap;
place-items: center;
justify-content: space-between;
min-width: 100vw;
max-width: 100vw;
height: var(--en-tete-hauteur);
padding: var(--en-tete-marges-internes-bloc) var(--en-tete-marges-internes-ligne);
background: var(--couleur-gris);

View file

@ -36,6 +36,7 @@
.produit__illustration__survol {
visibility: visible;
opacity: 1;
transition: 0.3s opacity, 0.3s visibility;
}
}
}
@ -54,7 +55,7 @@
height: 100%;
visibility: hidden;
opacity: 0;
transition: 0.2s opacity, 0.2s visibility;
transition: 0.15s opacity, 0.15s visibility;
}
img {

View file

@ -0,0 +1,36 @@
// Styles pour la boîte flottante des Informations sur le Produit
.informations-produit {
position: sticky;
bottom: 0;
overflow: visible;
width: 0;
height: 0;
background-color: rgb(0 0 0 / 50%);
&__conteneur {
transform: translate(calc(50vw - 35ch), -100%);
display: grid;
grid-auto-rows: 1fr;
width: 70ch;
max-width: 70ch;
height: 180px;
background: rgb(255 255 255 / 80%);
border: 1px solid var(--couleur-noir);
section {
display: flex;
flex-flow: row nowrap;
padding: 1rem;
+ section {
border-top: 1px solid var(--couleur-noir);
}
}
}
}
.produits-similaires {
position: relative;
margin-top: 80px;
}

View file

@ -1,12 +1,23 @@
// Styles pour le menu des Catégories de Produits
/**
* Le menu avec les Catégories de Produits pour une navigation rapide.
*
* 1. Applique une marge supérieure égale à la hauteur de l'en-tête pour qu'elle puisse s'afficher
* correctement.
*/
#menu-categories-produits {
/* Dimensions */
--menu-entree-longueur-minimale: 13ch;
--menu-section-hauteur: var(--menu-categories-produits-hauteur);
/* Marges */
--menu-section-marges-bloc-debut: var(--en-tete-hauteur); /* 1 */
--menu-entree-marges-internes-ligne: var(--espace-m);
height: var(--menu-section-hauteur);
margin-top: var(--menu-section-marges-bloc-debut); /* 1 */
/**
* Liste des Catégories de Produits.
*

View file

@ -12,7 +12,7 @@
grid-template-columns: 1fr 1fr;
place-items: center;
align-self: end;
min-width: 100vw;
max-width: 100vw;
padding: var(--pied-de-page-marges-internes-bloc) var(--pied-de-page-marges-internes-ligne);
line-height: 1.5;
background: var(--couleur-jaune);

View file

@ -14,6 +14,8 @@
// 3. Régions
@use "layouts/en-tete" as en-tete;
@use "layouts/colonnes-photos" as colonnes-photos;
@use "layouts/grille-produits" as grille-produits;
@use "layouts/informations-produit" as informations-produit;
@use "layouts/menu-categories-produits" as menu-categories-produits;
@use "layouts/pied-de-page" as pied-de-page;

View file

@ -0,0 +1,50 @@
// Scripts pour la Page Produit
const CLASSE_POSITION_FIXE: string = "position-fixe";
const CLASSE_INFORMATIONS_PRODUIT = "informations-produit";
const CLASSE_PRODUITS_SIMILAIRES = "produits-similaires";
/* Fonctions utilitaires */
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.`);
return element;
};
export const estDansLaVue = (element: Element) => {
const rect: DOMRect = element.getBoundingClientRect();
return (
rect.top >= 0
&& rect.left >= 0
&& rect.top <= (window.innerHeight || document.documentElement.clientHeight)
&& rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
// const creeObservateurIntersection = (element: Element, options: IntersectionObserverInit, classe = "anime") => {
// const observateur = new IntersectionObserver(entrees => {
// for (const entree of entrees) {
// const cible = entree.target;
// /* Enclenchement de l'animation */
// if (entree.isIntersecting || estDansLaVue(cible)) {
// cible.classList.add(classe);
// return;
// }
// /* Empêche que le cycle ne se répète */
// if (cible.classList.contains(classe)) {
// observateur.unobserve(cible);
// }
// }
// }, options || {});
// observateur.observe(element);
// return observateur;
// };
document.addEventListener("DOMContentLoaded", () => {
// gereBoiteInformationsProduit();
});

View file

@ -0,0 +1,26 @@
{# Boîte flottante contenant les informations sur le Produit, en détails, et le sélecteur de quantité/taille pour l'ajout au Panier #}
<aside aria-label="Product's details, size and quantity selection" class="informations-produit">
<div class="informations-produit__conteneur">
<section class="details-produit"></section>
<section class="selecteur-produit">
<h3>Boroboro Silver Ring</h3>
<label for="selection-variation-produit">Select size:</label>
<select name="variations" id="selection-variation-produit">
<option value="50">50</option>
<option value="52">52</option>
<option value="54">54</option>
<option value="56">56</option>
<option value="58">58</option>
<option value="60">60</option>
<option value="62">62</option>
</select>
</section>
<section class="actions-produit">
<button type="button">Add to cart</button>
</section>
</div>
</aside>

View file

@ -0,0 +1,20 @@
<section aria-label="Products in the same Collection" class="produits-similaires">
<header>From the same Collection</header>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Ad labore quisquam nisi corporis impedit eos a. Maiores,
perspiciatis error! Tenetur incidunt repudiandae fugit beatae dicta debitis corrupti nesciunt pariatur aperiam!
</p>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Ad labore quisquam nisi corporis impedit eos a. Maiores,
perspiciatis error! Tenetur incidunt repudiandae fugit beatae dicta debitis corrupti nesciunt pariatur aperiam!
</p>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Ad labore quisquam nisi corporis impedit eos a. Maiores,
perspiciatis error! Tenetur incidunt repudiandae fugit beatae dicta debitis corrupti nesciunt pariatur aperiam!
</p>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Ad labore quisquam nisi corporis impedit eos a. Maiores,
perspiciatis error! Tenetur incidunt repudiandae fugit beatae dicta debitis corrupti nesciunt pariatur aperiam!
</p>
</section>

View file

@ -5,11 +5,11 @@
<figure>
<a href="{{ produit.url }}">
<picture class="produit__illustration produit__illustration__principale">
{# {{ produit.illustration.image }} #} {{ produit.premiere_variation_image }}
{{ produit.premiere_photo_gauche }}
</picture>
<picture class="produit__illustration produit__illustration__survol">
{# {{ produit.illustration.image }} #} {{ produit.deuxieme_variation_image }}
{{ produit.premiere_photo_droite }}
</picture>
</a>

View file

@ -0,0 +1,37 @@
{% extends "base.twig" %}
{% block contenu %}
{# Menu avec les catégories de produits #}
{% include "parts/menu-categories-produits.twig" %}
{# Illustrations du Produit #}
<main class="photos-produit">
<div class="photos-produit__conteneur">
<section aria-label="Photo of the Product alone" class="colonne-gauche">
{% for photo in produit.photos_colonne_gauche %}
<figure>
<picture>
{{ photo }}
</picture>
</figure>
{% endfor %}
</section>
<section aria-label="Photos of the Product worn" class="colonne-droite">
{% for photo in produit.photos_colonne_droite %}
<figure>
<picture>
{{ photo }}
</picture>
</figure>
{% endfor %}
</section>
</div>
</main>
{# Boîte des Informations du Produit #}
{% include "parts/pages/produit/informations-produit.twig" %}
{# Produits similaires, généralement ceux de la même Collection #}
{% include "parts/pages/produit/produits-similaires.twig" %}
{% endblock contenu %}