/* Page /make-pennylane-automatisation-facturation — cas d'usage généré automatiquement (pipeline GSC).
 * Gabarit standard BoomMaker : hero + sections + FAQ + CTA. CSS partagés only. */

const { useState } = React;
const { Logo, ArrowUpRight, Check, ThemeToggle, FooterMin, useReveal } = window.BMShared;

const C = {
  "slug": "make-pennylane-automatisation-facturation",
  "breadcrumb": "Make + Pennylane",
  "eyebrow": "Opérations · Facturation 2026",
  "h1": "Make + Pennylane : ta facturation",
  "h1Em": "enfin automatisée sans dev",
  "lead": "Pennylane gère tes factures et ta compta. Make connecte tout le reste. Ensemble, ils éliminent les ressaisies, les relances oubliées et les exports manuels qui te font perdre du temps chaque semaine.",
  "blocks": [
    {
      "type": "flow",
      "eyebrow": "Comment ça marche",
      "h2": "Un exemple concret de flux Make + Pennylane",
      "h2Em": "",
      "intro": "Voici ce que ça donne quand une facture passe en retard de paiement dans Pennylane.",
      "paragraphs": [],
      "stats": [],
      "cards": [],
      "steps": [],
      "items": [],
      "columns": [],
      "rows": [],
      "cases": [],
      "nodes": [
        {
          "label": "Facture en retard",
          "sub": "Pennylane détecte l'échéance dépassée",
          "kind": "trigger"
        },
        {
          "label": "Make se déclenche",
          "sub": "Le scénario s'active automatiquement",
          "kind": "action"
        },
        {
          "label": "Email de relance envoyé",
          "sub": "Personnalisé avec nom, montant, lien de paiement",
          "kind": "action"
        },
        {
          "label": "Airtable mis à jour",
          "sub": "Statut relance tracé dans ton tableau de bord",
          "kind": "action"
        },
        {
          "label": "Zéro ressaisie, zéro oubli",
          "sub": "Le suivi est complet sans action manuelle",
          "kind": "result"
        }
      ],
      "note": "Ce flux se construit en quelques heures avec Make. Aucune ligne de code.",
      "label": "",
      "text": ""
    },
    {
      "type": "stats",
      "eyebrow": "Ce que ça change",
      "h2": "Du temps récupéré chaque semaine",
      "h2Em": "",
      "intro": "Ce sont des ordres de grandeur observés sur des configurations similaires, pas des promesses.",
      "paragraphs": [],
      "stats": [
        {
          "value": "3 à 6 h",
          "label": "gagnées par semaine sur les tâches de facturation et relances manuelles"
        },
        {
          "value": "quelques jours",
          "label": "pour mettre en place un premier flux Make + Pennylane opérationnel"
        },
        {
          "value": "0 ressaisie",
          "label": "entre Pennylane et tes autres outils une fois le scénario actif"
        },
        {
          "value": "1 tableau de bord",
          "label": "pour suivre paiements, relances et trésorerie en temps réel dans Airtable"
        }
      ],
      "cards": [],
      "steps": [],
      "items": [],
      "columns": [],
      "rows": [],
      "cases": [],
      "nodes": [],
      "note": "",
      "label": "",
      "text": ""
    },
    {
      "type": "cards",
      "eyebrow": "Cas d'usage",
      "h2": "Ce que tu peux automatiser concrètement",
      "h2Em": "",
      "intro": "Make peut se connecter à Pennylane via webhook ou API pour déclencher des actions dans tes autres outils.",
      "paragraphs": [],
      "stats": [],
      "cards": [
        {
          "tag": "Cas 01",
          "title": "Relances clients automatiques",
          "body": "Dès qu'une facture dépasse son échéance dans Pennylane, Make envoie un email de relance personnalisé. Tu paramètres le délai, le ton et le contenu. Plus aucun impayé oublié."
        },
        {
          "tag": "Cas 02",
          "title": "Reporting trésorerie en temps réel",
          "body": "Make récupère les données de Pennylane et les pousse dans Airtable ou Google Sheets. Tu as un tableau de bord à jour sans exporter manuellement quoi que ce soit."
        },
        {
          "tag": "Cas 03",
          "title": "Notification équipe à la réception d'un paiement",
          "body": "Quand un client paie, Make envoie une alerte Slack ou email à ton équipe commerciale. Utile pour déclencher un onboarding ou une action de suivi immédiatement."
        },
        {
          "tag": "Cas 04",
          "title": "Création automatique de facture depuis un CRM",
          "body": "Un deal passe en statut gagné dans ton CRM, Make crée la facture correspondante dans Pennylane avec les bonnes infos. Zéro ressaisie, zéro erreur de montant."
        }
      ],
      "steps": [],
      "items": [],
      "columns": [],
      "rows": [],
      "cases": [],
      "nodes": [],
      "note": "",
      "label": "",
      "text": ""
    },
    {
      "type": "steps",
      "eyebrow": "Par où commencer",
      "h2": "Mettre en place Make + Pennylane en 4 étapes",
      "h2Em": "",
      "intro": "",
      "paragraphs": [],
      "stats": [],
      "cards": [],
      "steps": [
        {
          "title": "Identifier le flux le plus douloureux",
          "body": "Relances oubliées, exports manuels, ressaisies entre outils : commence par le problème qui te coûte le plus de temps ou d'argent chaque semaine."
        },
        {
          "title": "Connecter Pennylane à Make via webhook",
          "body": "Pennylane expose des webhooks natifs sur les événements clés (facture créée, payée, en retard). Make les capte et déclenche le scénario correspondant."
        },
        {
          "title": "Construire le scénario no-code dans Make",
          "body": "Tu configures les modules Make pour chaque étape : condition, transformation des données, envoi vers l'outil cible (Slack, Gmail, Airtable, HubSpot, etc.)."
        },
        {
          "title": "Tester, ajuster, activer",
          "body": "Make te permet de tester chaque étape avant de mettre le flux en production. Une fois validé, il tourne seul, 24h/24, sans intervention."
        }
      ],
      "items": [],
      "columns": [],
      "rows": [],
      "cases": [],
      "nodes": [],
      "note": "",
      "label": "",
      "text": ""
    },
    {
      "type": "cases",
      "eyebrow": "Profils types",
      "h2": "Qui utilise ce type d'automatisation",
      "h2Em": "",
      "intro": "Ces profils sont représentatifs des configurations que Boom Maker met en place. Aucun client nommé.",
      "paragraphs": [],
      "stats": [],
      "cards": [],
      "steps": [],
      "items": [],
      "columns": [],
      "rows": [],
      "cases": [
        {
          "profile": "Dirigeant de PME de services (10 à 30 salariés)",
          "context": "Il gère lui-même la facturation dans Pennylane mais perd 4 à 5 heures par semaine en relances manuelles et exports pour son expert-comptable.",
          "result": "Après mise en place de Make, les relances partent seules, le reporting est automatique. Il récupère ces heures pour des sujets à plus forte valeur."
        },
        {
          "profile": "Responsable administratif et financier de TPE",
          "context": "Elle jongle entre Pennylane, un CRM et des tableurs pour suivre la trésorerie. Les données ne sont jamais synchronisées au même moment.",
          "result": "Un flux Make centralise les données Pennylane dans Airtable en temps réel. Le tableau de bord est toujours à jour sans action manuelle."
        }
      ],
      "nodes": [],
      "note": "",
      "label": "",
      "text": ""
    },
    {
      "type": "callout",
      "eyebrow": "",
      "h2": "",
      "h2Em": "",
      "intro": "",
      "paragraphs": [],
      "stats": [],
      "cards": [],
      "steps": [],
      "items": [],
      "columns": [],
      "rows": [],
      "cases": [],
      "nodes": [],
      "note": "",
      "label": "À retenir",
      "text": "Make ne remplace pas Pennylane, il le prolonge. L'objectif est simple : les données entrent une seule fois, les actions se déclenchent automatiquement, ton équipe ne ressaisit plus rien."
    }
  ],
  "faq": [
    {
      "q": "Pennylane a-t-il une API ou des webhooks compatibles avec Make ?",
      "a": "Oui. Pennylane expose des webhooks sur les événements clés (facture créée, payée, en retard, avoir émis). Make les capte nativement via son module Webhook. Pour des appels plus avancés, l'API REST de Pennylane est accessible avec une clé API."
    },
    {
      "q": "Faut-il savoir coder pour connecter Make à Pennylane ?",
      "a": "Non. Make est une plateforme no-code. Tu configures les flux visuellement, module par module. Boom Maker peut aussi te livrer le scénario clé en main si tu préfères ne pas t'en occuper."
    },
    {
      "q": "Combien de temps faut-il pour mettre en place un premier flux ?",
      "a": "Pour un flux simple (relances automatiques ou notification de paiement), compte quelques heures à quelques jours selon la complexité de tes outils existants. Un flux plus complet avec reporting Airtable peut prendre une à deux semaines."
    },
    {
      "q": "Make peut-il aussi créer des factures dans Pennylane automatiquement ?",
      "a": "Oui, via l'API Pennylane. Make peut créer une facture dès qu'un événement se produit dans un autre outil : deal gagné dans un CRM, formulaire rempli, ligne ajoutée dans un tableur. Les données sont transmises sans ressaisie."
    },
    {
      "q": "Quel est le coût de Make pour ce type d'usage ?",
      "a": "Make propose un plan gratuit limité et des plans payants à partir de quelques dizaines d'euros par mois selon le volume d'opérations. Pour la plupart des TPE/PME, le plan Core ou Pro suffit. Le coût est généralement amorti très rapidement par le temps gagné."
    },
    {
      "q": "Est-ce que ça fonctionne aussi avec la facturation électronique obligatoire 2026 ?",
      "a": "Pennylane est positionné comme plateforme de dématérialisation partenaire (PDP) pour la réforme 2026. Make peut s'intégrer dans ce contexte pour automatiser les flux autour de la facture électronique, notamment les notifications, le suivi et le reporting. Les détails de conformité restent à valider avec ton expert-comptable."
    }
  ],
  "ctaTitle": "Tu veux connecter Pennylane à tes outils",
  "ctaEm": "sans y passer des semaines ?",
  "ctaText": "On regarde ensemble tes flux actuels et on identifie ce qui peut tourner seul dès la semaine prochaine. Audit gratuit de 30 minutes, sans engagement.",
  "ctaSecondary": null
};

const AFF = {"make":"https://www.make.com/en/register?pc=boommaker","airtable":"https://airtable.com/invite/r/b7FpxImb","claude":"https://claude.ai/referral/JkRs2Ml5fA","emelia":"https://emelia.io/fr?_by=julia87"};
const affLink = (name) => AFF[String(name || '').toLowerCase().trim()] || null;

const PageNav = () => {
  const [open, setOpen] = useState(false);
  return (
    <>
      <nav className="nav" id="nav">
        <a href="/" className="nav-logo" aria-label="Boom Maker"><Logo /></a>
        <div className="nav-links">
          <div className="nav-dropdown">
            <button type="button" className="nav-dropdown-trigger" aria-haspopup="true">
              Expertises <span className="nav-dropdown-caret">▾</span>
            </button>
            <div className="nav-dropdown-menu" role="menu">
              <a href="/expertises">3 piliers</a>
              <a href="/cas-usage">Cas d'usage</a>
              <a href="/partners">Partenaires</a>
            </div>
          </div>
          <a href="/tarifs">Tarifs</a>
          <a href="/news">News</a>
          <div className="nav-dropdown">
            <button type="button" className="nav-dropdown-trigger" aria-haspopup="true">
              À propos <span className="nav-dropdown-caret">▾</span>
            </button>
            <div className="nav-dropdown-menu" role="menu">
              <a href="/a-propos">BoomMaker</a>
              <a href="/#faq">FAQ</a>
            </div>
          </div>
          <a href="/contact">Contact</a>
        </div>
        <ThemeToggle />
        <a href="/audit-gratuit" className="btn btn-glow nav-cta-desktop">Audit gratuit <ArrowUpRight /></a>
        <button className="nav-burger" aria-label="Menu" aria-expanded={open}
                onClick={() => setOpen((o) => !o)}>
          <span /><span /><span />
        </button>
      </nav>
      <div className={`nav-mobile ${open ? 'open' : ''}`} onClick={() => setOpen(false)}>
        <span className="nav-mobile-group">/ Expertises</span>
        <a href="/expertises">3 piliers</a>
        <a href="/cas-usage">Cas d'usage</a>
        <a href="/partners">Partenaires</a>
        <a href="/tarifs">Tarifs</a>
        <a href="/news">News</a>
        <span className="nav-mobile-group">/ À propos</span>
        <a href="/a-propos">BoomMaker</a>
        <a href="/#faq">FAQ</a>
        <a href="/contact">Contact</a>
        <a href="/audit-gratuit" className="btn btn-glow">Audit gratuit <ArrowUpRight /></a>
      </div>
    </>
  );
};

/* Rend un bloc de contenu selon son type. Wrapper commun = .expertises-cases
 * (eyebrow + titre), puis corps spécifique. */
const Block = ({ b }) => {
  const head = (
    <>
      {b.eyebrow ? (
        <div className="expertise-eyebrow eyebrow"><span className="pulse" />{b.eyebrow}</div>
      ) : null}
      {b.h2 ? (
        <h2 className="expertises-cases-title">{b.h2}{b.h2Em ? <> <em>{b.h2Em}</em></> : null}</h2>
      ) : null}
      {b.intro ? <p className="uc-intro">{b.intro}</p> : null}
    </>
  );

  let body = null;
  if (b.type === 'stats') {
    body = (
      <div className="uc-stats">
        {b.stats.map((s, i) => (
          <div className="uc-stat" key={i}>
            <div className="uc-stat-value">{s.value}</div>
            <span className="uc-stat-label">{s.label}</span>
          </div>
        ))}
      </div>
    );
  } else if (b.type === 'cards') {
    body = (
      <div className="uc-cards">
        {b.cards.map((card, i) => (
          <article className="uc-card" key={i}>
            {card.tag ? <div className="uc-card-tag">{card.tag}</div> : null}
            <h3 className="uc-card-title">{card.title}</h3>
            <p className="uc-card-body">{card.body}</p>
          </article>
        ))}
      </div>
    );
  } else if (b.type === 'steps') {
    body = (
      <ol className="uc-steps">
        {b.steps.map((s, i) => (
          <li className="uc-step" key={i}>
            <div className="uc-step-num">/ {String(i + 1).padStart(2, '0')}</div>
            <div className="uc-step-content">
              <h3>{s.title}</h3>
              <p>{s.body}</p>
            </div>
          </li>
        ))}
      </ol>
    );
  } else if (b.type === 'comparison') {
    body = (
      <div className="uc-table-wrap">
        <table className="uc-table">
          <thead>
            <tr>{b.columns.map((col, i) => <th key={i}>{col}</th>)}</tr>
          </thead>
          <tbody>
            {b.rows.map((row, ri) => (
              <tr key={ri}>
                {row.map((cell, ci) => {
                  if (ci !== 0) return <td key={ci}>{cell}</td>;
                  const href = affLink(cell);
                  return (
                    <th scope="row" key={ci}>
                      {href
                        ? <a href={href} target="_blank" rel="sponsored noopener">{cell}</a>
                        : cell}
                    </th>
                  );
                })}
              </tr>
            ))}
          </tbody>
        </table>
        {b.rows.some((r) => affLink(r[0])) ? (
          <p className="uc-aff-note">Certains liens sont affiliés : si tu passes par eux, Boom Maker peut toucher une commission, sans surcoût pour toi.</p>
        ) : null}
      </div>
    );
  } else if (b.type === 'cases') {
    body = (
      <div className="uc-cases">
        {b.cases.map((cs, i) => (
          <article className="uc-case" key={i}>
            <div className="uc-case-profile">{cs.profile}</div>
            {cs.context ? <p className="uc-case-context">{cs.context}</p> : null}
            {cs.result ? <p className="uc-case-result">{cs.result}</p> : null}
          </article>
        ))}
      </div>
    );
  } else if (b.type === 'checklist') {
    body = (
      <ul className="uc-checklist">
        {b.items.map((it, i) => (
          <li key={i}>
            <Check />
            <span>{it.strong ? <strong>{it.strong} </strong> : null}{it.text}</span>
          </li>
        ))}
      </ul>
    );
  } else if (b.type === 'callout') {
    body = (
      <div className="uc-callout">
        {b.label ? <span className="uc-callout-label">{b.label}</span> : null}
        <p>{b.text}</p>
      </div>
    );
  } else if (b.type === 'flow') {
    const kinds = { trigger: 'uc-flow-trigger', action: '', result: 'uc-flow-result' };
    body = (
      <>
        <div
          className="uc-flow"
          role="img"
          aria-label={b.nodes.map((n) => n.label).filter(Boolean).join(', puis ')}
        >
          {b.nodes.map((n, i) => (
            <React.Fragment key={i}>
              <div className={`uc-flow-node ${kinds[n.kind] || ''}`.trim()}>
                <span className="uc-flow-node-label">{n.label}</span>
                {n.sub ? <span className="uc-flow-node-sub">{n.sub}</span> : null}
              </div>
              {i < b.nodes.length - 1 ? (
                <span className="uc-flow-arrow" aria-hidden="true">→</span>
              ) : null}
            </React.Fragment>
          ))}
        </div>
        {b.note ? <p className="uc-flow-note">{b.note}</p> : null}
      </>
    );
  } else {
    body = b.paragraphs.map((p, i) => (
      <p className="expertises-cases-lead" key={i}>{p}</p>
    ));
  }

  return <section className="expertises-cases">{head}{body}</section>;
};

const PageContent = () => {
  useReveal();
  return (
    <div className="usecase-page tarifs-page">
      <PageNav />

      <article className="audit-hero">
        <div className="container">
          <nav className="expertises-breadcrumb" aria-label="Fil d'Ariane">
            <a href="/">Accueil</a>
            <span className="expertises-breadcrumb-sep" aria-hidden="true">/</span>
            <a href="/cas-usage">Cas d'usage</a>
            <span className="expertises-breadcrumb-sep" aria-hidden="true">/</span>
            <span aria-current="page">{C.breadcrumb}</span>
          </nav>
          <span className="eyebrow"><span className="pulse" /> {C.eyebrow}</span>
          <h1>{C.h1}{C.h1Em ? <> <em>{C.h1Em}</em></> : null}</h1>
          <p className="lead">{C.lead}</p>
        </div>
      </article>

      <section className="expertises-content tarifs-content">
        <div className="container">
          <div className="expertises-main">
            {C.blocks.map((b, bi) => <Block b={b} key={bi} />)}

            {C.faq.length ? (
              <section className="expertises-faq" id="faq" aria-labelledby="faq-title">
                <div className="expertise-eyebrow eyebrow"><span className="pulse" />Questions fréquentes</div>
                <h2 className="expertises-faq-title" id="faq-title">Ce qu'on nous demande <em>le plus souvent.</em></h2>
                <div className="expertises-faq-list">
                  {C.faq.map((item, i) => (
                    <details className="expertises-faq-item" key={i}>
                      <summary>
                        <span>{item.q}</span>
                        <span className="expertises-faq-caret" aria-hidden="true">+</span>
                      </summary>
                      <p>{item.a}</p>
                    </details>
                  ))}
                </div>
              </section>
            ) : null}
          </div>
        </div>
      </section>

      <section className="partners-content partners-content-minimal">
        <div className="container">
          <div className="partners-cta-final">
            <h2>{C.ctaTitle}{C.ctaEm ? <> <em>{C.ctaEm}</em></> : null}</h2>
            <p>{C.ctaText}</p>
            <div className="partners-cta">
              <a href="/audit-gratuit" className="btn btn-glow">Réserver l'audit gratuit <ArrowUpRight /></a>
              {C.ctaSecondary ? (
                <a href={C.ctaSecondary.href} className="btn btn-ghost">{C.ctaSecondary.label} <ArrowUpRight /></a>
              ) : (
                <a href="/cas-usage" className="btn btn-ghost">Voir tous les cas d'usage <ArrowUpRight /></a>
              )}
            </div>
          </div>
        </div>
      </section>

      <FooterMin />
    </div>
  );
};

ReactDOM.createRoot(document.getElementById('root')).render(<PageContent />);
