feat(web): add credibility strip to subscription page

The page had no credibility signal at the point of conversion. Added a
CredibilityStrip under the header (shown only to converting users:
no-sub / trial / expired / pending) surfacing real, verifiable product
facts — 50+ marka, 1M+ parça, OEM + alternatif kodlar, saniyede sonuç,
KVKK uyumlu · SSL. Deliberately no fabricated customer counts or
testimonials.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-25 15:27:43 +03:00
parent daaf616335
commit 2912dc6eb2
4 changed files with 77 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
/**
* Tests for the CredibilityStrip shown to converting users (no-sub / trial /
* expired / pending). It surfaces only real, verifiable product facts — data
* scale, speed and security — NOT fabricated customer counts or testimonials.
*/
import { render } from "@testing-library/react";
import { vi } from "vitest";
vi.mock("@/lib/i18n", () => ({
useTranslation: () => ({
t: (key: string) => key,
locale: "tr",
setLocale: vi.fn(),
}),
}));
import { CredibilityStrip } from "@/routes/dashboard/subscription/index";
describe("CredibilityStrip", () => {
test("renders all five product-fact items", () => {
const { container } = render(<CredibilityStrip />);
const text = container.textContent ?? "";
for (const key of ["brands", "parts", "oem", "speed", "security"]) {
expect(text).toContain(`subscription.credibility.${key}`);
}
});
test("each item pairs an icon (svg) with its label", () => {
const { container } = render(<CredibilityStrip />);
const svgs = container.querySelectorAll("svg");
expect(svgs.length).toBe(5);
});
});

View File

@@ -30,18 +30,22 @@ import { createFileRoute, useNavigate } from "@tanstack/react-router";
import {
AlertTriangle,
ArrowRight,
Boxes,
Check,
CheckCircle2,
Clock,
CreditCard,
Crown,
Hash,
Info,
Layers,
Loader2,
Minus,
Pencil,
ShieldCheck,
Sparkles,
X,
Zap,
} from "lucide-react";
import { Suspense, lazy, useEffect, useMemo, useRef, useState } from "react";
@@ -550,6 +554,8 @@ export function SubscriptionPage() {
<p className="text-sm text-muted-foreground">{t("subscription.subtitle")}</p>
</header>
{showStepper && <CredibilityStrip />}
{subscription && hasActiveSub && (
<ActiveSubscriptionCard
subscription={subscription}
@@ -941,6 +947,29 @@ function StepCard({
);
}
export function CredibilityStrip() {
const { t } = useTranslation();
const items = [
{ icon: Layers, key: "brands" },
{ icon: Boxes, key: "parts" },
{ icon: Hash, key: "oem" },
{ icon: Zap, key: "speed" },
{ icon: ShieldCheck, key: "security" },
] as const;
return (
<div className="grid grid-cols-2 gap-x-4 gap-y-3 rounded-2xl border border-border bg-muted/20 px-5 py-4 sm:grid-cols-3 lg:grid-cols-5">
{items.map(({ icon: Icon, key }) => (
<div key={key} className="flex items-center gap-2 text-sm">
<Icon className="h-4 w-4 shrink-0 text-primary" />
<span className="font-medium leading-5 text-foreground/85">
{t(`subscription.credibility.${key}`)}
</span>
</div>
))}
</div>
);
}
export function PlanHelperHint() {
const { t } = useTranslation();
return (