Files

197 lines
7.2 KiB
TypeScript

'use client'
import React, { useEffect, useRef, useState } from 'react'
import { useAccount } from '@hanzo/app/lib/account'
import { ReferralHero } from '@/components/referrals/ReferralHero'
import ReferralLink from '@/components/referrals/ReferralLink'
import ReferralStatsComponent from '@/components/referrals/ReferralStats'
import ReferralHistory from '@/components/referrals/ReferralHistory'
import { RewardTiers } from '@/components/referrals/RewardTiers'
import { HowItWorks } from '@/components/referrals/HowItWorks'
import { CreatorStudio } from '@/components/referrals/CreatorStudio'
import { SubmitPost } from '@/components/referrals/SubmitPost'
import { ReferralFaq } from '@/components/referrals/ReferralFaq'
import { ReferralRecord, ReferralStats as ReferralStatsType } from '@/components/referrals/types'
import { mine } from '@/lib/hanzo/referrals'
import { Box, Button, Pulse, Text, View, XStack, YStack } from '@hanzo/ui'
import { Action } from '@hanzo/ui/marketing'
import { ArrowRight } from 'lucide-react'
import { useI18n } from '@hanzo/i18n/react'
export default function ReferralProgram() {
const { t } = useI18n()
const { user } = useAccount()
const [referralCode, setReferralCode] = useState<string>('')
const [referralLink, setReferralLink] = useState<string>('')
const [stats, setStats] = useState<ReferralStatsType>({
signedUp: 0,
qualified: 0,
pending: 0,
})
const [history, setHistory] = useState<ReferralRecord[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const dashboardRef = useRef<HTMLDivElement>(null)
useEffect(() => {
if (!user?.id) {
setLoading(false)
return
}
// ONE read: the org's code, the link the service mints for it, and the orgs
// that signed up with it (lib/hanzo/referrals.ts).
async function loadReferralData() {
try {
setLoading(true)
setError(null)
const got = await mine()
setReferralCode(got.code)
setReferralLink(got.link)
setStats({
signedUp: got.counts.total,
qualified: got.counts.qualified,
pending: got.counts.signup,
})
setHistory(
got.referrals.map((r) => ({
id: r.id,
name: r.referee,
status: r.status === 'qualified' ? 'Using Hanzo' : 'Not yet active',
date: r.createdAt ? new Date(r.createdAt * 1000).toLocaleDateString() : '',
})),
)
} catch (err) {
setError(err instanceof Error ? err.message : 'Your referral link could not be loaded right now.')
} finally {
setLoading(false)
}
}
void loadReferralData()
}, [user?.id])
const scrollToDashboard = () => {
if (dashboardRef.current) {
dashboardRef.current.scrollIntoView({ behavior: 'smooth' })
}
}
const isLoggedIn = Boolean(user?.id && referralCode)
const effectiveCode = isLoggedIn ? referralCode : ''
const effectiveLink = isLoggedIn ? referralLink || `https://hanzo.ai/?ref=${referralCode}` : ''
return (
<YStack px="$4" py="$8" $sm={{ px: '$8', py: '$12' }}>
<YStack width="100%" maxW={1040} mx="auto" gap={48}>
{/* Section 01: Hero (One clear message, 3 benefits, single CTA) */}
<ReferralHero
isAuthenticated={isLoggedIn}
referralLink={effectiveLink}
onGetLinkClick={scrollToDashboard}
/>
{error && (
<Box
p={16}
borderWidth={1}
borderColor="var(--destructive)"
rounded="var(--radius-lg)"
bg="var(--panel, rgba(255, 255, 255, 0.03))"
>
<Text display="block" fontSize="$2" lineHeight="1.1607rem" color="var(--state-error-text)">
{error}
</Text>
</Box>
)}
{loading && user?.id ? (
<YStack gap={24}>
{[1, 2].map((i) => (
<Pulse
key={i}
p={24}
borderWidth={1}
borderColor="var(--neutral-800)"
rounded="var(--radius-lg)"
bg="var(--panel, rgba(255, 255, 255, 0.03))"
>
<Box height={16} width="33.333333%" mb={16} rounded="var(--radius-sm)" bg="var(--neutral-800)" />
<Box height={32} width="100%" rounded="var(--radius-sm)" bg="var(--neutral-800)" />
</Pulse>
))}
</YStack>
) : null}
{/* Live Creator Link & Stats strictly when authenticated, or Sign-In Gate when unauthenticated */}
{isLoggedIn ? (
<div ref={dashboardRef}>
<YStack gap={24}>
<ReferralLink referralLink={effectiveLink} referralCode={effectiveCode} />
<ReferralStatsComponent referralStats={stats} />
{history.length > 0 && <ReferralHistory referralHistory={history} />}
</YStack>
</div>
) : !loading ? (
<div ref={dashboardRef}>
<YStack
p={28}
$sm={{ p: 36 }}
rounded="var(--radius-lg)"
borderWidth={1}
borderColor="var(--border)"
bg="var(--panel, rgba(255, 255, 255, 0.03))"
gap={20}
>
<XStack items="center" justify="space-between" flexWrap="wrap" gap={16}>
<YStack gap={4} maxW={600}>
<Text fontSize="$5" fontWeight="600" color="var(--foreground)">
{t('Sign in to access your Referral Link & Dashboard')}
</Text>
<Text fontSize="$2" color="var(--muted-foreground)">
{t('Referral links and custom vanity codes require a signed-in Hanzo account so referrals and 10% token rewards are credited to your organization.')}
</Text>
</YStack>
<XStack gap={10} items="center">
<Action render="a" href="/login?next=/referral" fill>
{t('Sign In')}
<ArrowRight size={14} aria-hidden />
</Action>
<Action render="a" href="/signup?next=/referral">
{t('Create Account')}
</Action>
</XStack>
</XStack>
</YStack>
</div>
) : null}
{/* Section 02: Three Reward Cards (Bronze $25, Silver $100, Gold $500) */}
<RewardTiers />
{/* Section 03: How It Works (01, 02, 03) */}
<HowItWorks />
{/* Section 04 & 05: Creator Studio & Submit a Post (strictly for logged-in accounts with a real referral link) */}
{isLoggedIn ? (
<>
<CreatorStudio referralLink={effectiveLink} />
<SubmitPost referralLink={effectiveLink} />
</>
) : null}
<ReferralFaq />
{/* Compact Footer Note */}
<Box pt={16} borderTopWidth={1} borderColor="var(--border)" items="center">
<Text fontSize="$1" color="var(--muted-foreground)" style={{ textAlign: 'center' }}>
{t('Official Hanzo AI Creator & Referral Program ยท All submissions reviewed by engineering operations.')}
</Text>
</Box>
</YStack>
</YStack>
)
}