Skip to content

Instantly share code, notes, and snippets.

@FlorenceBuchelet
Last active December 23, 2024 10:02
Show Gist options
  • Select an option

  • Save FlorenceBuchelet/3a79cc0c143f11578e9e27f4466b5007 to your computer and use it in GitHub Desktop.

Select an option

Save FlorenceBuchelet/3a79cc0c143f11578e9e27f4466b5007 to your computer and use it in GitHub Desktop.

Mise à jour fiche produit Hors Livre

Objectif : Enrichir la liste d'informations des produits Hors Livre.

Branche : feature/non_books_product_sheet

Composants concernés

ProductSummaryCaracteristics.tsx

Route : app/theme/components/organisms/ProductSummary/ProductSummaryCaracteristics/ProductSummaryCaracteristics.tsx

Les caractéristiques étant mapées sur l'objet availableInfos, lui-même filtré sur l'objet infos, il n'y a rien à éditer dans le retour du composant, c'est cet objet qu'il faudra étudier.

    const availableInfos = infos?.filter((info) => !!info.value);

    return (
        availableInfos &&
        availableInfos.length > 0 && (
        <div className="product-summary-caracteristics">
            <div className="list-wrapper" ref={$wrapper}>
            <ul className="list" ref={$list}>
                {availableInfos.map((info, index) => {
                return (
                    info.title &&
                    info.value && (
                    <li key={index} ref={(el) => el && $infos.current.push(el)}>
                        <Caption className="title">{info.title}</Caption>
                        <Body3>{info.value}</Body3>
                    </li>
                    )
                );
            })}
                (...)
        )
    )

Plutôt que de mettre des conditions très complexes dans l'objet infos, nous avons créé trois objets : un pour les jeux (infosGame), un pour le hors livre (infosNonBookNonGame) et un dernier générique (infosGeneric).

Grâce à des vérifications de type, nous pouvons faire en sorte que l'objet infos corresponde au bon type de produit. Certaines vérifications de types sont également utilisées dans l'objet générique.

  const productType = product.product_type ?? "";

  const isNonBookNonGame = [DCTR_TYPES.MUSIC, DCTR_TYPES.GAMES, DCTR_TYPES.STATIONERY, DCTR_TYPES.eREADERS].includes(
    productType
  );
  const isBookOrEBook = [DCTR_TYPES.BOOK, DCTR_TYPES.EBOOK].includes(productType);
  const isBook = [DCTR_TYPES.BOOK].includes(productType);
  const isGame = [DCTR_TYPES.GAMES].includes(productType) || product.breadcrumbs[0].name.toLowerCase().includes("jeux");
  const isStationery = [DCTR_TYPES.STATIONERY].includes(productType);
  const isMusic = [DCTR_TYPES.MUSIC].includes(productType);

  (...)

  let infos;

  if (isGame) {
    infos = infosGames;
  } else if (isNonBookNonGame) {
    infos = infosNonBookNonGame;
  } else {
    infos = infosGeneric;
  }

  const availableInfos = infos?.filter((info) => !!info.value);

A noter : en attendant l'implémentation du type JJ (jeux/jouets), les jeux sont identifiés à partir du premier breadcrumbs.

ProductSummaryCaracteristics.tsx > objet infos

Les trois objets :

  const infosGeneric = [
    {
      title: l10n("product.caracteristics.page_number"),
      value: product.number_of_pages ?? null
    },
    {
      title: l10n("product.caracteristics.presentation"),
      value: productType === DCTR_TYPES.BOOK ? product.presentation?.name : null
    },
    {
      title: l10n("product.caracteristics.format"),
      value: isBookOrEBook || isMusic ? (ebookFormatLabel ?? product.format?.name) : null
    },
    {
      title: l10n("product.caracteristics.weight"),
      value:
        product.weight && product.weight > 0
          ? product.weight + " " + l10n("product.caracteristics.weight.kilograms")
          : null
    },
    {
      title: l10n("product.caracteristics.dimensions"),
      value: isBook || isMusic ? product.dimensions : null
    },
    {
      title: l10n("product.caracteristics.isbn"),
      value: product.isbn ?? null
    },
    { title: l10n("product.caracteristics.ean"), value: productType !== DCTR_TYPES.eREADERS ? product.ean : null },
    {
      title: l10n("product.caracteristics.release_date"),
      value: isBookOrEBook || isMusic ? new Date(product.publication_date).toLocaleDateString("fr-FR") : null
    },
    {
      title: l10n("product.caracteristics.collection"),
      value: isBook || isMusic ? product?.collection?.name : null
    },
    {
      title: l10n("product.caracteristics.supplier"),
      value: isMusic ? product.supplier?.name : null
    },
    {
      title: l10n("product.caracteristics.supplier.ref"),
      value: isMusic ? product.supplier?.ref : null
    },
    {
      title: l10n("product.caracteristics.copy_right"),
      value: product.ebook_information?.copy_right ?? null
    },
    {
      title: l10n("product.caracteristics.protected"),
      value: product?.ebook_information?.protection_name ?? null
    },
    {
      title: l10n("product.caracteristics.file_size"),
      value: getEbookFileSizeLabel(product)
    },
    {
      title: l10n("product.caracteristics.multidevices"),
      value: product.ebook_information?.multi_devices ?? null
    },
    {
      title: l10n("product.caracteristics.more_format_information"),
      value: product.ebook_information?.more_format_information ?? null
    },
    {
      title: l10n("product.caracteristics.editor"),
      value: product.publisher?.name ?? null
    },
    ...authorsWithoutMainAuthor.map((author) => {
      return { title: author?.function_name, value: author?.name };
    })
  ];

  const infosNonBookNonGame = [
    {
      title: l10n("product.caracteristics.dctr_commercial_brand"),
      value: product.dctr_commercial_brand ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_supplier_name"),
      value: product.supplier?.name ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_ecriture_couleurs"),
      value: product.dctr_ecriture_couleurs ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_couleurs"),
      value: product.dctr_couleurs ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_type_pointe"),
      value: product.dctr_type_pointe ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_diametre_pointe"),
      value: product.dctr_diametre_pointe ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_ean"),
      value: product.base_ean ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_supplier_ref"),
      value: product.supplier?.ref ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_composants"),
      value: product.dctr_composants ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_dimensions"),
      value: product.dimensions
        ? `${product.dctr_dimensions.length} x ${product.dctr_dimensions.width} x ${product.dctr_dimensions.height}`
        : null
    },
    {
      title: l10n("product.caracteristics.weight"),
      value:
        product.weight && product.weight > 0
          ? product.weight + " " + l10n("product.caracteristics.weight.kilograms")
          : null
    },
    {
      title: l10n("product.caracteristics.dctr_qte_lot"),
      value: product.dctr_qte_lot ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_number_of_pages"),
      value: product.dctr_number_of_pages ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_volume_sac"),
      value: product.dctr_volume_sac ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_certificats_authenticite"),
      value: product.dctr_certificats_authenticite ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_volume_papet"),
      value: product.dctr_volume_papet ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_grammage"),
      value: product.dctr_grammage ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_preference_manuelle"),
      value: product.dctr_preference_manuelle ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_rechargeable"),
      value: product.dctr_rechargeable ? l10n("common.yes") : null
    },
    {
      title: l10n("product.caracteristics.dctr_effacable"),
      value: product.dctr_effacable ? l10n("common.yes") : null
    },
    {
      title: l10n("product.caracteristics.dctr_indelebile"),
      value: product.dctr_indelebile ? l10n("common.yes") : null
    },
    {
      title: l10n("product.caracteristics.dctr_type_bille"),
      value: product.dctr_type_bille ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_diametre_bille"),
      value: product.dctr_diametre_bille ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_type_encre"),
      value: product.dctr_type_encre ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_aquarellable"),
      value: product.dctr_aquarellable ? l10n("common.yes") : null
    },
    {
      title: l10n("product.caracteristics.dctr_waterproof"),
      value: product.dctr_waterproof ? l10n("common.yes") : null
    },
    {
      title: l10n("product.caracteristics.dctr_reglure"),
      value: product.dctr_reglure ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_nb_piles"),
      value:
        product.dctr_nb_piles && product.dctr_nb_piles > 0 ? product.dctr_nb_piles : null
    },
    {
      title: l10n("product.caracteristics.dctr_type_piles"),
      value:
        product.dctr_nb_piles && product.dctr_nb_piles > 0 ? product.dctr_type_piles : null
    },
    {
      title: l10n("product.caracteristics.dctr_batteries_incluses"),
      value: (() => {
        if (product.dctr_nb_piles && product.dctr_nb_piles > 0) {
          return product.dctr_batteries_incluses ? l10n("common.yes") : l10n("common.no");
        }
        return null;
      })()
    },
    {
      title: l10n("product.caracteristics.dctr_normes_conformite"),
      value: product.dctr_normes_conformite ?? null
    },
    ...authorsWithoutMainAuthor.map((author) => {
      return { title: author?.function_name, value: author?.name };
    })
  ];

  const infosGames = [
    {
      title: l10n("product.caracteristics.dctr_age_lecture_min"),
      value: product.dctr_age_lecture_min ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_nb_joueur_min"),
      value: product.dctr_nb_joueur_min ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_nb_joueur_max"),
      value: product.dctr_nb_joueur_max ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_mecaniques"),
      value: product.dctr_mecaniques ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_themes_jeu"),
      value: product.dctr_themes_jeu ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_supplier_name"),
      value: product.supplier?.name ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_commercial_brand"),
      value: product.dctr_commercial_brand ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_temps_jeu_min"),
      value: product.dctr_temps_jeu_min ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_temps_jeu_max"),
      value: product.dctr_temps_jeu_max ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_publication_date"),
      value: product.dctr_publication_date ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_foreign_edition_name"),
      value: product.dctr_foreign_edition_name ?? null
    },

    {
      title: l10n("product.caracteristics.dctr_ean"),
      value: product.base_ean ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_dimensions"),
      value: product.dimensions
        ? `${product.dctr_dimensions.length} x ${product.dctr_dimensions.width} x ${product.dctr_dimensions.height}`
        : null
    },
    {
      title: l10n("product.caracteristics.weight"),
      value:
        product.weight && product.weight > 0
          ? product.weight + " " + l10n("product.caracteristics.weight.kilograms")
          : null
    },
    {
      title: l10n("product.caracteristics.dctr_nb_piles"),
      value:
        product.dctr_nb_piles && product.dctr_nb_piles > 0 ? product.dctr_nb_piles : null
    },
    {
      title: l10n("product.caracteristics.dctr_type_piles"),
      value:
        product.dctr_nb_piles && product.dctr_nb_piles > 0 ? product.dctr_type_piles : null
    },
    {
      title: l10n("product.caracteristics.dctr_batteries_incluses"),
      value: (() => {
        if (product.dctr_nb_piles && product.dctr_nb_piles > 0) {
          return product.dctr_batteries_incluses ? l10n("common.yes") : l10n("common.no");
        }
        return null;
      })()
    },
    {
      title: l10n("product.caracteristics.dctr_normes_conformite"),
      value: product.dctr_normes_conformite ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_supplier_ref"),
      value: product.supplier?.ref ?? null
    },
    {
      title: l10n("product.caracteristics.dctr_recompenses_jeu"),
      value: product.dctr_recompenses_jeu ?? null
    },
    ...authorsWithoutMainAuthor.map((author) => {
      return { title: author?.function_name, value: author?.name };
    })
  ];

⚠️⚠️ Attention : les valeurs sont ordonnées dans ces objets selon l'ordre d'affichage décidé pour le projet (voir avec Camille Hernoux).

Chaque label étant géré par le hook useL10n(), il a également fallu ajouter les labels supplémentaires dans le fichier de localisation (lang/fr.json lignes 450+ "product.caracteristics.NOM_DE_LA_CARACTERISTIQUE").
(Attention, les changements de ce fichier demandent à relancer le projet pour être pris en compte)

  "product.caracteristics.dctr_ean": {
    "defaultMessage": "EAN"
  },
  "product.caracteristics.dctr_commercial_brand": {
    "defaultMessage": "Marque"
  },
  "product.caracteristics.dctr_supplier_name": {
    "defaultMessage": "Fournisseur"
  },
  "product.caracteristics.dctr_supplier_ref": {
    "defaultMessage": "Réf. fournisseur"
  },
  "product.caracteristics.dctr_publication_date": {
    "defaultMessage": "Date de parution"
  },
  "product.caracteristics.dctr_couleurs": {
    "defaultMessage": "Couleurs"
  },
  "product.caracteristics.dctr_ecriture_couleurs": {
    "defaultMessage": "Couleurs d'écriture"
  },
  "product.caracteristics.dctr_composants": {
    "defaultMessage": "Matières"
  },
  "product.caracteristics.dctr_foreign_edition_name": {
    "defaultMessage": "Langue"
  },
  "product.caracteristics.dctr_age_lecture_min": {
    "defaultMessage": "Age minimum"
  },
  "product.caracteristics.dctr_age_lecture_max": {
    "defaultMessage": "Age maximum"
  },
  "product.caracteristics.dctr_nb_joueur_min": {
    "defaultMessage": "Nombre de joueurs"
  },
  "product.caracteristics.dctr_nb_joueur_max": {
    "defaultMessage": "Nombre de joueurs"
  },
  "product.caracteristics.dctr_temps_jeu_min": {
    "defaultMessage": "Durée de la partie"
  },
  "product.caracteristics.dctr_temps_jeu_max": {
    "defaultMessage": "Durée de la partie"
  },
  "product.caracteristics.dctr_recompenses_jeu": {
    "defaultMessage": "Récompenses"
  },
  "product.caracteristics.dctr_mecaniques": {
    "defaultMessage": "Mécaniques"
  },
  "product.caracteristics.dctr_themes_jeu": {
    "defaultMessage": "Thèmes"
  },
  "product.caracteristics.dctr_volume_sac": {
    "defaultMessage": "Contenance"
  },
  "product.caracteristics.dctr_grammage": {
    "defaultMessage": "Grammage"
  },
  "product.caracteristics.dctr_reglure": {
    "defaultMessage": "Réglure"
  },
  "product.caracteristics.dctr_number_of_pages": {
    "defaultMessage": "Nb. de pages"
  },
  "product.caracteristics.dctr_qte_lot": {
    "defaultMessage": "Capacité unité"
  },
  "product.caracteristics.dctr_volume_papet": {
    "defaultMessage": "Contenance"
  },
  "product.caracteristics.dctr_normes_conformite": {
    "defaultMessage": "Normes de conformité"
  },
  "product.caracteristics.dctr_dimensions": {
    "defaultMessage": "Dimensions"
  },
  // .length, .width, .height ??
  "product.caracteristics.dctr_certificats_authenticite": {
    "defaultMessage": "Certificats d'authenticité"
  },
  "product.caracteristics.dctr_nb_piles": {
    "defaultMessage": "Piles"
  },
  "product.caracteristics.dctr_type_piles": {
    "defaultMessage": "Piles"
  },
  "product.caracteristics.dctr_batteries_incluses": {
    "defaultMessage": "Piles"
  },
  "product.caracteristics.dctr_preference_manuelle": {
    "defaultMessage": "Main d'écriture"
  },
  "product.caracteristics.dctr_rechargeable": {
    "defaultMessage": "Rechargeable"
  },
  "product.caracteristics.dctr_effacable": {
    "defaultMessage": "Effaçable"
  },
  "product.caracteristics.dctr_indelebile": {
    "defaultMessage": "Indélébile"
  },
  "product.caracteristics.dctr_type_pointe": {
    "defaultMessage": "Type de pointe"
  },
  "product.caracteristics.dctr_diametre_pointe": {
    "defaultMessage": "Diamètre de la pointe"
  },
  "product.caracteristics.dctr_type_bille": {
    "defaultMessage": "Type de bille"
  },
  "product.caracteristics.dctr_diametre_bille": {
    "defaultMessage": "Diamètre de la bille"
  },
  "product.caracteristics.dctr_type_encre": {
    "defaultMessage": "Type d'encre"
  },
  "product.caracteristics.dctr_aquarellable": {
    "defaultMessage": "Couleur aquarellable"
  },
  "product.caracteristics.dctr_waterproof": {
    "defaultMessage": "Waterproof"
  },

Autres éléments

Listes des valeurs à ajouter basées sur le tableau HL - List Attributs (Données par fiche produit) associées aux données déjà mapées (ex. ean), par ordre de priorité d'affichage :

Hors livre générique :

  • Titre : Libellé article WEB => title
  • Nom marque commerciale/ Nom fournisseur
  • Couleurs d'écriture
  • Couleurs du produit
  • Type de pointe
  • Diamètre de la pointe
  • EAN13 => ean
  • Référence fournisseur => supplier.ref
  • Hauteur / Largeur / Epaisse => dimensions à préciser au format L x l x h
  • Poids => weight
  • Capacité unité (quantité lot ?)
  • Nombre de pages
  • Contenance (sac)
  • Certificats d'authenticité
  • Contenance (papet)
  • Grammage
  • Main d'écriture
  • Rechargeable
  • Effacable
  • Indélébile
  • Type de bille
  • Diamètre de la bille
  • Type d'encre
  • Couleur aquarellable
  • waterproof
  • Réglure
  • Normes de conformités
  • Nombre de piles / batterie
  • Piles / batteries requises
  • Piles / batteries incluses
  • Normes de conformité

Jeux :

  • Titre : Libellé article WEB
  • Age minimum
  • Nombre joueurs minimum
  • Nombre joueurs maximum
  • Mécaniques
  • Thème
  • Nom marque commerciale / Nom fournisseur => supplier à préciser
  • Temps jeu minimum / Temps jeu maximum
  • Date de mise en vente => release_date
  • Langue
  • EAN13
  • Hauteur / Largeur / Epaisse => dimensions à préciser au format L x l x h
  • Poids => weight
  • Extensions du produits
  • Nombre de piles / batterie
  • Piles / batteries requises
  • Piles / batteries incluses
  • Normes de conformité
  • Référence fournisseur => supplier.ref
  • Mention d'édition / Normes de conformité
  • Récompenses

Visibiité désirée en jeux mais ignoré sur la version actuelle :

  • Auteur 1 (pas d'ordre indiqué)
  • Auteur 2 (pas d'ordre indiqué)
  • Illustrateur 1 (pas d'ordre indiqué)
  • Illustrateur 2 (pas d'ordre indiqué)
  • Age maximum (pas d'ordre indiqué)

Tableau des types produits:

export const DCTR_TYPES = {
  BOOK: "L",
  EBOOK: "LN",
  CD: "CD",
  eREADERS: "T",
  STATIONERY: "P",
  AUDIO_BOOK: "LA",
  GAMES: "JJ", // Changement de J à JJ
  MUSIC: "MN",
  EPUB: "EP"
};

TODO:

  • Gérer le formatage des différentes données (en particulier Dimensions)
  • Faire attention au passage de J à JJ
  • Enlever la gestion du type jeu sur les breadcrumbs
  • Fix : eslint-disable
  • Fix : Nous avons ajouté (product as any) car pour le moment les caractéristiques ne sont pas dans les types qui seront générés à partir de la forme des données fournies par le back
  • Enlever les caractéristiques "Is Book?", "Is Non Book?" et "Is Game?"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment