Locale provider (en default, persisted) + EN/SV switcher in header; converted header + landing sections + catalog/sources/order-flow/most-of-portal to useT({en,sv}). Fixed two partial conversions (forskott TRUST object/tuple map; kallor undefined ALL + raw object renders). tsc 0, build green. Remaining: admin/* + a few partials.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
63 lines
3.1 KiB
TypeScript
63 lines
3.1 KiB
TypeScript
"use client";
|
|
|
|
import { useReveal } from "@/hooks/use-reveal";
|
|
import { useT } from "@/components/locale-provider";
|
|
|
|
const NUMBERS: [string, { en: string; sv: string }, boolean][] = [
|
|
["94%", { en: "Average confidence", sv: "Snittkonfidens" }, true],
|
|
["50/50", { en: "Start. Approved.", sv: "Start. Godkänt." }, false],
|
|
["<4d", { en: "Delivery", sv: "Leverans" }, false],
|
|
];
|
|
|
|
export function TestimonialsSection() {
|
|
const t = useT();
|
|
const ref = useReveal<HTMLElement>();
|
|
return (
|
|
<section ref={ref} className="relative border-b border-border bg-background">
|
|
<div className="mx-auto max-w-[80rem] px-6 py-32 lg:py-44">
|
|
<div className="flex items-baseline justify-between border-b border-border pb-6">
|
|
<p className="reveal font-mono text-[11px] uppercase tracking-[0.18em] text-muted-foreground">{t({ en: "05 — Proof", sv: "05 — Bevis" })}</p>
|
|
<p className="reveal delay-1 font-mono text-[11px] uppercase tracking-[0.18em] text-muted-foreground">{t({ en: "Measurable", sv: "Mätbart" })}</p>
|
|
</div>
|
|
|
|
<h2 className="reveal delay-1 mt-10 max-w-3xl text-[clamp(2.4rem,6vw,4.5rem)] font-medium leading-[0.98] tracking-[-0.03em]">
|
|
{t({ en: "Numbers.", sv: "Siffror." })}
|
|
<br />
|
|
{t({ en: "Not promises.", sv: "Inte löften." })}
|
|
</h2>
|
|
|
|
<div className="mt-20 grid grid-cols-1 border-t border-border sm:grid-cols-3">
|
|
{NUMBERS.map(([n, l, red], i) => (
|
|
<div
|
|
key={l.sv}
|
|
className={`reveal delay-${i + 2} group relative border-b border-border py-12 sm:border-b-0 sm:border-l sm:py-0 sm:pl-8 sm:pr-4 ${i === 0 ? "sm:border-l-0 sm:pl-0" : ""}`}
|
|
>
|
|
<p className="font-mono text-[11px] tabular-nums text-muted-foreground/60">0{i + 1}</p>
|
|
<p
|
|
className="mt-3 text-[clamp(3.2rem,8vw,6rem)] font-semibold leading-[0.9] tracking-[-0.04em] transition-transform duration-300 group-hover:-translate-y-0.5"
|
|
style={{ color: red ? "var(--accent-red)" : "var(--foreground)" }}
|
|
>
|
|
{n}
|
|
</p>
|
|
<p className="mt-4 font-mono text-[11px] uppercase tracking-[0.14em] text-muted-foreground">{t(l)}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<figure className="reveal-scale delay-5 mt-24 max-w-3xl border-t border-border pt-10">
|
|
<blockquote className="text-[clamp(1.5rem,3.2vw,2.25rem)] font-medium leading-[1.15] tracking-[-0.02em]">
|
|
{t({
|
|
en: "“We trust the list before we dial. The per-contact provenance is what sealed it.”",
|
|
sv: "“Vi litar på listan innan vi ringer. Härkomsten per kontakt avgjorde.”",
|
|
})}
|
|
</blockquote>
|
|
<figcaption className="mt-8 flex items-center gap-3 font-mono text-[11px] uppercase tracking-[0.16em] text-muted-foreground">
|
|
<span aria-hidden className="inline-block h-1.5 w-1.5" style={{ background: "var(--prov-0)" }} />
|
|
RevOps · B2B SaaS
|
|
</figcaption>
|
|
</figure>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|