2026-04-05
This commit is contained in:
parent
5f835ca4e6
commit
949195caf8
71 changed files with 535 additions and 458 deletions
|
|
@ -22,7 +22,8 @@ $templates = ['404.twig'];
|
|||
*
|
||||
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
|
||||
*/
|
||||
function load_page_resources(): void {
|
||||
function load_page_resources(): void
|
||||
{
|
||||
Resource::enqueue_style_file(
|
||||
handle: 'haiku-atelier-2024-styles-page-a-propos',
|
||||
path: '/assets/css/pages/page-modele-simple.css',
|
||||
|
|
@ -31,7 +32,4 @@ function load_page_resources(): void {
|
|||
|
||||
add_action('wp_enqueue_scripts', load_page_resources(...));
|
||||
|
||||
Timber::render(
|
||||
data: $context,
|
||||
filenames: $templates,
|
||||
);
|
||||
Timber::render(data: $context, filenames: $templates);
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@ $templates = ['boutique.twig'];
|
|||
/** @var list<WC_Product> $wc_products Les informations brutes des Produits. */
|
||||
$wc_products = wc_get_products(['limit' => 12, 'order' => 'DESC', 'orderby' => 'date', 'status' => 'publish']);
|
||||
|
||||
$products = array_map(
|
||||
callback: Product::new(...),
|
||||
array: $wc_products,
|
||||
);
|
||||
$products = array_map(callback: Product::new(...), array: $wc_products);
|
||||
$context['products'] = $products;
|
||||
|
||||
/**
|
||||
|
|
@ -37,7 +34,8 @@ $context['products'] = $products;
|
|||
*
|
||||
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
|
||||
*/
|
||||
function load_page_resources(): void {
|
||||
function load_page_resources(): void
|
||||
{
|
||||
Resource::enqueue_style_file(
|
||||
handle: 'haiku-atelier-2024-styles-page-boutique',
|
||||
path: '/assets/css/pages/page-boutique.css',
|
||||
|
|
@ -54,7 +52,4 @@ function load_page_resources(): void {
|
|||
|
||||
add_action('wp_enqueue_scripts', load_page_resources(...));
|
||||
|
||||
Timber::render(
|
||||
data: $context,
|
||||
filenames: $templates,
|
||||
);
|
||||
Timber::render(data: $context, filenames: $templates);
|
||||
|
|
|
|||
|
|
@ -11,18 +11,18 @@ jQuery(document).ready(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;
|
||||
var tinyMCEMediaButtons = _wpCustomizeSettings.controls[$(this).attr("id")].skyrocketmediabuttons;
|
||||
const tinyMCEToolbar1String = _wpCustomizeSettings.controls[$(this).attr("id")].skyrockettinymcetoolbar1;
|
||||
const tinyMCEToolbar2String = _wpCustomizeSettings.controls[$(this).attr("id")].skyrockettinymcetoolbar2;
|
||||
const tinyMCEMediaButtons = _wpCustomizeSettings.controls[$(this).attr("id")].skyrocketmediabuttons;
|
||||
|
||||
wp.editor.initialize($(this).attr("id"), {
|
||||
mediaButtons: tinyMCEMediaButtons,
|
||||
quicktags: true,
|
||||
tinymce: {
|
||||
wpautop: true,
|
||||
toolbar1: tinyMCEToolbar1String,
|
||||
toolbar2: tinyMCEToolbar2String,
|
||||
},
|
||||
quicktags: true,
|
||||
mediaButtons: tinyMCEMediaButtons,
|
||||
});
|
||||
});
|
||||
$(document).on("tinymce-editor-init", function (event, editor) {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ $templates = ['accueil.twig'];
|
|||
*
|
||||
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
|
||||
*/
|
||||
function load_page_resources(): void {
|
||||
function load_page_resources(): void
|
||||
{
|
||||
Resource::enqueue_style_file(
|
||||
handle: 'haiku-atelier-2024-styles-page-accueil',
|
||||
path: '/assets/css/pages/page-accueil.css',
|
||||
|
|
@ -35,7 +36,4 @@ function load_page_resources(): void {
|
|||
|
||||
add_action('wp_enqueue_scripts', load_page_resources(...));
|
||||
|
||||
Timber::render(
|
||||
data: $context,
|
||||
filenames: $templates,
|
||||
);
|
||||
Timber::render(data: $context, filenames: $templates);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ Timber::init();
|
|||
Timber::$dirname = ['views'];
|
||||
|
||||
// Charge les Scripts du thème (report d'erreurs)
|
||||
function load_scripts(): void {
|
||||
function load_scripts(): void
|
||||
{
|
||||
// wp_enqueue_script_module(
|
||||
// id: 'haiku-atelier-2024-gaffe',
|
||||
// deps: [],
|
||||
|
|
@ -52,7 +53,8 @@ function load_scripts(): void {
|
|||
add_action('wp_enqueue_scripts', 'load_scripts');
|
||||
|
||||
// Charge les styles du thème
|
||||
function charge_styles_haiku_atelier_2024(): void {
|
||||
function charge_styles_haiku_atelier_2024(): void
|
||||
{
|
||||
wp_enqueue_style(
|
||||
handle: 'haiku-atelier-2024-styles',
|
||||
src: get_template_directory_uri() . '/assets/css/main.css',
|
||||
|
|
@ -70,7 +72,8 @@ new StarterSite();
|
|||
/**
|
||||
* Personnalisation du thème.
|
||||
*/
|
||||
function enregistre_personnalisations_theme(mixed $wp_customize): void {
|
||||
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'),
|
||||
|
|
@ -144,7 +147,8 @@ function enregistre_personnalisations_theme(mixed $wp_customize): void {
|
|||
|
||||
add_action('customize_register', 'enregistre_personnalisations_theme');
|
||||
|
||||
function retire_tailles_image_par_defaut(mixed $sizes): mixed {
|
||||
function retire_tailles_image_par_defaut(mixed $sizes): mixed
|
||||
{
|
||||
/** @var list<string> */
|
||||
$targets = ['full', 'thumbnail'];
|
||||
|
||||
|
|
@ -177,7 +181,8 @@ add_filter('should_load_remote_block_patterns', '__return_false');
|
|||
*/
|
||||
|
||||
// Charge Carbon Fields
|
||||
function charge_carbon_fields(): void {
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,4 @@ use Timber\Timber;
|
|||
$context = Timber::context();
|
||||
$templates = ['base.twig'];
|
||||
|
||||
Timber::render(
|
||||
data: $context,
|
||||
filenames: $templates,
|
||||
);
|
||||
Timber::render(data: $context, filenames: $templates);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ $context['image_dimensions'] = $image_dimensions;
|
|||
*
|
||||
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
|
||||
*/
|
||||
function load_page_resources(): void {
|
||||
function load_page_resources(): void
|
||||
{
|
||||
Resource::enqueue_style_file(
|
||||
handle: 'haiku-atelier-2024-styles-page-a-propos',
|
||||
path: '/assets/css/pages/page-a-propos.css',
|
||||
|
|
@ -47,7 +48,4 @@ function load_page_resources(): void {
|
|||
|
||||
add_action('wp_enqueue_scripts', load_page_resources(...));
|
||||
|
||||
Timber::render(
|
||||
data: $context,
|
||||
filenames: $templates,
|
||||
);
|
||||
Timber::render(data: $context, filenames: $templates);
|
||||
|
|
|
|||
|
|
@ -104,7 +104,8 @@ $context['methodes_livraison'] = $methodes_livraison;
|
|||
*
|
||||
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
|
||||
*/
|
||||
function load_page_resources(): void {
|
||||
function load_page_resources(): void
|
||||
{
|
||||
Resource::enqueue_style_file(
|
||||
handle: 'haiku-atelier-2024-styles-page-panier',
|
||||
path: '/assets/css/pages/page-panier.css',
|
||||
|
|
@ -118,7 +119,4 @@ function load_page_resources(): void {
|
|||
add_action('wp_enqueue_scripts', load_page_resources(...));
|
||||
|
||||
// Rendu
|
||||
Timber::render(
|
||||
filenames: $templates,
|
||||
data: $context,
|
||||
);
|
||||
Timber::render(filenames: $templates, data: $context);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ use WC_Session_Handler;
|
|||
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) {
|
||||
function get_discount_amount(WC_Coupon $coupon)
|
||||
{
|
||||
if ($coupon->get_discount_type() === 'fixed_cart') {
|
||||
return $coupon->get_amount() * 100;
|
||||
} else {
|
||||
|
|
@ -30,7 +31,8 @@ function get_discount_amount(WC_Coupon $coupon) {
|
|||
}
|
||||
}
|
||||
|
||||
function get_discount_duration(WC_Coupon $coupon): string {
|
||||
function get_discount_duration(WC_Coupon $coupon): string
|
||||
{
|
||||
if ($coupon->get_discount_type() === 'fixed_cart') {
|
||||
return 'once';
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ $templates = ['contact.twig'];
|
|||
*
|
||||
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
|
||||
*/
|
||||
function load_page_resources(): void {
|
||||
function load_page_resources(): void
|
||||
{
|
||||
Resource::enqueue_style_file(
|
||||
handle: 'haiku-atelier-2024-styles-page-contact',
|
||||
path: '/assets/css/pages/page-contact.css',
|
||||
|
|
@ -32,7 +33,4 @@ function load_page_resources(): void {
|
|||
add_action('wp_enqueue_scripts', load_page_resources(...));
|
||||
|
||||
// Rendu
|
||||
Timber::render(
|
||||
filenames: $templates,
|
||||
data: $context,
|
||||
);
|
||||
Timber::render(filenames: $templates, data: $context);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ $templates = ['echec-commande.twig'];
|
|||
*
|
||||
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
|
||||
*/
|
||||
function load_page_resources(): void {
|
||||
function load_page_resources(): void
|
||||
{
|
||||
Resource::enqueue_style_file(
|
||||
handle: 'haiku-atelier-2024-styles-page-modele-simple',
|
||||
path: '/assets/css/pages/page-modele-simple.css',
|
||||
|
|
@ -32,7 +33,4 @@ function load_page_resources(): void {
|
|||
add_action('wp_enqueue_scripts', load_page_resources(...));
|
||||
|
||||
// Rendu
|
||||
Timber::render(
|
||||
filenames: $templates,
|
||||
data: $context,
|
||||
);
|
||||
Timber::render(filenames: $templates, data: $context);
|
||||
|
|
|
|||
|
|
@ -101,7 +101,8 @@ try {
|
|||
$context['produits'] = $produits;
|
||||
|
||||
// Charge les scripts et styles de la page
|
||||
function charge_scripts_styles_page_succes_commande(): void {
|
||||
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',
|
||||
|
|
@ -114,10 +115,7 @@ try {
|
|||
add_action('wp_enqueue_scripts', 'charge_scripts_styles_page_succes_commande');
|
||||
|
||||
// Rendu
|
||||
Timber::render(
|
||||
filenames: $templates,
|
||||
data: $context,
|
||||
);
|
||||
Timber::render(filenames: $templates, data: $context);
|
||||
} catch (Error $error) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => esc_html($error->getMessage())]);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ $templates = ['cgv.twig'];
|
|||
*
|
||||
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
|
||||
*/
|
||||
function load_page_resources(): void {
|
||||
function load_page_resources(): void
|
||||
{
|
||||
Resource::enqueue_style_file(
|
||||
handle: '/assets/css/pages/page-modele-simple.css',
|
||||
path: '/assets/css/pages/page-modele-simple.css',
|
||||
|
|
@ -30,7 +31,4 @@ function load_page_resources(): void {
|
|||
add_action('wp_enqueue_scripts', load_page_resources(...));
|
||||
|
||||
// Rendu
|
||||
Timber::render(
|
||||
filenames: $templates,
|
||||
data: $context,
|
||||
);
|
||||
Timber::render(filenames: $templates, data: $context);
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ $context['same_collection_products'] = $same_collection_products;
|
|||
*
|
||||
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
|
||||
*/
|
||||
function load_page_resources(): void {
|
||||
function load_page_resources(): void
|
||||
{
|
||||
Resource::enqueue_script_module_file(
|
||||
id: 'haiku-atelier-2024-scripts-page-produit',
|
||||
path: '/assets/js/scripts-page-produit.js',
|
||||
|
|
@ -75,7 +76,4 @@ function load_page_resources(): void {
|
|||
add_action('wp_enqueue_scripts', load_page_resources(...));
|
||||
|
||||
// Rendu
|
||||
Timber::render(
|
||||
filenames: $templates,
|
||||
data: $context,
|
||||
);
|
||||
Timber::render(filenames: $templates, data: $context);
|
||||
|
|
|
|||
|
|
@ -28,8 +28,10 @@ use function wp_create_nonce;
|
|||
use function wp_get_attachment_image_src;
|
||||
use function wpautop;
|
||||
|
||||
final class StarterSite extends Site {
|
||||
public function __construct() {
|
||||
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']);
|
||||
|
||||
|
|
@ -44,7 +46,8 @@ final class StarterSite extends Site {
|
|||
*
|
||||
* @return array<int,mixed>
|
||||
*/
|
||||
public function ajoute_au_contexte_twig(array $context): array {
|
||||
public function ajoute_au_contexte_twig(array $context): array
|
||||
{
|
||||
$context['site'] = $this;
|
||||
|
||||
$context['environnement'] = env('WP_ENV');
|
||||
|
|
@ -94,22 +97,11 @@ final class StarterSite extends Site {
|
|||
// 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,
|
||||
);
|
||||
$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(...));
|
||||
|
|
@ -130,10 +122,7 @@ final class StarterSite extends Site {
|
|||
];
|
||||
$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,
|
||||
),
|
||||
static fn($categories): array => array_map(callback: $cree_entree_menu, array: $categories),
|
||||
);
|
||||
|
||||
$context['categories_produits'] = $entrees_menu_categories;
|
||||
|
|
@ -159,7 +148,8 @@ final class StarterSite extends Site {
|
|||
return $context;
|
||||
}
|
||||
|
||||
public function defini_fonctionnalites_theme(): void {
|
||||
public function defini_fonctionnalites_theme(): void
|
||||
{
|
||||
// Laisse WordPress gérer le titre de la page
|
||||
add_theme_support('title-tag');
|
||||
|
||||
|
|
@ -181,9 +171,11 @@ final class StarterSite extends Site {
|
|||
*
|
||||
* @param array $options un tableau avec les options d'environnement
|
||||
*/
|
||||
public function maj_environnement_twig(array $options): array {
|
||||
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");
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ declare(strict_types=1);
|
|||
use Carbon_Fields\Container;
|
||||
use Carbon_Fields\Field;
|
||||
|
||||
function cree_champs_personnalises_produit(): void {
|
||||
function cree_champs_personnalises_produit(): void
|
||||
{
|
||||
Container::make('post_meta', "Product's Details")
|
||||
->where('post_type', '=', 'product')
|
||||
->add_fields([
|
||||
|
|
@ -26,7 +27,8 @@ function cree_champs_personnalises_produit(): void {
|
|||
]);
|
||||
}
|
||||
|
||||
function cree_champ_personnalise_commande($order): void {
|
||||
function cree_champ_personnalise_commande($order): void
|
||||
{
|
||||
woocommerce_wp_text_input([
|
||||
'id' => 'tracking_number',
|
||||
'label' => 'Tracking Number:',
|
||||
|
|
@ -35,7 +37,8 @@ function cree_champ_personnalise_commande($order): void {
|
|||
]);
|
||||
}
|
||||
|
||||
function maj_champ_personnalise_commande($order_id): void {
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
function enregistre_controle_personnalise_tinymce(): void {
|
||||
function enregistre_controle_personnalise_tinymce(): void
|
||||
{
|
||||
/**
|
||||
* TinyMCE Custom Control.
|
||||
*
|
||||
|
|
@ -17,14 +18,16 @@ function enregistre_controle_personnalise_tinymce(): void {
|
|||
*
|
||||
* @see https://github.com/maddisondesigns
|
||||
*/
|
||||
final class ControlesPersonnalises extends WP_Customize_Control {
|
||||
final class ControlesPersonnalises extends WP_Customize_Control
|
||||
{
|
||||
/** The type of control being rendered. */
|
||||
public $type = 'editeur_tinymce';
|
||||
|
||||
/**
|
||||
* Enqueue our scripts and styles.
|
||||
*/
|
||||
public function enqueue(): void {
|
||||
public function enqueue(): void
|
||||
{
|
||||
wp_enqueue_script(
|
||||
handle: 'controle-personnalise-tinymce',
|
||||
src: get_template_directory_uri() . '/assets/vendor/controle-personnalise-tinymce.js',
|
||||
|
|
@ -38,7 +41,8 @@ function enregistre_controle_personnalise_tinymce(): void {
|
|||
/**
|
||||
* Render the control in the customizer.
|
||||
*/
|
||||
public function render_content(): void { ?>
|
||||
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)) { ?>
|
||||
|
|
@ -55,7 +59,8 @@ function enregistre_controle_personnalise_tinymce(): void {
|
|||
/**
|
||||
* Pass our TinyMCE toolbar string to JavaScript.
|
||||
*/
|
||||
public function to_json(): void {
|
||||
public function to_json(): void
|
||||
{
|
||||
parent::to_json();
|
||||
|
||||
$this->json['skyrockettinymcetoolbar1'] = isset($this->input_attrs['toolbar1'])
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ use Illuminate\Support\Arr;
|
|||
use WC_Product_Attribute;
|
||||
use WP_Term;
|
||||
|
||||
final readonly class Attribute {
|
||||
final readonly class Attribute
|
||||
{
|
||||
/**
|
||||
* @param list<AttributeOption> $options
|
||||
*/
|
||||
|
|
@ -18,7 +19,8 @@ final readonly class Attribute {
|
|||
public array $options,
|
||||
) {}
|
||||
|
||||
public static function new(WC_Product_Attribute $attribute): self {
|
||||
public static function new(WC_Product_Attribute $attribute): self
|
||||
{
|
||||
$name = wc_attribute_label($attribute->get_name());
|
||||
$slug = $attribute->get_name();
|
||||
/** @var list<WP_Term> */
|
||||
|
|
@ -26,10 +28,6 @@ final readonly class Attribute {
|
|||
/** @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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,22 +6,20 @@ namespace HaikuAtelier\Data;
|
|||
|
||||
use WP_Term;
|
||||
|
||||
final readonly class AttributeOption {
|
||||
final readonly class AttributeOption
|
||||
{
|
||||
public function __construct(
|
||||
public int $id,
|
||||
public string $name,
|
||||
public string $slug,
|
||||
) {}
|
||||
|
||||
public static function new(WP_Term $term): self {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ use function is_float;
|
|||
use function is_int;
|
||||
use function is_string;
|
||||
|
||||
final readonly class Cart {
|
||||
final readonly class Cart
|
||||
{
|
||||
public function __construct() {}
|
||||
|
||||
/** La valeur par défaut d'une donnée invalide du Panier. */
|
||||
|
|
@ -22,7 +23,8 @@ final readonly class Cart {
|
|||
*
|
||||
* @return array<int,string>
|
||||
*/
|
||||
public static function get_allowed_countries(): array {
|
||||
public static function get_allowed_countries(): array
|
||||
{
|
||||
return [
|
||||
'AD',
|
||||
'AL',
|
||||
|
|
@ -95,7 +97,8 @@ final readonly class Cart {
|
|||
];
|
||||
}
|
||||
|
||||
public static function parse_cart_value(int|float|string|bool $cart_value): string {
|
||||
public static function parse_cart_value(int|float|string|bool $cart_value): string
|
||||
{
|
||||
if (is_int($cart_value) || is_float($cart_value)) {
|
||||
return self::format_number($cart_value);
|
||||
}
|
||||
|
|
@ -110,7 +113,8 @@ final readonly class Cart {
|
|||
return '0.00';
|
||||
}
|
||||
|
||||
private static function format_number(int|float $number): string {
|
||||
private static function format_number(int|float $number): string
|
||||
{
|
||||
$formatted_number = Number::format(
|
||||
number: $number,
|
||||
// precision et max_precision sont mutuellement exclusifs.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ use WP_Term;
|
|||
|
||||
use function Psl\Option\from_nullable;
|
||||
|
||||
final readonly class Product {
|
||||
final readonly class Product
|
||||
{
|
||||
/**
|
||||
* @param list<Attribute> $attributes
|
||||
* @param list<string> $left_column_photos
|
||||
|
|
@ -41,12 +42,14 @@ final readonly class Product {
|
|||
/**
|
||||
* @return list<Attribute>
|
||||
*/
|
||||
public static function get_attributes_for_product(WC_Product $product): array {
|
||||
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 {
|
||||
public static function new(WC_Product $product): self
|
||||
{
|
||||
/** @var list<Attribute> */
|
||||
$attributes = self::get_attributes_for_product($product);
|
||||
/** @var lowercase-string */
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ namespace HaikuAtelier\Data;
|
|||
|
||||
use WC_Product;
|
||||
|
||||
final readonly class ProductVariation {
|
||||
final readonly class ProductVariation
|
||||
{
|
||||
/**
|
||||
* @param int $id L'ID de la Variation
|
||||
* @param string $price Le prix de la Variation
|
||||
|
|
@ -21,7 +22,8 @@ final readonly class ProductVariation {
|
|||
/**
|
||||
* Créé une nouvelle instance de `ProductVariation` à partir d'un `WC_Product`.
|
||||
*/
|
||||
public static function new(WC_Product $product): self {
|
||||
public static function new(WC_Product $product): self
|
||||
{
|
||||
$id = $product->get_id();
|
||||
$price = $product->get_price();
|
||||
/** @var list<ProductVariationAttribute> */
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace HaikuAtelier\Data;
|
||||
|
||||
final readonly class ProductVariationAttribute {
|
||||
final readonly class ProductVariationAttribute
|
||||
{
|
||||
/**
|
||||
* @param string $attribute Le slug de l'Attribut
|
||||
* @param string $value Le slug de la valeur de l'Attribut
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
declare(strict_types=1);
|
||||
|
||||
// Désactive divers transformations du contenu par WordPress
|
||||
function desactive_wpautop(): void {
|
||||
function desactive_wpautop(): void
|
||||
{
|
||||
remove_filter('the_content', 'wpautop');
|
||||
}
|
||||
|
||||
|
|
@ -18,7 +19,8 @@ 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 {
|
||||
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>
|
||||
|
|
@ -37,18 +39,21 @@ 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 {
|
||||
function autorise_import_svg_mediatheque(array $file_types): array
|
||||
{
|
||||
$new_filetypes = [];
|
||||
$new_filetypes['svg'] = 'image/svg+xml';
|
||||
|
||||
return array_merge($file_types, $new_filetypes);
|
||||
}
|
||||
|
||||
function retire_motifs_blocs_gutenberg(): void {
|
||||
function retire_motifs_blocs_gutenberg(): void
|
||||
{
|
||||
remove_theme_support('core-block-patterns');
|
||||
}
|
||||
|
||||
function retire_styles_core_block(): void {
|
||||
function retire_styles_core_block(): void
|
||||
{
|
||||
wp_dequeue_style('core-block-supports');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ require_once 'TraitementInformations.php';
|
|||
* Désactive les fonctionnalités liées aux images Produit WooCommerce, empêchant le chargement de
|
||||
* scripts et styles inutiles.
|
||||
*/
|
||||
function desactive_images_produit_woocommerce(): void {
|
||||
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);
|
||||
|
|
@ -25,7 +26,8 @@ function desactive_images_produit_woocommerce(): void {
|
|||
/**
|
||||
* Désactive les champs liés aux images Produit de l'administration.
|
||||
*/
|
||||
function desactive_champs_admin_images_produit_woocommerce(): void {
|
||||
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');
|
||||
}
|
||||
|
|
@ -35,7 +37,8 @@ function desactive_champs_admin_images_produit_woocommerce(): void {
|
|||
/**
|
||||
* Désactive tous les scripts et styles WooCommerce.
|
||||
*/
|
||||
function dequeue_woocommerce_styles_scripts(): void {
|
||||
function dequeue_woocommerce_styles_scripts(): void
|
||||
{
|
||||
// Styles
|
||||
wp_dequeue_style('photoswipe-default-skin-css');
|
||||
wp_dequeue_style('photoswipe-default-skin');
|
||||
|
|
@ -82,7 +85,8 @@ function dequeue_woocommerce_styles_scripts(): void {
|
|||
/**
|
||||
* Désactive scripts et styles liés aux blocs Gutenberg.
|
||||
*/
|
||||
function desactive_blocs_gutenberg_woocommerce(): void {
|
||||
function desactive_blocs_gutenberg_woocommerce(): void
|
||||
{
|
||||
wp_deregister_style('wc-blocks-style');
|
||||
wp_dequeue_style('wc-blocks-style');
|
||||
}
|
||||
|
|
@ -92,7 +96,8 @@ 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 {
|
||||
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');
|
||||
|
|
@ -101,18 +106,21 @@ function woocommerce_photoswipe(): void {
|
|||
/**
|
||||
* Désactive l'Attribution des Commandes WooCommerce.
|
||||
*/
|
||||
function desactive_attribution_commande_woocommerce(): void {
|
||||
function desactive_attribution_commande_woocommerce(): void
|
||||
{
|
||||
update_option('woocommerce_feature_order_attribution_enabled', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retire d'autres merdes WooCommerce.
|
||||
*/
|
||||
function retire_script_galerie(): void {
|
||||
function retire_script_galerie(): void
|
||||
{
|
||||
remove_action('wp_head', 'wc_gallery_noscript');
|
||||
}
|
||||
|
||||
function retire_merdes_wc(): void {
|
||||
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);
|
||||
|
|
@ -145,13 +153,10 @@ function genere_balises_img_dans_produit_dans_reponse_rest(
|
|||
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($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],
|
||||
);
|
||||
|
||||
|
|
@ -162,13 +167,10 @@ function genere_balises_img_dans_produit_dans_reponse_rest(
|
|||
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($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],
|
||||
);
|
||||
|
||||
|
|
@ -209,7 +211,8 @@ 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 {
|
||||
function remove_payments_ad_tab(): void
|
||||
{
|
||||
remove_menu_page('admin.php?page=wc-settings&tab=checkout');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ declare(strict_types=1);
|
|||
/**
|
||||
* Enregistre la Taxonomie « Collection ».
|
||||
*/
|
||||
function enregistre_taxonomie_collection(): void {
|
||||
function enregistre_taxonomie_collection(): void
|
||||
{
|
||||
$labels = [
|
||||
'add_new_item' => __('Add New Collection'),
|
||||
'all_items' => __('All Collections'),
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ use function Crell\fp\pipe;
|
|||
*
|
||||
* @return string TODO
|
||||
*/
|
||||
function genere_balise_img_multiformats(string $id, bool $lazy = false): string {
|
||||
function genere_balise_img_multiformats(string $id, bool $lazy = false): string
|
||||
{
|
||||
$int_id = (int) $id;
|
||||
|
||||
if (-1 === $int_id) {
|
||||
|
|
@ -43,24 +44,18 @@ function genere_balise_img_multiformats(string $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 = '';
|
||||
|
|
@ -90,7 +85,8 @@ function genere_balise_img_multiformats(string $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();
|
||||
}
|
||||
|
||||
|
|
@ -100,16 +96,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(),
|
||||
|
|
@ -153,7 +147,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);
|
||||
|
||||
|
|
@ -205,7 +200,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): callable {
|
||||
function recupere_produits_meme_collection(string $slug_collection): callable
|
||||
{
|
||||
return static fn(int $id_produit): array|stdClass => wc_get_products([
|
||||
'exclude' => [$id_produit],
|
||||
'limit' => 4,
|
||||
|
|
@ -218,7 +214,8 @@ function recupere_produits_meme_collection(string $slug_collection): callable {
|
|||
|
||||
// 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],
|
||||
|
|
|
|||
|
|
@ -9,11 +9,13 @@ use Illuminate\Support\Arr;
|
|||
use function is_array;
|
||||
use function is_string;
|
||||
|
||||
final readonly class HaikuProduct {
|
||||
final readonly class HaikuProduct
|
||||
{
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public static function get_left_column_photos(int $post_id): array {
|
||||
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)))
|
||||
|
|
@ -23,7 +25,8 @@ final readonly class HaikuProduct {
|
|||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public static function get_right_column_photos(int $post_id): array {
|
||||
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)) {
|
||||
|
|
|
|||
|
|
@ -12,11 +12,13 @@ use function is_array;
|
|||
use function Psl\Option\none;
|
||||
use function Psl\Option\some;
|
||||
|
||||
final readonly class Post {
|
||||
final readonly class Post
|
||||
{
|
||||
/**
|
||||
* @return Option\Option<mixed>
|
||||
*/
|
||||
public static function get_post_meta(int $post_id, string $key): Option\Option {
|
||||
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);
|
||||
|
||||
|
|
@ -30,7 +32,8 @@ final readonly class Post {
|
|||
/**
|
||||
* @return Option\Option<array<mixed>>
|
||||
*/
|
||||
public static function get_post_meta_array(int $post_id, string $key): Option\Option {
|
||||
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);
|
||||
|
||||
|
|
@ -44,7 +47,8 @@ final readonly class Post {
|
|||
/**
|
||||
* @return Option\Option<array<mixed>>
|
||||
*/
|
||||
public static function get_terms(int $post_id, string $taxonomy_name): Option\Option {
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@ use Exception;
|
|||
|
||||
use function is_bool;
|
||||
|
||||
final readonly class Resource {
|
||||
public static function enqueue_script_module_file(string $path, string $id): void {
|
||||
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;
|
||||
|
|
@ -21,15 +23,11 @@ final readonly class Resource {
|
|||
|
||||
$version = (string) $file_mtime;
|
||||
|
||||
wp_enqueue_script_module(
|
||||
id: $id,
|
||||
src: $file_uri,
|
||||
deps: [],
|
||||
version: $version,
|
||||
);
|
||||
wp_enqueue_script_module(id: $id, src: $file_uri, deps: [], version: $version);
|
||||
}
|
||||
|
||||
public static function enqueue_style_file(string $path, string $handle): void {
|
||||
public static function enqueue_style_file(string $path, string $handle): void
|
||||
{
|
||||
$file_uri = get_template_directory_uri() . $path;
|
||||
|
||||
$file_path = get_template_directory() . $path;
|
||||
|
|
@ -41,12 +39,6 @@ final readonly class Resource {
|
|||
|
||||
$ver = (string) $file_mtime;
|
||||
|
||||
wp_enqueue_style(
|
||||
handle: $handle,
|
||||
src: $file_uri,
|
||||
deps: [],
|
||||
ver: $ver,
|
||||
media: 'all',
|
||||
);
|
||||
wp_enqueue_style(handle: $handle, src: $file_uri, deps: [], ver: $ver, media: 'all');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,13 @@ use function is_array;
|
|||
use function Psl\Option\none;
|
||||
use function Psl\Option\some;
|
||||
|
||||
final readonly class Term {
|
||||
final readonly class Term
|
||||
{
|
||||
/**
|
||||
* @return Option\Option<list<WP_Term>>
|
||||
*/
|
||||
public static function get_terms(int $post_id, string $taxonomy_name): Option\Option {
|
||||
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)) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { pipe, Option } from "effect";
|
||||
import { Option, pipe } from "effect";
|
||||
|
||||
export const getOptionOrThrowWithError =
|
||||
(message: string) =>
|
||||
|
|
|
|||
|
|
@ -3,18 +3,18 @@
|
|||
import { ATTRIBUT_CHARGEMENT } from "../constantes/dom";
|
||||
|
||||
// Types
|
||||
interface AnimationCycleTexte {
|
||||
type AnimationCycleTexte = {
|
||||
callback: () => void;
|
||||
etapes: Array<string>;
|
||||
index: number;
|
||||
interval: NodeJS.Timeout;
|
||||
}
|
||||
};
|
||||
|
||||
interface ParametresAnimationCycleTexte {
|
||||
type ParametresAnimationCycleTexte = {
|
||||
attribut: string;
|
||||
element: HTMLElement;
|
||||
etapes: Array<string>;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Créer le nécessaire pour une animation s'exécutant jusqu'à ce que un interval soit manuellement arrêté. L'animation
|
||||
|
|
@ -39,7 +39,7 @@ const lanceAnimationCycleTexte = (args: ParametresAnimationCycleTexte): Animatio
|
|||
},
|
||||
etapes: args.etapes,
|
||||
index: 0,
|
||||
interval: setInterval(() => {}, 2147483647),
|
||||
interval: setInterval(() => {}, 2_147_483_647),
|
||||
};
|
||||
|
||||
return animation;
|
||||
|
|
|
|||
|
|
@ -123,8 +123,12 @@ export const reporteEtLeveErreur = <E extends Error>(erreur: E): never => {
|
|||
export const reporteEtJournaliseErreur = <E extends Error>(erreur: E): void => {
|
||||
reporteErreur(erreur);
|
||||
console.error(erreur);
|
||||
if (erreur instanceof ValiError) console.error(erreur.issues);
|
||||
if (erreur instanceof ErreurAdresseInvalide) console.error(erreur.problemes);
|
||||
if (erreur instanceof ValiError) {
|
||||
console.error(erreur.issues);
|
||||
}
|
||||
if (erreur instanceof ErreurAdresseInvalide) {
|
||||
console.error(erreur.problemes);
|
||||
}
|
||||
};
|
||||
|
||||
export const reporteEtRetourneErreur = <E extends Error>(erreur: E): E => {
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ export const CODE_PROMO_MAJ_EVENT = new CustomEvent(CODE_PROMO_MAJ, {});
|
|||
|
||||
// Interfaces
|
||||
|
||||
export interface UpdatedShippingRatesEvent extends Event {
|
||||
export type UpdatedShippingRatesEvent = {
|
||||
detail: { refresh_methods: boolean; shipping_rates: ReadonlyArray<WCStoreShippingRateShippingRate> };
|
||||
}
|
||||
export interface UpdatedTotalsEvent extends Event {
|
||||
} & Event;
|
||||
export type UpdatedTotalsEvent = {
|
||||
detail: { totals: WCStoreCartTotals };
|
||||
}
|
||||
} & Event;
|
||||
|
||||
// Méthodes
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { pipe } from "@mobily/ts-belt";
|
||||
import { Either } from "purify-ts";
|
||||
import { parse, type ValiError } from "valibot";
|
||||
import { parse } from "valibot";
|
||||
import type { ValiError } from "valibot";
|
||||
|
||||
import type {
|
||||
MessageMajBoutonPanier,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ type ArgumentsPostBackendWC = {
|
|||
route: string;
|
||||
};
|
||||
|
||||
// fetch
|
||||
// Fetch
|
||||
|
||||
export const getBackend = (args: ArgumentsGetBackendWC): Promise<Response> =>
|
||||
fetch(args.route, {
|
||||
|
|
@ -120,19 +120,16 @@ export const safeFetch = (f: Promise<Response>): EitherAsync<DOMException | Type
|
|||
EitherAsync<DOMException | TypeError, Response>(async () => await f);
|
||||
|
||||
// Réponses Simplifiées
|
||||
export const newPartialResponse = async (reponse: Response): Promise<SimplifiedResponse> => {
|
||||
return {
|
||||
body: await reponse.json(),
|
||||
status: reponse.status,
|
||||
};
|
||||
};
|
||||
export const newPartialResponse = async (reponse: Response): Promise<SimplifiedResponse> => ({
|
||||
body: await reponse.json(),
|
||||
status: reponse.status,
|
||||
});
|
||||
|
||||
export const traiteErreursBackendWooCommerce = (rs: SimplifiedResponse): HttpCodeErrors => {
|
||||
return match(rs)
|
||||
export const traiteErreursBackendWooCommerce = (rs: SimplifiedResponse): HttpCodeErrors =>
|
||||
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)));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export const WCStoreBillingAddressSchema = v.object({
|
|||
city: v.string(),
|
||||
company: v.string(),
|
||||
country: v.string(),
|
||||
// email: v.optional(v.pipe(v.string(), v.email())),
|
||||
// Email: v.optional(v.pipe(v.string(), v.email())),
|
||||
email: v.string(),
|
||||
first_name: v.string(),
|
||||
last_name: v.string(),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ import type { GenericSchema, InferOutput, ValiError } from "valibot";
|
|||
import { Either, Maybe } from "purify-ts";
|
||||
|
||||
import { safeJsonParse } from "./dom.ts";
|
||||
import { ErreurEntreeInexistante, type NonExistingKeyError } from "./erreurs.ts";
|
||||
import { ErreurEntreeInexistante } from "./erreurs.ts";
|
||||
import type { NonExistingKeyError } from "./erreurs.ts";
|
||||
import { safeSchemaParse, safeSchemaParseCurried } from "./validation.ts";
|
||||
|
||||
export type GetSessionStorage<S extends GenericSchema> = Either<ErreursGetSessionStorage<S>, InferOutput<S>>;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ export type FetchErrors = DOMException | Error | TypeError;
|
|||
|
||||
export type HttpCodeErrors = BadRequestError | Error | ForbiddenError | NotFoundError | ServerError | UnauthorizedError;
|
||||
|
||||
export interface SimplifiedResponse {
|
||||
export type SimplifiedResponse = {
|
||||
body: unknown;
|
||||
status: number;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { D } from "@mobily/ts-belt";
|
||||
import { type Either, Maybe } from "purify-ts";
|
||||
import { Maybe } from "purify-ts";
|
||||
import type { Either } from "purify-ts";
|
||||
|
||||
import { CleNonTrouveError } from "./erreurs";
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
*/
|
||||
|
||||
import { Either } from "purify-ts";
|
||||
import { type GenericSchema, type InferOutput, parse, type ValiError } from "valibot";
|
||||
import { parse } from "valibot";
|
||||
import type { GenericSchema, InferOutput, ValiError } from "valibot";
|
||||
|
||||
export const safeSchemaParse = <Schema extends GenericSchema>(
|
||||
valeur: unknown,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import { map as dictMap, values as dictValues } from "@mobily/ts-belt/Dict";
|
|||
import { trim as stringTrim } from "@mobily/ts-belt/String";
|
||||
import { EitherAsync, Maybe } from "purify-ts";
|
||||
import { match, P } from "ts-pattern";
|
||||
import { type AnySchema, ValiError } from "valibot";
|
||||
import { ValiError } from "valibot";
|
||||
import type { AnySchema } from "valibot";
|
||||
|
||||
import type { WCStoreBillingAddress, WCStoreShippingAddress } from "../lib/types/api/adresses";
|
||||
import type { WCStoreCart, WCStoreShippingRate, WCStoreShippingRateShippingRate } from "../lib/types/api/cart";
|
||||
|
|
@ -43,10 +44,10 @@ import { safeSchemaParse } from "../lib/validation";
|
|||
import { E } from "./scripts-page-panier-elements";
|
||||
import { getShippingRatesLS } from "./scripts-page-panier-local-storage";
|
||||
|
||||
interface Addresses {
|
||||
type Addresses = {
|
||||
billing_address: WCStoreBillingAddress;
|
||||
shipping_address: WCStoreShippingAddress;
|
||||
}
|
||||
};
|
||||
|
||||
// @ts-expect-error -- États injectés par le modèle PHP
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- États injectés par le modèle PHP
|
||||
|
|
@ -65,35 +66,33 @@ export const initCartFormEventEmitters = (): void => {
|
|||
});
|
||||
};
|
||||
|
||||
export const getAddressesFromForm = (formFields: Record<string, string>, areAddressesMerged: boolean): Addresses => {
|
||||
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"] ?? ""),
|
||||
email: formFields["facturation-email"] ?? formFields["livraison-email"] ?? "",
|
||||
first_name: formFields["facturation-prenom"] ?? formFields["livraison-prenom"] ?? "",
|
||||
last_name: formFields["facturation-nom"] ?? formFields["livraison-nom"] ?? "",
|
||||
phone: formFields["facturation-telephone"] ?? formFields["livraison-telephone"] ?? "",
|
||||
postcode: formFields["facturation-code-postal"] ?? formFields["livraison-code-postal"] ?? "",
|
||||
state: formFields["facturation-region-etat"] ?? formFields["livraison-region-etat"] ?? "",
|
||||
},
|
||||
shipping_address: {
|
||||
address_1: formFields["livraison-adresse"] ?? "",
|
||||
address_2: "",
|
||||
city: formFields["livraison-ville"] ?? "",
|
||||
company: "",
|
||||
country: formFields["livraison-pays"] ?? "",
|
||||
first_name: formFields["livraison-prenom"] ?? "",
|
||||
last_name: formFields["livraison-nom"] ?? "",
|
||||
phone: formFields["livraison-telephone"] ?? "",
|
||||
postcode: formFields["livraison-code-postal"] ?? "",
|
||||
state: formFields["livraison-region-etat"] ?? "",
|
||||
},
|
||||
};
|
||||
};
|
||||
export const getAddressesFromForm = (formFields: Record<string, string>, areAddressesMerged: boolean): Addresses => ({
|
||||
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"] ?? ""),
|
||||
email: formFields["facturation-email"] ?? formFields["livraison-email"] ?? "",
|
||||
first_name: formFields["facturation-prenom"] ?? formFields["livraison-prenom"] ?? "",
|
||||
last_name: formFields["facturation-nom"] ?? formFields["livraison-nom"] ?? "",
|
||||
phone: formFields["facturation-telephone"] ?? formFields["livraison-telephone"] ?? "",
|
||||
postcode: formFields["facturation-code-postal"] ?? formFields["livraison-code-postal"] ?? "",
|
||||
state: formFields["facturation-region-etat"] ?? formFields["livraison-region-etat"] ?? "",
|
||||
},
|
||||
shipping_address: {
|
||||
address_1: formFields["livraison-adresse"] ?? "",
|
||||
address_2: "",
|
||||
city: formFields["livraison-ville"] ?? "",
|
||||
company: "",
|
||||
country: formFields["livraison-pays"] ?? "",
|
||||
first_name: formFields["livraison-prenom"] ?? "",
|
||||
last_name: formFields["livraison-nom"] ?? "",
|
||||
phone: formFields["livraison-telephone"] ?? "",
|
||||
postcode: formFields["livraison-code-postal"] ?? "",
|
||||
state: formFields["livraison-region-etat"] ?? "",
|
||||
},
|
||||
});
|
||||
|
||||
export const initShippingCalculationButton = (): void => {
|
||||
// Déclenche au clic sur le Bouton de soumission du Formulaire la requête pour le calcul des frais de livraison
|
||||
|
|
@ -119,11 +118,11 @@ export const initShippingCalculationButton = (): void => {
|
|||
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) => {
|
||||
return safeFetch(postBackend(ROUTE_API_MAJ_CLIENT, JSON.stringify(args), false));
|
||||
})
|
||||
.chain((rs: Response) => {
|
||||
return EitherAsync<ErreurAdresseInvalide | HttpCodeErrors, unknown>(
|
||||
.chain((args: WCStoreCartUpdateCustomerArgs) =>
|
||||
safeFetch(postBackend(ROUTE_API_MAJ_CLIENT, JSON.stringify(args), false)),
|
||||
)
|
||||
.chain((rs: Response) =>
|
||||
EitherAsync<ErreurAdresseInvalide | HttpCodeErrors, unknown>(
|
||||
async ({ throwE }): Promise<unknown> =>
|
||||
match(await newPartialResponse(rs))
|
||||
.with({ status: 200 }, (rs): unknown => rs.body)
|
||||
|
|
@ -135,8 +134,8 @@ export const initShippingCalculationButton = (): void => {
|
|||
(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 => {
|
||||
/** La méthode de livraison sélectionnée dans le SessionStorage */
|
||||
|
|
@ -299,9 +298,9 @@ export const initOrderCreationButton = (): void => {
|
|||
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) => {
|
||||
return safeFetch(postBackend(ROUTE_API_NOUVELLE_COMMANDES, JSON.stringify(args), true));
|
||||
})
|
||||
.chain((args: WCV3OrdersArgs) =>
|
||||
safeFetch(postBackend(ROUTE_API_NOUVELLE_COMMANDES, JSON.stringify(args), true)),
|
||||
)
|
||||
.chain((rs: Response) =>
|
||||
EitherAsync<HttpCodeErrors, unknown>(
|
||||
async ({ throwE }): Promise<unknown> =>
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ export const initialiseElementsCodePromo = (): void => {
|
|||
);
|
||||
|
||||
window.dispatchEvent(CODE_PROMO_MAJ_EVENT);
|
||||
// emetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true);
|
||||
// EmetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true);
|
||||
})
|
||||
.ifLeft((erreur) => {
|
||||
// Rétablis le texte d'origine
|
||||
|
|
@ -194,7 +194,9 @@ export const initialiseElementsCodePromo = (): void => {
|
|||
)
|
||||
.chain((reponse: Response) =>
|
||||
EitherAsync<ServerError, unknown>(async ({ throwE }) => {
|
||||
if (estReponse500(reponse)) throwE(new ServerError("500 server Error"));
|
||||
if (estReponse500(reponse)) {
|
||||
throwE(new ServerError("500 server Error"));
|
||||
}
|
||||
return await reponse.json();
|
||||
}),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { forEach as arrayForEach, map as arrayMap } from "@mobily/ts-belt/Array";
|
||||
import { html, render, type TemplateResult } from "lit-html";
|
||||
import { html, render } from "lit-html";
|
||||
import type { TemplateResult } from "lit-html";
|
||||
|
||||
import type { WCStoreCartTotals, WCStoreShippingRateShippingRate } from "../lib/types/api/cart";
|
||||
import type { WCStoreShippingRateShippingRates } from "../lib/types/api/couts-livraison";
|
||||
|
|
@ -66,8 +67,9 @@ export const generateShippingRatesHTML = (
|
|||
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 shippingRatesHTML: ReadonlyArray<TemplateResult> = arrayMap(
|
||||
shippingRates,
|
||||
(methode) => html` <div>
|
||||
<input
|
||||
id="methode-livraison-${methode.method_id}"
|
||||
name="choix-methode-livraison"
|
||||
|
|
@ -78,8 +80,8 @@ export const generateShippingRatesHTML = (
|
|||
<label for="methode-livraison-${methode.method_id}"
|
||||
>${methode.name} (${formateEnEuros(methode.price)})</label
|
||||
>
|
||||
</div>`;
|
||||
});
|
||||
</div>`,
|
||||
);
|
||||
|
||||
// Ajoute les nouveaux Produits dans le DOM
|
||||
container.removeAttribute(ATTRIBUT_HIDDEN);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import { pipe } from "@mobily/ts-belt";
|
|||
import { forEach as arrayForEach, map as arrayMap } from "@mobily/ts-belt/Array";
|
||||
import { EitherAsync, Maybe } from "purify-ts";
|
||||
import { match, P } from "ts-pattern";
|
||||
import { type AnySchema, ValiError } from "valibot";
|
||||
import { ValiError } from "valibot";
|
||||
import type { AnySchema } from "valibot";
|
||||
|
||||
import type { WCStoreCart } from "../lib/types/api/cart";
|
||||
import type { WCStoreCartRemoveItemArgs } from "../lib/types/api/cart-remove-item";
|
||||
|
|
|
|||
|
|
@ -59,9 +59,13 @@ const initialiseObservationFenetre = (): void => {
|
|||
// Met à jour la valeur du défilement vertical dans la page
|
||||
defilementY = majDefilementY();
|
||||
// Vérifie que le Ratio soit le bon
|
||||
if (ratioActuel < RATIO_MINIMUM_PAGE_PAR_FENETRE) return;
|
||||
if (ratioActuel < RATIO_MINIMUM_PAGE_PAR_FENETRE) {
|
||||
return;
|
||||
}
|
||||
// Attend la prochaine étape
|
||||
if (etapePlanifiee) return;
|
||||
if (etapePlanifiee) {
|
||||
return;
|
||||
}
|
||||
|
||||
etapePlanifiee = true;
|
||||
requestAnimationFrame((): void =>
|
||||
|
|
|
|||
|
|
@ -17,12 +17,16 @@ document.addEventListener("DOMContentLoaded", (): void => {
|
|||
|
||||
// Créé un nouvel Observer pour la première et dernière entrée.
|
||||
EffectArray.forEach(firstAndLastEntries, (menuEntry, _index) => {
|
||||
if (Predicate.isUndefined(menuEntry)) return;
|
||||
if (Predicate.isUndefined(menuEntry)) {
|
||||
return;
|
||||
}
|
||||
|
||||
new IntersectionObserver(
|
||||
EffectArray.forEach((intersectionEntry) => {
|
||||
// Ne déclenche rien si le scroll n'est pas horizontal
|
||||
if (intersectionEntry.boundingClientRect.top <= 0) return;
|
||||
if (intersectionEntry.boundingClientRect.top <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Match.value([intersectionEntry.isIntersecting]).pipe(
|
||||
Match.when([true, 0], () => productsCategoriesMenu.removeAttribute("data-entrees-presentes-debut")),
|
||||
|
|
@ -32,7 +36,7 @@ document.addEventListener("DOMContentLoaded", (): void => {
|
|||
Match.orElse(() => {}),
|
||||
);
|
||||
}),
|
||||
{ root: null, threshold: 0.9 },
|
||||
{ root: undefined, threshold: 0.9 },
|
||||
).observe(menuEntry);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ const initGestionAnimation = (): void => {
|
|||
A.at(E.IMAGES_STORYTELLING, 0),
|
||||
O.tap((img) => {
|
||||
const options: IntersectionObserverInit = {
|
||||
root: null,
|
||||
root: undefined,
|
||||
rootMargin: "0px",
|
||||
threshold: 0,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -92,13 +92,13 @@ const initialisePageBoutique = (): void => {
|
|||
)
|
||||
// 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse
|
||||
.chain((reponse: Response) =>
|
||||
EitherAsync<APIFetchErrors, unknown>(async ({ throwE }) => {
|
||||
return match(await newPartialResponse(reponse))
|
||||
EitherAsync<APIFetchErrors, unknown>(async ({ throwE }) =>
|
||||
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)
|
||||
.run();
|
||||
}),
|
||||
.run(),
|
||||
),
|
||||
)
|
||||
// 5. Vérifie le Schéma de la Réponse
|
||||
.chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCV3ProductsSchema)))
|
||||
|
|
@ -139,12 +139,12 @@ const initialisePageBoutique = (): void => {
|
|||
</figure>
|
||||
</article>
|
||||
`,
|
||||
tap((article) => fragment.appendChild(article)),
|
||||
tap((article) => fragment.append(article)),
|
||||
);
|
||||
}
|
||||
|
||||
// Ajoute les nouveaux Produits dans le DOM
|
||||
E.GRILLE_PRODUITS.appendChild(fragment);
|
||||
E.GRILLE_PRODUITS.append(fragment);
|
||||
E.GRILLE_PRODUITS.setAttribute(ATTRIBUT_PAGE, String(nouveauNumeroPage));
|
||||
|
||||
E.BOUTON_PLUS_DE_PRODUITS.textContent = "Show more";
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ import {
|
|||
} from "./constantes/dom.ts";
|
||||
import { NOM_CANAL_BOUTON_PANIER, NOM_CANAL_CONTENU_PANIER } from "./constantes/messages.ts";
|
||||
import { getDOMElementsWithSelector, recupereElementAvecSelecteur, recupereElementOuLeve } from "./lib/dom.ts";
|
||||
import { type CleNonTrouveError, reporteErreur } from "./lib/erreurs.ts";
|
||||
import { reporteErreur } from "./lib/erreurs.ts";
|
||||
import type { CleNonTrouveError } from "./lib/erreurs.ts";
|
||||
import { valideMessageMajBoutonPanier, valideMessageMajContenuPanier } from "./lib/messages.ts";
|
||||
import { arrondisADeuxDecimales, diviseParCent, formateEnEuros, inverseNombre } from "./lib/nombres.ts";
|
||||
import { propEither } from "./lib/utils.ts";
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ import { tap as optionTap } from "@mobily/ts-belt/Option";
|
|||
import { pipe as epipe } from "effect";
|
||||
import { EitherAsync, Maybe } from "purify-ts";
|
||||
import { match, P } from "ts-pattern";
|
||||
import { type AnySchema, ValiError } from "valibot";
|
||||
import { ValiError } from "valibot";
|
||||
import type { AnySchema } from "valibot";
|
||||
|
||||
import type { WCStoreCart } from "./lib/types/api/cart";
|
||||
import type { WCStoreCartAddItemArgs, WCStoreCartAddItemArgsItems } from "./lib/types/api/cart-add-item.ts";
|
||||
|
|
@ -79,8 +80,12 @@ const gereAccordeonDetailsProduit = (): void => {
|
|||
const idContenu: null | string = bouton.getAttribute(ATTRIBUT_ARIA_CONTROLS);
|
||||
const sectionCorrespondante: HTMLDivElement | undefined = E.CONTENUS_ACCORDEON[index];
|
||||
|
||||
if (!idContenu) throw new Error("Le lien ne dispose pas d'ID !");
|
||||
if (!sectionCorrespondante) throw new Error("Le lien ne dispose pas de section correspondante !");
|
||||
if (!idContenu) {
|
||||
throw new Error("Le lien ne dispose pas d'ID !");
|
||||
}
|
||||
if (!sectionCorrespondante) {
|
||||
throw new Error("Le lien ne dispose pas de section correspondante !");
|
||||
}
|
||||
|
||||
contenus.set(idContenu, [bouton, sectionCorrespondante]);
|
||||
|
||||
|
|
@ -93,7 +98,9 @@ const gereAccordeonDetailsProduit = (): void => {
|
|||
pipe(contenus.values(), Array.from<EnsembleLienContenu>, deplieToutesSections);
|
||||
|
||||
// Ne fais rien de plus si l'onglet sélectionné était le courant
|
||||
if (estAncienContenuDeplie) return;
|
||||
if (estAncienContenuDeplie) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ouvre le nouvel onglet sélectionné
|
||||
bouton.setAttribute(ATTRIBUT_ARIA_EXPANDED, "true");
|
||||
|
|
@ -130,14 +137,14 @@ const getAttributesFromDom = (): ReadonlyArray<WCStoreCartAddItemArgsItems> => {
|
|||
document.querySelectorAll<HTMLSelectElement>(".selecteur-produit select"),
|
||||
Array.from<HTMLSelectElement>,
|
||||
);
|
||||
if (selectElements.length === 0) return [];
|
||||
if (selectElements.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const attributes = selectElements.map((select: HTMLSelectElement) => {
|
||||
return {
|
||||
attribute: select.id,
|
||||
value: select.value,
|
||||
} satisfies WCStoreCartAddItemArgsItems;
|
||||
});
|
||||
const attributes = selectElements.map((select: HTMLSelectElement) => ({
|
||||
attribute: select.id,
|
||||
value: select.value,
|
||||
}));
|
||||
|
||||
return attributes;
|
||||
};
|
||||
|
|
@ -176,9 +183,9 @@ const ajouteProduitAuPanier = (event: MouseEvent): void => {
|
|||
id: E.DOM_VARIATION.map((selecteur: HTMLSelectElement): number => Number(selecteur.value))
|
||||
// Récupère l'ID du Produit de la Page pour les Produits simples
|
||||
.orDefault(ETATS_PAGE.idProduit),
|
||||
// id: ETATS_PAGE.idProduit,
|
||||
// Id: ETATS_PAGE.idProduit,
|
||||
quantity: 1,
|
||||
// variation: getAttributeValuesFromDom(),
|
||||
// Variation: getAttributeValuesFromDom(),
|
||||
};
|
||||
|
||||
// Réalise la Requête et traite sa Réponse
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMeta {
|
||||
type ImportMeta = {
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|
||||
};
|
||||
|
||||
interface ImportMetaEnv {}
|
||||
type ImportMetaEnv = {};
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ $context['products_category_id'] = $products_category_id;
|
|||
*
|
||||
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
|
||||
*/
|
||||
function load_page_resources(): void {
|
||||
function load_page_resources(): void
|
||||
{
|
||||
Resource::enqueue_style_file(
|
||||
handle: 'haiku-atelier-2024-styles-page-boutique',
|
||||
path: '/assets/css/pages/page-boutique.css',
|
||||
|
|
@ -65,7 +66,4 @@ function load_page_resources(): void {
|
|||
add_action('wp_enqueue_scripts', load_page_resources(...));
|
||||
|
||||
// Rendu
|
||||
Timber::render(
|
||||
filenames: $templates,
|
||||
data: $context,
|
||||
);
|
||||
Timber::render(filenames: $templates, data: $context);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,4 @@ $email = [
|
|||
|
||||
$context['commande'] = $email;
|
||||
// Rendu
|
||||
Timber::render(
|
||||
filenames: $templates,
|
||||
data: $context,
|
||||
);
|
||||
Timber::render(filenames: $templates, data: $context);
|
||||
|
|
|
|||
|
|
@ -76,7 +76,4 @@ $email['adresses']['facturation']['country'] = WC()->countries->countries[$comma
|
|||
|
||||
$context['commande'] = $email;
|
||||
// Rendu
|
||||
Timber::render(
|
||||
filenames: $templates,
|
||||
data: $context,
|
||||
);
|
||||
Timber::render(filenames: $templates, data: $context);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,4 @@ $email['adresses']['facturation']['country'] = WC()->countries->countries[$comma
|
|||
$context['commande'] = $email;
|
||||
|
||||
// Rendu
|
||||
Timber::render(
|
||||
filenames: $templates,
|
||||
data: $context,
|
||||
);
|
||||
Timber::render(filenames: $templates, data: $context);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue