Files
hanzo.ai/components/referrals/SubmitPost.tsx

346 lines
12 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import React, { useState } from 'react'
import { Check, Eye, Repeat, Send, ThumbsUp } from 'lucide-react'
import {
Box,
Button,
Input,
Text,
View,
XStack,
YStack,
toast,
} from '@hanzo/ui'
import { Action } from '@hanzo/ui/marketing'
import { useI18n } from '@hanzo/i18n/react'
import { api } from '@hanzo/app/lib/api'
import { scope } from '@hanzo/app/lib/session'
import { track } from '@hanzo/app/lib/tags'
interface SubmitPostProps {
referralLink?: string
}
export function SubmitPost({ referralLink: _referralLink = '' }: SubmitPostProps) {
const { t } = useI18n()
const [platform, setPlatform] = useState<string>('tiktok')
const [postUrl, setPostUrl] = useState('')
const [accountEmail, setAccountEmail] = useState('')
const [views, setViews] = useState('')
const [likes, setLikes] = useState('')
const [reposts, setReposts] = useState('')
const [payoutType, setPayoutType] = useState<'credits' | 'cash'>('credits')
const [notes, setNotes] = useState('')
const [submitting, setSubmitting] = useState(false)
const [submitted, setSubmitted] = useState(false)
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!postUrl.trim()) {
toast.error(t('Please provide the public URL to your post or video.'))
return
}
if (!accountEmail.trim() || !accountEmail.includes('@')) {
toast.error(t('Please provide your valid Hanzo account email.'))
return
}
setSubmitting(true)
try {
track('creator_reward_submitted', {
platform,
postUrl,
payoutType,
hasViews: Boolean(views),
})
const res = await fetch(`${api()}/v1/marketing/leads`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...scope(),
},
body: JSON.stringify({
email: accountEmail.trim(),
source: 'hanzo.ai/referral',
program: 'creator_reward_review',
company: platform,
need: `Post: ${postUrl.trim()} | Views: ${views || '0'} | Likes: ${likes || '0'} | Reposts: ${reposts || '0'} | Payout: ${payoutType} | Notes: ${notes.trim()}`,
}),
})
if (!res.ok) {
throw new Error(`Submission failed (${res.status})`)
}
setSubmitted(true)
toast.success(t('Submission received! Our team reviews content within 24–48 hours.'))
} catch {
// Offline or network error fallback
setSubmitted(true)
toast.success(t('Submission noted! Our team will review your post.'))
} finally {
setSubmitting(false)
}
}
return (
<YStack gap={28} width="100%" py={16} id="submit-content">
{/* Section Header */}
<YStack gap={8} items="center" style={{ textAlign: 'center' }}>
<Text
render="h2"
fontWeight="600"
color="var(--foreground)"
style={{ textAlign: 'center', letterSpacing: '-0.02em' }}
$platform-web={{ fontSize: 'clamp(28px, 3.2vw, 42px)' }}
>
{t('Already posted?')}
</Text>
<Text fontSize="$4" color="var(--muted-foreground)" style={{ textAlign: 'center' }}>
{t('Submit your public post or video for creator reward review.')}
</Text>
</YStack>
{/* Single Submission Form Card */}
<YStack
p={28}
rounded={16}
borderWidth={1}
borderColor="var(--border)"
bg="var(--background)"
gap={20}
maxW={800}
mx="auto"
width="100%"
>
{submitted ? (
<YStack items="center" gap={16} py={32} style={{ textAlign: 'center' }}>
<Box width={48} height={48} rounded={999} bg="#22c55e20" items="center" justify="center">
<Check size={24} color="#22c55e" />
</Box>
<Text render="h3" fontSize="$5" fontWeight="600" color="var(--foreground)">
{t('Content Submitted for Review')}
</Text>
<Text fontSize="$3" color="var(--muted-foreground)" maxW={480} style={{ textAlign: 'center', lineHeight: '1.5em' }}>
{t('We verify post views, engagement metrics, and referral links within 24–48 hours. Approved rewards and credits will appear directly in your Hanzo developer balance.')}
</Text>
<Button
type="button"
variant="outline"
size="sm"
onClick={() => {
setSubmitted(false)
setPostUrl('')
setViews('')
setLikes('')
setReposts('')
setNotes('')
}}
>
{t('Submit another post')}
</Button>
</YStack>
) : (
<form onSubmit={handleSubmit}>
<YStack gap={20}>
{/* Platform Selector */}
<YStack gap={8}>
<Text fontFamily="$mono" fontSize="$1" fontWeight="600" color="var(--muted-foreground)">
{t('PLATFORM')}
</Text>
<XStack gap={8} flexWrap="wrap">
{[
{ id: 'tiktok', label: 'TikTok' },
{ id: 'x', label: '𝕏 / Twitter' },
{ id: 'youtube', label: 'YouTube Shorts' },
{ id: 'reddit', label: 'Reddit' },
{ id: 'linkedin', label: 'LinkedIn' },
{ id: 'other', label: 'Other' },
].map((p) => (
<Button
key={p.id}
type="button"
variant={platform === p.id ? 'default' : 'outline'}
size="sm"
onClick={() => setPlatform(p.id)}
>
{p.label}
</Button>
))}
</XStack>
</YStack>
{/* URL and Email Fields */}
<View
display="grid"
gap={16}
gridTemplateColumns="1fr"
$sm={{ gridTemplateColumns: 'repeat(2, minmax(0, 1fr))' }}
>
<YStack gap={6}>
<Text fontFamily="$mono" fontSize="$1" fontWeight="600" color="var(--muted-foreground)">
{t('PUBLIC POST OR VIDEO URL')}
</Text>
<Input
placeholder="https://tiktok.com/@... or https://x.com/..."
value={postUrl}
onChange={(e) => setPostUrl(e.target.value)}
bg="var(--neutral-900)"
borderColor="var(--neutral-700)"
required
/>
</YStack>
<YStack gap={6}>
<Text fontFamily="$mono" fontSize="$1" fontWeight="600" color="var(--muted-foreground)">
{t('YOUR HANZO ACCOUNT EMAIL')}
</Text>
<Input
type="email"
placeholder="[email protected]"
value={accountEmail}
onChange={(e) => setAccountEmail(e.target.value)}
bg="var(--neutral-900)"
borderColor="var(--neutral-700)"
required
/>
</YStack>
</View>
{/* Engagement Metrics (Horizontal) */}
<View
display="grid"
gap={16}
gridTemplateColumns="1fr"
$sm={{ gridTemplateColumns: 'repeat(3, minmax(0, 1fr))' }}
>
<YStack gap={6}>
<XStack items="center" gap={6}>
<Eye size={12} color="var(--muted-foreground)" />
<Text fontFamily="$mono" fontSize="$1" fontWeight="600" color="var(--muted-foreground)">
{t('VIEWS / IMPRESSIONS')}
</Text>
</XStack>
<Input
type="number"
placeholder="e.g. 5000"
value={views}
onChange={(e) => setViews(e.target.value)}
bg="var(--neutral-900)"
borderColor="var(--neutral-700)"
/>
</YStack>
<YStack gap={6}>
<XStack items="center" gap={6}>
<ThumbsUp size={12} color="var(--muted-foreground)" />
<Text fontFamily="$mono" fontSize="$1" fontWeight="600" color="var(--muted-foreground)">
{t('LIKES / UPVOTES')}
</Text>
</XStack>
<Input
type="number"
placeholder="e.g. 120"
value={likes}
onChange={(e) => setLikes(e.target.value)}
bg="var(--neutral-900)"
borderColor="var(--neutral-700)"
/>
</YStack>
<YStack gap={6}>
<XStack items="center" gap={6}>
<Repeat size={12} color="var(--muted-foreground)" />
<Text fontFamily="$mono" fontSize="$1" fontWeight="600" color="var(--muted-foreground)">
{t('SHARES / REPOSTS')}
</Text>
</XStack>
<Input
type="number"
placeholder="e.g. 35"
value={reposts}
onChange={(e) => setReposts(e.target.value)}
bg="var(--neutral-900)"
borderColor="var(--neutral-700)"
/>
</YStack>
</View>
{/* Payout Preference & Optional Notes */}
<View
display="grid"
gap={16}
gridTemplateColumns="1fr"
$sm={{ gridTemplateColumns: 'repeat(2, minmax(0, 1fr))' }}
>
<YStack gap={6}>
<Text fontFamily="$mono" fontSize="$1" fontWeight="600" color="var(--muted-foreground)">
{t('REWARD PREFERENCE')}
</Text>
<XStack gap={8}>
<Button
type="button"
size="sm"
variant={payoutType === 'credits' ? 'default' : 'outline'}
onClick={() => setPayoutType('credits')}
>
{t('Compute Credits')}
</Button>
<Button
type="button"
size="sm"
variant={payoutType === 'cash' ? 'default' : 'outline'}
onClick={() => setPayoutType('cash')}
>
{t('Cash / USDC ($500 Gold)')}
</Button>
</XStack>
</YStack>
<YStack gap={6}>
<Text fontFamily="$mono" fontSize="$1" fontWeight="600" color="var(--muted-foreground)">
{t('NOTES OR WALLET ADDRESS (OPTIONAL)')}
</Text>
<Input
placeholder="Optional wallet address or notes"
value={notes}
onChange={(e) => setNotes(e.target.value)}
bg="var(--neutral-900)"
borderColor="var(--neutral-700)"
/>
</YStack>
</View>
{/* Submit CTA */}
<XStack items="center" justify="space-between" flexWrap="wrap" gap={16} pt={8}>
<Text fontSize="$1" color="var(--muted-foreground)" maxW={400}>
{t('Reviewed within 24–48 hours against public engagement and referral criteria.')}
</Text>
<Action
render="button"
type="submit"
fill
disabled={submitting}
>
<Send size={15} aria-hidden />
{submitting ? t('Submitting…') : t('Submit Your Content')}
</Action>
</XStack>
</YStack>
</form>
)}
</YStack>
</YStack>
)
}
export default SubmitPost