SPB Git

spb/groupe-ka Public

Groupe KA — site du holding + KA ID (compte unique & SSO des 7 plateformes). Next.js 16, SQLite, Google & Apple login.

TypeScript 89.7% CSS 5.8% HTML 4.4%
5.0 KB · 128 lines tsx
Raw Blame History
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// Carte de membre IMPRIMABLE au format carte bancaire (CR80 : 85,6 × 54 mm),3// recto (identité) / verso (QR + zone NFC). À imprimer à l'échelle 100 %,4// avec les arrière-plans activés, puis coller un autocollant NFC (NTAG215)5// au dos, programmé avec l'URL d'identification du membre.6import type { Metadata } from "next";7import { redirect } from "next/navigation";8import QRCode from "qrcode";9import { getSessionUser } from "@/lib/auth";10import { ensureKaId } from "@/lib/db";11import { roleCard } from "@/lib/roles";12import PrintButton from "./PrintButton";1314export const metadata: Metadata = {15  title: "Carte imprimable | Groupe KA",16  robots: { index: false },17};1819export const dynamic = "force-dynamic";2021function fmtDate(iso: string | null): string {22  if (!iso) return "";23  const d = new Date(iso.includes("T") ? iso : iso.replace(" ", "T") + "Z");24  if (Number.isNaN(d.getTime())) return "";25  return d.toLocaleDateString("fr-CA", { month: "2-digit", year: "numeric" });26}2728export default async function CarteImprimable() {29  const user = await getSessionUser();30  if (!user) redirect("/connexion?next=%2Fcompte%2Fcarte");31  const kaId = user.kaId ?? ensureKaId(user.id);32  const url = `https://www.groupe-ka.com/m/${kaId}`;33  const qr = await QRCode.toDataURL(url, {34    margin: 0,35    width: 400,36    color: { dark: "#141814", light: "#ffffff" },37  });3839  return (40    <main className="print-page mx-auto max-w-2xl px-4 pb-16 sm:px-6">41      <section className="no-print pt-10">42        <p className="kicker">Carte physique · à imprimer</p>43        <h1 className="gk-display mt-3 text-[clamp(24px,4.5vw,36px)] leading-[1.02] font-bold tracking-[-0.03em] uppercase">44          Votre carte, <span className="hl">en vrai</span>45        </h1>46        <p className="mt-3 max-w-lg text-[13.5px] text-ink-2">47          Format carte bancaire (85,6 × 54 mm). Imprimez à l&apos;échelle48          100 % avec les arrière-plans activés, découpez le long des repères,49          et collez un autocollant NFC au dos (zone indiquée).50        </p>51        <div className="mt-5 flex flex-wrap gap-3">52          <PrintButton />53          <a href="/compte" className="btn btn-ghost">54            ← Mon compte55          </a>56        </div>57      </section>5859      <div className="print-cards mt-8 flex flex-col items-center gap-8">60        {/* ---------- RECTO ---------- */}61        <div className="pcard pcard-front">62          <div className="pcard-watermark" aria-hidden="true">63            KA64          </div>65          <div className="pcard-head">66            <span className="pcard-brand">67              Groupe <span className="pcard-ka">KA</span>68            </span>69            <span className="pcard-label">CARTE DE MEMBRE</span>70          </div>71          <div className="pcard-id">72            <span className="pcard-id-label">KA-ID</span>73            <span className="pcard-id-value">{kaId}</span>74          </div>75          <div className="pcard-foot">76            <div className="pcard-holder">77              <span className="pcard-name">{user.name || user.email}</span>78              {roleCard(user.role) && (79                <span className="pcard-role">{roleCard(user.role)}</span>80              )}81              <span className="pcard-since">82                MEMBRE DEPUIS {fmtDate(user.createdAt)}83              </span>84            </div>85            {user.avatarUrl ? (86              // eslint-disable-next-line @next/next/no-img-element87              <img className="pcard-avatar" src={user.avatarUrl} alt="" />88            ) : (89              <span className="pcard-avatar pcard-avatar-empty">90                {(user.name || user.email).charAt(0).toUpperCase()}91              </span>92            )}93          </div>94        </div>9596        {/* ---------- VERSO ---------- */}97        <div className="pcard pcard-back">98          <div className="pcard-back-left">99            {/* eslint-disable-next-line @next/next/no-img-element */}100            <img className="pcard-qr" src={qr} alt={`Code QR — ${url}`} />101          </div>102          <div className="pcard-back-right">103            <p className="pcard-back-title">104              Tapez la carte (NFC)105              <br />106              ou scannez le code107            </p>108            <p className="pcard-back-url">groupe-ka.com/m/{kaId.slice(3)}</p>109            <div className="pcard-nfc" aria-hidden="true">110              <span className="pcard-nfc-ico">)))</span> zone NFC — coller la111              puce ici112            </div>113            <p className="pcard-back-foot">114              Identité vérifiable en ligne · Lou·Ka — Immo·Ka — Vrai-Prix —115              ValoPlex — Auto·Ka — Fabri·Ka — Food·Ka116            </p>117          </div>118        </div>119      </div>120121      <p className="no-print gk-mono mt-8 text-[11px] text-ink-3">122        Astuce : imprimez sur du papier cartonné (200 g+) ou plastifiez.123        L&apos;autocollant NFC se colle au dos, dans la zone « NFC ».124      </p>125    </main>126  );127}128