88 lines
2.8 KiB
TypeScript
88 lines
2.8 KiB
TypeScript
"use client";
|
|
|
|
import { useRef, useState } from "react";
|
|
import { LandingHero } from "./landing/LandingHero";
|
|
import { AssetStats } from "./landing/AssetStats";
|
|
import { TopicEbookShowcase } from "./landing/TopicEbookShowcase";
|
|
import { CompareSection } from "./landing/CompareSection";
|
|
import { CommunityPreview } from "./landing/CommunityPreview";
|
|
import { FAQSection } from "./landing/FAQSection";
|
|
import { LandingCTA } from "./landing/LandingCTA";
|
|
import { LoginModal } from "./landing/LoginModal";
|
|
import { PromoProofModal } from "./landing/PromoProofModal";
|
|
import styles from "./vip.module.css";
|
|
|
|
type LandingPageProps = {
|
|
onJoin: () => void;
|
|
onVerify: (userId: string) => Promise<boolean>;
|
|
onVerifyByEmail?: (
|
|
email: string,
|
|
password: string,
|
|
user_id?: string
|
|
) => Promise<boolean | { ok: boolean; error?: string }>;
|
|
onVerifySuccess: () => void;
|
|
};
|
|
|
|
export function LandingPage({
|
|
onJoin,
|
|
onVerify,
|
|
onVerifyByEmail,
|
|
onVerifySuccess,
|
|
}: LandingPageProps) {
|
|
const [loginModalOpen, setLoginModalOpen] = useState(false);
|
|
const [promoModalOpen, setPromoModalOpen] = useState(false);
|
|
const [payTestMode, setPayTestMode] = useState(() => {
|
|
if (typeof window === "undefined") return false;
|
|
return localStorage.getItem("vipPayTestMode") === "1";
|
|
});
|
|
const titleTapCountRef = useRef(0);
|
|
|
|
const handleHeroTitleTap = () => {
|
|
titleTapCountRef.current += 1;
|
|
if (titleTapCountRef.current < 10) return;
|
|
titleTapCountRef.current = 0;
|
|
const nextMode = !payTestMode;
|
|
setPayTestMode(nextMode);
|
|
if (typeof window !== "undefined") {
|
|
localStorage.setItem("vipPayTestMode", nextMode ? "1" : "0");
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<div className={styles.landingScene}>
|
|
<div className={styles.landingSceneBg} aria-hidden>
|
|
<div className={styles.landingOrb} />
|
|
<div className={styles.landingOrb} />
|
|
<div className={styles.landingOrb} />
|
|
<div className={styles.landingMesh} />
|
|
<div className={styles.landingNoise} />
|
|
</div>
|
|
<div className={styles.landingSceneInner}>
|
|
<LandingHero onTitleTap={handleHeroTitleTap} />
|
|
<AssetStats />
|
|
<TopicEbookShowcase onLockedClick={() => setLoginModalOpen(true)} />
|
|
<CompareSection />
|
|
<div className="hidden" aria-hidden>
|
|
<CommunityPreview />
|
|
</div>
|
|
<FAQSection />
|
|
<LandingCTA
|
|
onJoin={onJoin}
|
|
onLogin={() => setLoginModalOpen(true)}
|
|
payTestMode={payTestMode}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<LoginModal
|
|
open={loginModalOpen}
|
|
onClose={() => setLoginModalOpen(false)}
|
|
onVerify={onVerify}
|
|
onVerifyByEmail={onVerifyByEmail}
|
|
onSuccess={onVerifySuccess}
|
|
/>
|
|
<PromoProofModal open={promoModalOpen} onClose={() => setPromoModalOpen(false)} />
|
|
</>
|
|
);
|
|
}
|