137 lines
5.1 KiB
TypeScript
137 lines
5.1 KiB
TypeScript
"use client";
|
|
import { useEffect, useState } from "react";
|
|
|
|
const SLIDES = [
|
|
{
|
|
title: "Verify every product with one scan",
|
|
body: "Consumers scan your QR code and instantly see authenticity, batch details, and compliance — no app, no login.",
|
|
art: <ScanArt />,
|
|
},
|
|
{
|
|
title: "Personalize your QR codes",
|
|
body: "Customize color, dot shape, frame, and style — even add your brand logo — with a live preview.",
|
|
art: <CustomizeArt />,
|
|
},
|
|
{
|
|
title: "Download your custom QR codes",
|
|
body: "Save your QR codes in PNG, SVG, and PDF, then print and share them wherever you want.",
|
|
art: <DownloadArt />,
|
|
},
|
|
];
|
|
|
|
export default function AuthCarousel() {
|
|
const [i, setI] = useState(0);
|
|
useEffect(() => {
|
|
const t = setInterval(() => setI((x) => (x + 1) % SLIDES.length), 5000);
|
|
return () => clearInterval(t);
|
|
}, []);
|
|
const s = SLIDES[i];
|
|
return (
|
|
<div className="hidden lg:flex flex-col justify-center items-center text-white p-12 relative overflow-hidden"
|
|
style={{ background: "linear-gradient(160deg,#3b82f6,#2563eb)" }}>
|
|
<div key={i} className="w-full max-w-md animate-[fadein_.5s_ease]">
|
|
<div className="mb-8">{s.art}</div>
|
|
<h2 className="text-3xl font-extrabold text-center leading-tight">{s.title}</h2>
|
|
<p className="text-white/85 text-center mt-4">{s.body}</p>
|
|
</div>
|
|
<div className="flex gap-2 mt-10">
|
|
{SLIDES.map((_, k) => (
|
|
<button key={k} onClick={() => setI(k)} aria-label={`Slide ${k + 1}`}
|
|
className={`h-2.5 rounded-full transition-all ${k === i ? "w-6 bg-white" : "w-2.5 bg-white/40"}`} />
|
|
))}
|
|
</div>
|
|
<style>{`@keyframes fadein{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}`}</style>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
/* ---------- illustrations (inline SVG) ---------- */
|
|
|
|
function Frame({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<div className="mx-auto w-full max-w-sm rounded-2xl bg-white/10 border border-white/25 p-6 backdrop-blur">
|
|
{children}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function QrGlyph({ size = 96 }: { size?: number }) {
|
|
// deterministic pseudo-random QR-looking grid
|
|
const cells = Array.from({ length: 49 }, (_, k) => (k * 7 + (k % 5) * 3) % 3 === 0);
|
|
return (
|
|
<div className="rounded-xl bg-white p-2" style={{ width: size, height: size }}>
|
|
<div className="grid grid-cols-7 grid-rows-7 gap-[2px] h-full w-full">
|
|
{cells.map((on, k) => <div key={k} className={on ? "bg-slate-900 rounded-[1px]" : ""} />)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function ScanArt() {
|
|
return (
|
|
<Frame>
|
|
<div className="flex items-center justify-between">
|
|
<div className="rounded-lg bg-white/90 px-3 py-2 text-slate-800 text-sm font-bold flex items-center gap-2">
|
|
<span className="text-blue-500">▦</span> 25
|
|
</div>
|
|
<div className="border-2 border-dashed border-white/60 rounded-2xl p-2">
|
|
<QrGlyph size={96} />
|
|
</div>
|
|
<div className="rounded-lg bg-white/90 px-3 py-2 text-slate-800 text-sm font-bold">134</div>
|
|
</div>
|
|
<div className="mt-5 flex justify-center gap-2">
|
|
{["Genuine", "Batch", "Verified"].map((t) => (
|
|
<span key={t} className="text-[10px] font-semibold bg-white/20 rounded-full px-2 py-1">{t}</span>
|
|
))}
|
|
</div>
|
|
</Frame>
|
|
);
|
|
}
|
|
|
|
function CustomizeArt() {
|
|
return (
|
|
<Frame>
|
|
<div className="flex items-center justify-center gap-4">
|
|
<div className="space-y-2">
|
|
{["#0b1f4d", "#f97316", "#2563eb"].map((c) => (
|
|
<div key={c} className="rounded-lg bg-white p-1.5">
|
|
<div className="grid grid-cols-5 grid-rows-5 gap-[1px] h-9 w-9">
|
|
{Array.from({ length: 25 }, (_, k) => (
|
|
<div key={k} style={{ background: (k * 3) % 3 === 0 ? c : "transparent" }} className="rounded-[1px]" />
|
|
))}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
<div className="border-2 border-dashed border-white/60 rounded-2xl p-2">
|
|
<QrGlyph size={92} />
|
|
<div className="mt-1 bg-slate-900 text-white text-[10px] font-bold text-center rounded py-1">SCAN ME</div>
|
|
</div>
|
|
<div className="rounded-xl bg-white p-2 grid grid-cols-2 gap-1.5">
|
|
{["#c7d2fe", "#fde68a", "#bfdbfe", "#fed7aa"].map((c) => (
|
|
<div key={c} className="h-6 w-6 rounded" style={{ background: c }} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div className="mt-4 flex justify-center">
|
|
<span className="bg-amber-100 text-amber-800 text-[11px] font-bold rounded-full px-3 py-1">CUSTOMIZE</span>
|
|
</div>
|
|
</Frame>
|
|
);
|
|
}
|
|
|
|
function DownloadArt() {
|
|
return (
|
|
<Frame>
|
|
<div className="flex justify-center">
|
|
<div className="border-2 border-dashed border-white/60 rounded-2xl p-2"><QrGlyph size={92} /></div>
|
|
</div>
|
|
<div className="mt-5 grid grid-cols-3 gap-2">
|
|
{["PNG", "JPG", "SVG", "PRINT", "PDF", "EPS"].map((f) => (
|
|
<div key={f} className="rounded-lg bg-white text-slate-700 text-[11px] font-bold text-center py-2 shadow-sm">{f}</div>
|
|
))}
|
|
</div>
|
|
</Frame>
|
|
);
|
|
}
|