◆ Portail Antalaha

Annuaire › Code ouvert

Réservations de sorties en pirogue (Alpine.js)

tutorial · Voir le site ↗
Connectez-vous pour copier ce site

Code publié par son auteur, en lecture seule. « Copier dans mon espace » crée un nouveau site à vous (non publié) que vous pouvez modifier librement.

js/outils.js · 4.5 Ko

/* ==========================================================================
   js/outils.js — Petites fonctions utilitaires, SANS rapport avec Alpine
   --------------------------------------------------------------------------
   Ce fichier crée un objet global « Outils » utilisé par les autres scripts :
     - un stockage sûr (localStorage avec repli en mémoire) ;
     - des fonctions de dates ;
     - le formatage de l'Ariary ;
     - des identifiants uniques.

   Séparer ces fonctions « pures » du code Alpine rend le tout plus lisible
   et plus simple à tester.

   ORDRE DE CHARGEMENT : ce fichier doit venir en PREMIER (avant store.js et
   composants.js), car ils s'en servent. Voir la fin d'index.html.
   ========================================================================== */

const Outils = (function () {

  /* ------------------------------------------------------------------
     STOCKAGE SÛR
     Dans le bac à sable du portail, la simple lecture de
     window.localStorage lève une SecurityError. Si on n'attrape pas
     l'erreur, tout le script s'arrête ! On garde donc un « plan B » :
     un objet en mémoire (perdu au rechargement, mais l'appli marche).
     ------------------------------------------------------------------ */
  const memoire = {};          // plan B : données gardées dans la page
  let enMemoire = false;       // devient true si localStorage est inutilisable

  /** Lit une chaîne enregistrée, ou null si absente. */
  function lire(cle) {
    try {
      return window.localStorage.getItem(cle);
    } catch (erreur) {
      enMemoire = true;
      return Object.prototype.hasOwnProperty.call(memoire, cle) ? memoire[cle] : null;
    }
  }

  /** Enregistre une chaîne. */
  function ecrire(cle, valeur) {
    try {
      window.localStorage.setItem(cle, valeur);
    } catch (erreur) {
      enMemoire = true;
      memoire[cle] = valeur;
    }
  }

  /* ------------------------------------------------------------------
     DATES
     On manipule les dates sous forme de texte ISO « AAAA-MM-JJ » : c'est
     le format des <input type="date">, et on peut les comparer
     directement comme des textes ("2026-03-01" < "2026-03-15").
     ------------------------------------------------------------------ */

  /** Met un nombre sur 2 chiffres : 5 -> "05". */
  function deuxChiffres(n) {
    return String(n).padStart(2, '0');
  }

  /** Transforme un objet Date en « AAAA-MM-JJ » (heure LOCALE). */
  function versIso(date) {
    return date.getFullYear() + '-' + deuxChiffres(date.getMonth() + 1) + '-' + deuxChiffres(date.getDate());
  }

  /** La date d'aujourd'hui au format ISO. */
  function aujourdhui() {
    return versIso(new Date());
  }

  /** La date dans « n » jours (n peut être négatif). */
  function dansJours(n) {
    const d = new Date();
    d.setDate(d.getDate() + n);
    return versIso(d);
  }

  /** Vrai si le texte est une vraie date ISO (refuse "2026-02-31"). */
  function dateValide(iso) {
    if (typeof iso !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(iso)) return false;
    const d = new Date(iso + 'T00:00:00');
    return !isNaN(d.getTime()) && versIso(d) === iso;
  }

  /** « 2026-03-05 » -> « jeu. 5 mars 2026 » */
  function dateLisible(iso) {
    if (!dateValide(iso)) return '—';
    return new Date(iso + 'T00:00:00').toLocaleDateString('fr-FR', {
      weekday: 'short', day: 'numeric', month: 'long', year: 'numeric'
    });
  }

  /* ------------------------------------------------------------------
     DIVERS
     ------------------------------------------------------------------ */

  /** 1234567 -> « 1 234 567 Ar » */
  function formatAriary(n) {
    const nombre = Number(n) || 0;
    return new Intl.NumberFormat('fr-FR', { maximumFractionDigits: 0 }).format(nombre) + ' Ar';
  }

  /** « Jean Rakoto » -> « JR » (pour l'avatar). */
  function initiales(nom) {
    const mots = String(nom || '').trim().split(/\s+/).filter(Boolean);
    if (mots.length === 0) return '?';
    if (mots.length === 1) return mots[0].slice(0, 2).toUpperCase();
    return (mots[0][0] + mots[mots.length - 1][0]).toUpperCase();
  }

  /** Identifiant unique : heure en base 36 + hasard. */
  function nouvelId() {
    return Date.now().toString(36) + Math.random().toString(36).slice(2, 7);
  }

  // On expose ce qui doit être utilisable ailleurs.
  return {
    lire, ecrire, aujourdhui, dansJours, dateValide, dateLisible,
    formatAriary, initiales, nouvelId,
    /** Vrai si le stockage durable est indisponible. */
    get enMemoire() { return enMemoire; }
  };
})();