This commit is contained in:
gcch 2025-06-23 15:01:30 +02:00
commit fb04196dc5
20 changed files with 226 additions and 180 deletions

View file

@ -151,10 +151,13 @@ $contexte["pays_livraison"] = $pays_livraison;
$contexte["sous_total_livraison"] = $total_livraison;
$contexte["methodes_livraison"] = $methodes_livraison;
// echo "<pre>";
echo "<pre>";
print_r($adresse_livraison);
print_r($adresse_facturation);
print_r($adresse_renseignee);
// print_r($methodes_livraison);
// print_r(WC()->session->get("chosen_shipping_methods"));
// echo "</pre>";
echo "</pre>";
// Charge les scripts et styles de la page
function charge_scripts_styles_page_panier(): void {

View file

@ -6,37 +6,37 @@ import { safeJsonParse } from "./dom.ts";
import { ErreurEntreeInexistante, type NonExistingKeyError } from "./erreurs.ts";
import { safeSchemaParse, safeSchemaParseCurried } from "./validation.ts";
export type GetLocalStorage<S extends GenericSchema> = Either<ErreursGetLocalStorage<S>, InferOutput<S>>;
type ErreursGetLocalStorage<S extends GenericSchema> =
export type GetSessionStorage<S extends GenericSchema> = Either<ErreursGetSessionStorage<S>, InferOutput<S>>;
type ErreursGetSessionStorage<S extends GenericSchema> =
| NonExistingKeyError
| SyntaxError
| ValiError<S>;
/**
* Récupère une entrée dans le Stockage Local (`localStorage`) sous forme d'`Either`.
* Récupère une entrée dans le Stockage Local (`sessionStorage`) sous forme d'`Either`.
*
* @param cle La clé de l'entrée.
* @returns Un `Either` avec une `NonExistingKeyError` si la clé est absente (`Left`), la
* valeur de l'entrée sinon (`Right`).
*/
export const eitherGetLocalStorage = (cle: string): Either<NonExistingKeyError, string> =>
export const eitherGetSessionStorage = (cle: string): Either<NonExistingKeyError, string> =>
Maybe
.fromNullable(localStorage.getItem(cle))
.fromNullable(sessionStorage.getItem(cle))
.toEither(ErreurEntreeInexistante(`Clé ${cle} absente dans le stockage de session.`));
export const eitherSetLocalStorage = <V>(cle: string, valeur: V): Either<DOMException, V> =>
export const eitherSetSessionStorage = <V>(cle: string, valeur: V): Either<DOMException, V> =>
Either.encase<DOMException, V>(() => {
const json = JSON.stringify(valeur) || "";
localStorage.setItem(cle, json);
sessionStorage.setItem(cle, json);
return valeur;
});
export const getLocalStorageByKey = <S extends GenericSchema>(key: string, schema: S): GetLocalStorage<S> =>
eitherGetLocalStorage(key)
export const getSessionStorageByKey = <S extends GenericSchema>(key: string, schema: S): GetSessionStorage<S> =>
eitherGetSessionStorage(key)
.chain(safeJsonParse)
.chain(safeSchemaParseCurried(schema));
export const setLocalStorageByKey =
export const setSessionStorageByKey =
<S extends GenericSchema>(key: string, schema: S) =>
(value: unknown): Either<DOMException | ValiError<S>, InferOutput<S>> =>
safeSchemaParse(value, schema).chain(v => eitherSetLocalStorage(key, v));
safeSchemaParse(value, schema).chain(v => eitherSetSessionStorage(key, v));

View file

@ -17,6 +17,7 @@ import { ROUTE_API_MAJ_CLIENT, ROUTE_API_NOUVELLE_COMMANDES } from "../constante
import { ATTRIBUT_CHARGEMENT, ATTRIBUT_LIVRAISON_VALIDEE } from "../constantes/dom";
import { NOM_CANAL_REVALIDATION_LIVRAISON } from "../constantes/messages";
import {
ERREUR_ADRESSE_GENERIQUE,
ERREUR_ADRESSE_MAUVAIS_CODE_POSTAL,
ERREUR_GENERIQUE_CREATION_COMMANDE,
ERREUR_GENERIQUE_RESEAU,
@ -55,12 +56,10 @@ const postBackend = prefilledPostBackend(ETATS_PAGE.nonce, ETATS_PAGE.authString
/**
* Initialise les Émetteurs d'Événements sur divers parties du Panier.
*
* 1. Émet un Événement de mise à jour des Adresses quand le Formulaire est modifié (s'il est valide).
*
* @returns void
*/
export const initCartFormEventEmiters = (): void => {
logger.debug("ADRESSES", "initCartFormEventEmiters");
export const initCartFormEventEmitters = (): void => {
logger.debug("ADRESSES", "initCartFormEventEmitters");
E.FORMULAIRE_PANIER.addEventListener("change", (): void => {
logger.info("ADRESSES", "Changement du Formulaire Panier");
Maybe
@ -147,7 +146,7 @@ export const initShippingCalculationButton = (): void => {
.ifRight((cart: WCStoreCart): void => {
logger.debug("ADRESSES", "initShippingCalculationButton", "cart", cart);
/** La méthode de livraison sélectionnée dans le LocalStorage */
/** La méthode de livraison sélectionnée dans le SessionStorage */
const oldSelectedRateLS = getShippingRatesLS()
.chain(find(sr => sr.selected))
.ifJust(sr => logger.debug("ADRESSES", "initShippingCalculationButton", "oldSelectedRateLS", sr));
@ -157,7 +156,7 @@ export const initShippingCalculationButton = (): void => {
.chainNullable((sr: WCStoreShippingRate) => sr.shipping_rates)
.map((srs: Array<WCStoreShippingRateShippingRate>) =>
srs.map((sr: WCStoreShippingRateShippingRate, index: number) => {
// Sélectionne la nouvelle méthode demandée OU la première si le LocalStorage n'a pas été défini
// Sélectionne la nouvelle méthode demandée OU la première si le SessionStorage n'a pas été défini
oldSelectedRateLS.caseOf({
Just: sm => {
sr.selected = sr.method_id === sm.method_id;
@ -175,7 +174,7 @@ export const initShippingCalculationButton = (): void => {
)
.orDefault([]);
logger.debug("ADRESSES", "initShippingCalculationButton", "updatedRates", updatedRates);
// Met à jour les Méthodes de livraison dans le LocalStorage et le DOM
// Met à jour les Méthodes de livraison dans le SessionStorage et le DOM
window.dispatchEvent(createUpdatedShippingRatesEvent(updatedRates, true));
// Met à jour les Totaux
@ -191,7 +190,7 @@ export const initShippingCalculationButton = (): void => {
logger.debug("ADRESSES", "initShippingCalculationButton", "newTotals", newTotals);
window.dispatchEvent(createUpdatedTotalsEvent(newTotals));
// Réinitialise le Message affiché à l'Utiisateur
// Réinitialise le Message affiché à l'Utilisateur
E.MESSAGE_ADRESSES.textContent = " ";
// Active le Bouton pour la création de la Commande
E.BOUTON_ACTIONS_FORMULAIRE.textContent = "Check-out";
@ -238,7 +237,11 @@ export const initShippingCalculationButton = (): void => {
.finally((): void => setButtonLoadingState(E.BOUTON_ACTIONS_FORMULAIRE, false))
.run();
})
.ifNothing((): void => event.preventDefault());
// Ne fais rien si le Formulaire n'est pas valide.
.ifNothing((): void => {
event.preventDefault();
E.MESSAGE_ADRESSES.textContent = ERREUR_ADRESSE_GENERIQUE;
});
});
};
@ -267,7 +270,7 @@ export const initOrderCreationButton = (): void => {
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
emetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true);
throw new Error("LocalStorage indisponible.");
throw new Error("SessionStorage indisponible.");
})
.chain(first)
.orDefault({});

View file

@ -5,8 +5,8 @@ import type { UpdatedShippingRatesEvent, UpdatedTotalsEvent } from "../lib/evene
import { ATTRIBUT_LIVRAISON_VALIDEE } from "../constantes/dom";
import { ADRESSES_MAJ, CODE_PROMO_MAJ, SHIPPING_RATES_UPDATED, TOTALS_UPDATED } from "../constantes/evenements";
import { reporteEtJournaliseErreur } from "../lib/erreurs";
import { eitherSetLocalStorage } from "../lib/local-storage";
import { formateEnEuros } from "../lib/nombres";
import { eitherSetSessionStorage } from "../lib/session-storage";
import { logger } from "../logging";
import { E } from "./scripts-page-panier-elements";
import { generateShippingRatesHTML } from "./scripts-page-panier-methodes-livraison";
@ -48,8 +48,8 @@ export const souscrisEvenementsPanier = (): void => {
generateShippingRatesHTML(E.CONTENEUR_METHODES_LIVRAISON, event.shipping_rates);
}
})
// Met à jour le LocalStorage
.chain(event => eitherSetLocalStorage("shipping_rates", event.shipping_rates))
// Met à jour le SessionStorage
.chain(event => eitherSetSessionStorage("shipping_rates", event.shipping_rates))
.ifLeft(reporteEtJournaliseErreur);
});
@ -57,7 +57,7 @@ export const souscrisEvenementsPanier = (): void => {
Either
// La vérification du Schéma se fait à l'émission
.encase(() => (event as UpdatedTotalsEvent).detail.totals)
.chain(ts => eitherSetLocalStorage("totals", ts))
.chain(ts => eitherSetSessionStorage("totals", ts))
.ifLeft(reporteEtJournaliseErreur)
// Met à jour le DOM
.ifRight(ts => {

View file

@ -1,21 +1,19 @@
import type { Maybe } from "purify-ts";
import { reporteEtJournaliseErreur } from "../lib/erreurs";
import { getSessionStorageByKey, setSessionStorageByKey } from "../lib/session-storage";
import { WCStoreShippingRateShippingRatesSchema } from "../lib/schemas/api/couts-livraison";
import type { WCStoreShippingRateShippingRates } from "../lib/types/api/couts-livraison";
import { reporteEtJournaliseErreur } from "../lib/erreurs";
import { getLocalStorageByKey, setLocalStorageByKey } from "../lib/local-storage";
import { WCStoreShippingRateShippingRatesSchema } from "../lib/schemas/api/couts-livraison";
/* LS = LocalStorage */
/* LS = SessionStorage */
export const getShippingRatesLS = (): Maybe<WCStoreShippingRateShippingRates> =>
getLocalStorageByKey("shipping_rates", WCStoreShippingRateShippingRatesSchema)
getSessionStorageByKey("shipping_rates", WCStoreShippingRateShippingRatesSchema)
.ifLeft(reporteEtJournaliseErreur)
.toMaybe();
export const setShippingRatesLS = (
shippingRates: WCStoreShippingRateShippingRates,
): Maybe<WCStoreShippingRateShippingRates> =>
setLocalStorageByKey("shipping_rates", WCStoreShippingRateShippingRatesSchema)(shippingRates)
setSessionStorageByKey("shipping_rates", WCStoreShippingRateShippingRatesSchema)(shippingRates)
.ifLeft(reporteEtJournaliseErreur)
.toMaybe();

View file

@ -1,18 +1,16 @@
import { forEach as arrayForEach, map as arrayMap } from "@mobily/ts-belt/Array";
import { html, render, type TemplateResult } from "lit-html";
import type { WCStoreCartTotals, WCStoreShippingRateShippingRate } from "../lib/types/api/cart";
import type { WCStoreShippingRateShippingRates } from "../lib/types/api/couts-livraison";
import { ATTRIBUT_HIDDEN } from "../constantes/dom";
import { forEach, map } from "../lib/arrays";
import { getDOMElementsWithSelector } from "../lib/dom";
import { reporteEtJournaliseErreur } from "../lib/erreurs";
import { createUpdatedShippingRatesEvent, createUpdatedTotalsEvent } from "../lib/evenements/panier";
import { getLocalStorageByKey } from "../lib/local-storage";
import { getSessionStorageByKey } from "../lib/session-storage";
import { formateEnEuros } from "../lib/nombres";
import { find } from "../lib/safe-arrays";
import { WCStoreCartTotalsSchema } from "../lib/schemas/api/cart";
import type { WCStoreCartTotals, WCStoreShippingRateShippingRate } from "../lib/types/api/cart";
import type { WCStoreShippingRateShippingRates } from "../lib/types/api/couts-livraison";
import { logger } from "../logging";
import { E } from "./scripts-page-panier-elements";
import { getShippingRatesLS } from "./scripts-page-panier-local-storage";
@ -24,21 +22,21 @@ export const initShippingRatesChoicesActions = (): void => {
el.addEventListener("click", (event: MouseEvent): void => {
logger.info("METHODES_LIVRAISON", "Clic sur un choix de méthode de livraison");
// Récupère les méthodes du LocalStorage et les met à jour avec le nouveau choix
// Récupère les méthodes du SessionStorage et les met à jour avec le nouveau choix
getShippingRatesLS()
// Met à jour la sélection de la Méthode
.map(map((sr: WCStoreShippingRateShippingRate) => {
sr.selected = sr.method_id === (event.target as HTMLInputElement).value;
return sr;
}))
// Met à jour les Méthodes de livraison dans le LocalStorage et le DOM
// Met à jour les Méthodes de livraison dans le SessionStorage et le DOM
.ifJust((srs: WCStoreShippingRateShippingRates): void => {
window.dispatchEvent(createUpdatedShippingRatesEvent(srs, false));
})
// Met à jour les totaux dans le LocalStorage et le DOM
// Met à jour les totaux dans le SessionStorage et le DOM
.chain(find(sr => sr.selected))
.ifJust((sr: WCStoreShippingRateShippingRate): void => {
getLocalStorageByKey("totals", WCStoreCartTotalsSchema)
getSessionStorageByKey("totals", WCStoreCartTotalsSchema)
.ifLeft(reporteEtJournaliseErreur)
.map((ts: WCStoreCartTotals): WCStoreCartTotals => {
ts.total_shipping = sr.price;

View file

@ -5,13 +5,6 @@ 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 type { WCStoreCart } from "../lib/types/api/cart";
import type { WCStoreCartRemoveItemArgs } from "../lib/types/api/cart-remove-item";
import type { WCStoreCartUpdateItemArgs } from "../lib/types/api/cart-update-item";
import type { GenericPageState } from "../lib/types/pages";
import type { FetchErrors, HttpCodeErrors } from "../lib/types/reseau";
import { ROUTE_API_MAJ_ARTICLE_PANIER, ROUTE_API_RETIRE_ARTICLE_PANIER } from "../constantes/api";
import {
ATTRIBUT_CLE_PANIER,
@ -34,6 +27,11 @@ import { newPartialResponse, postBackend, safeFetch, traiteErreursBackendWooComm
import { WCStoreCartSchema } from "../lib/schemas/api/cart";
import { WCStoreCartRemoveItemArgsSchema } from "../lib/schemas/api/cart-remove-item";
import { WCStoreCartUpdateItemArgsSchema } from "../lib/schemas/api/cart-update-item";
import type { WCStoreCart } from "../lib/types/api/cart";
import type { WCStoreCartRemoveItemArgs } from "../lib/types/api/cart-remove-item";
import type { WCStoreCartUpdateItemArgs } from "../lib/types/api/cart-update-item";
import type { GenericPageState } from "../lib/types/pages";
import type { FetchErrors, HttpCodeErrors } from "../lib/types/reseau";
import { safeSchemaParse } from "../lib/validation";
import { E } from "./scripts-page-panier-elements";

View file

@ -26,7 +26,7 @@ import { valideMessageMajBoutonPanier, valideMessageMajContenuPanier } from "./l
import { arrondisADeuxDecimales, diviseParCent, formateEnEuros, inverseNombre } from "./lib/nombres.ts";
import { propEither } from "./lib/utils.ts";
import {
initCartFormEventEmiters,
initCartFormEventEmitters,
initOrderCreationButton,
initShippingCalculationButton,
} from "./page-panier/scripts-page-panier-adresses.ts";
@ -152,17 +152,17 @@ const initialiseMajFormulairesPanier = (): void => {
E.BOUTON_SEPARATION_ADRESSES.addEventListener("click", (): void => {
Maybe
.fromFalsy(E.BOUTON_SEPARATION_ADRESSES.checked)
// Les Adresses sont séparées
// Les Adresses sont séparées.
.ifJust((): void => {
// Rend visible le formulaire de facturation
// Rend visible le formulaire de facturation.
E.FORMULAIRE_FACTURATION.removeAttribute(ATTRIBUT_HIDDEN);
getDOMElementsWithSelector(E.FORMULAIRE_FACTURATION)("input, select").ifRight(
arrayForEach(champ => champ.removeAttribute(ATTRIBUT_DESACTIVE)),
);
})
// Les Adresses sont combinées
// Les Adresses sont combinées.
.ifNothing((): void => {
// Cache le formulaire de facturation
// Cache le formulaire de facturation.
E.FORMULAIRE_FACTURATION.setAttribute(ATTRIBUT_HIDDEN, "");
getDOMElementsWithSelector(E.FORMULAIRE_FACTURATION)<HTMLInputElement | HTMLSelectElement>(
"input, select",
@ -175,7 +175,7 @@ const initialiseMajFormulairesPanier = (): void => {
};
document.addEventListener("DOMContentLoaded", (): void => {
initCartFormEventEmiters();
initCartFormEventEmitters();
souscrisEvenementsPanier();
initialiseActionsEntreesPanier();
initShippingRatesChoicesActions();

View file

@ -12,6 +12,10 @@
srcset="{{ rel_url }}.webp"
type="image/webp"
>
<source
srcset="{{ rel_url }}.png"
type="image/png"
>
<img
alt="{{ alt }}"