50 lines
2.0 KiB
TypeScript
50 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { useEffect, useMemo, useState } from "react";
|
|
import { useTrack } from "@/hooks/use-track";
|
|
import { TRACKING_EVENTS } from "@/lib/tracking-events";
|
|
import { useDeveloperFlags } from "@/components/developer-flags-provider";
|
|
|
|
const variants = [
|
|
{ id: "A", title: "限时解锁活动", desc: "关注公众号回复“下载”,领取高级线路和社群资格。", cta: "去解锁", href: "/unlock" },
|
|
{ id: "B", title: "VIP 试用开放", desc: "试用会员权益:高速源、历史版本包、优先更新提醒。", cta: "查看会员", href: "/pricing" },
|
|
] as const;
|
|
|
|
export function HomeABBanner() {
|
|
const { track } = useTrack();
|
|
const { flags } = useDeveloperFlags();
|
|
const [variantId] = useState<"A" | "B">(() => {
|
|
if (typeof window === "undefined") return "A";
|
|
const key = "download_nova_ab_home";
|
|
const cached = localStorage.getItem(key) as "A" | "B" | null;
|
|
const picked = cached ?? (Math.random() > 0.5 ? "A" : "B");
|
|
localStorage.setItem(key, picked);
|
|
return picked;
|
|
});
|
|
const variant = useMemo(() => variants.find((v) => v.id === variantId) ?? variants[0], [variantId]);
|
|
|
|
useEffect(() => {
|
|
if (!flags.abBanner) return;
|
|
track(TRACKING_EVENTS.abExpose, { placement: "home_banner", variant: variantId });
|
|
}, [track, variantId, flags.abBanner]);
|
|
|
|
if (!flags.abBanner) return null;
|
|
|
|
return (
|
|
<section className="card-glass relative overflow-hidden">
|
|
<div className="absolute -right-8 -top-8 h-28 w-28 rounded-full bg-violet-300/20 blur-3xl" />
|
|
<p className="text-xs text-violet-300">A/B Banner · Variant {variant.id}</p>
|
|
<h3 className="mt-1 text-2xl font-semibold">{variant.title}</h3>
|
|
<p className="mt-2 max-w-2xl text-sm text-slate-300">{variant.desc}</p>
|
|
<Link
|
|
href={variant.href}
|
|
onClick={() => track(TRACKING_EVENTS.abClick, { placement: "home_banner", variant: variant.id })}
|
|
className="cta-main mt-4 inline-flex"
|
|
>
|
|
{variant.cta}
|
|
</Link>
|
|
</section>
|
|
);
|
|
}
|