252 lines
7.2 KiB
TypeScript
252 lines
7.2 KiB
TypeScript
'use client'
|
||
|
||
import { useState, useEffect } from 'react'
|
||
|
||
interface UnlockModalProps {
|
||
isOpen: boolean
|
||
onClose: () => void
|
||
}
|
||
|
||
interface ReferralStatus {
|
||
referralCount: number
|
||
isUnlocked: boolean
|
||
referralsNeeded: number
|
||
referralsRemaining: number
|
||
}
|
||
|
||
export default function UnlockModal({ isOpen, onClose }: UnlockModalProps) {
|
||
const [referralStatus, setReferralStatus] = useState<ReferralStatus | null>(null)
|
||
const [referralLink, setReferralLink] = useState<string>('')
|
||
const [loading, setLoading] = useState(true)
|
||
const [copied, setCopied] = useState(false)
|
||
|
||
useEffect(() => {
|
||
if (isOpen) {
|
||
fetchReferralData()
|
||
}
|
||
}, [isOpen])
|
||
|
||
const fetchReferralData = async () => {
|
||
setLoading(true)
|
||
try {
|
||
// Fetch referral status
|
||
const statusResponse = await fetch('/api/referrals/status', {
|
||
credentials: 'include',
|
||
})
|
||
const statusData = await statusResponse.json()
|
||
setReferralStatus(statusData)
|
||
|
||
// Fetch referral link if user is logged in
|
||
const linkResponse = await fetch('/api/referrals/link', {
|
||
credentials: 'include',
|
||
})
|
||
if (linkResponse.ok) {
|
||
const linkData = await linkResponse.json()
|
||
setReferralLink(linkData.referralLink)
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching referral data:', error)
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
const handleCopyLink = async () => {
|
||
if (!referralLink) return
|
||
|
||
try {
|
||
await navigator.clipboard.writeText(referralLink)
|
||
setCopied(true)
|
||
setTimeout(() => setCopied(false), 2000)
|
||
} catch (error) {
|
||
console.error('Failed to copy link:', error)
|
||
}
|
||
}
|
||
|
||
if (!isOpen) return null
|
||
|
||
const status = referralStatus || {
|
||
referralCount: 0,
|
||
isUnlocked: false,
|
||
referralsNeeded: 3,
|
||
referralsRemaining: 3,
|
||
}
|
||
|
||
return (
|
||
<div
|
||
style={{
|
||
position: 'fixed',
|
||
top: 0,
|
||
left: 0,
|
||
right: 0,
|
||
bottom: 0,
|
||
background: 'rgba(0, 0, 0, 0.7)',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
zIndex: 1000,
|
||
padding: '20px',
|
||
}}
|
||
onClick={onClose}
|
||
>
|
||
<div
|
||
style={{
|
||
background: 'var(--card)',
|
||
borderRadius: '16px',
|
||
padding: '32px',
|
||
maxWidth: '500px',
|
||
width: '100%',
|
||
boxShadow: '0 20px 60px rgba(0, 0, 0, 0.3)',
|
||
}}
|
||
onClick={(e) => e.stopPropagation()}
|
||
>
|
||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '24px' }}>
|
||
<h2 style={{ margin: 0 }}>Unlock wholesale prices</h2>
|
||
<button
|
||
onClick={onClose}
|
||
style={{
|
||
background: 'transparent',
|
||
border: 'none',
|
||
fontSize: '24px',
|
||
cursor: 'pointer',
|
||
color: 'var(--muted)',
|
||
padding: 0,
|
||
width: '32px',
|
||
height: '32px',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
}}
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
|
||
{loading ? (
|
||
<p style={{ color: 'var(--muted)', textAlign: 'center' }}>Loading...</p>
|
||
) : (
|
||
<>
|
||
<div style={{ marginBottom: '24px', textAlign: 'center' }}>
|
||
<div style={{ fontSize: '18px', marginBottom: '8px' }}>
|
||
🔒 {status.referralCount} of {status.referralsNeeded} referrals completed
|
||
</div>
|
||
<p style={{ color: 'var(--muted)', fontSize: '14px', margin: '8px 0' }}>
|
||
Invite {status.referralsNeeded} friends to sign up.
|
||
<br />
|
||
Once they do, wholesale prices unlock forever.
|
||
</p>
|
||
</div>
|
||
|
||
{referralLink ? (
|
||
<div style={{ marginBottom: '24px' }}>
|
||
<label
|
||
style={{
|
||
display: 'block',
|
||
marginBottom: '8px',
|
||
fontSize: '14px',
|
||
color: 'var(--muted)',
|
||
fontWeight: 500,
|
||
}}
|
||
>
|
||
Your referral link
|
||
</label>
|
||
<div style={{ display: 'flex', gap: '8px' }}>
|
||
<input
|
||
type="text"
|
||
value={referralLink}
|
||
readOnly
|
||
style={{
|
||
flex: 1,
|
||
padding: '12px',
|
||
borderRadius: '8px',
|
||
border: '1px solid var(--border)',
|
||
background: 'var(--bg-soft)',
|
||
color: 'var(--text)',
|
||
fontSize: '14px',
|
||
fontFamily: 'monospace',
|
||
}}
|
||
/>
|
||
<button
|
||
onClick={handleCopyLink}
|
||
style={{
|
||
padding: '12px 20px',
|
||
background: copied ? 'var(--accent)' : 'var(--bg-soft)',
|
||
border: '1px solid var(--border)',
|
||
borderRadius: '8px',
|
||
color: copied ? '#000' : 'var(--text)',
|
||
cursor: 'pointer',
|
||
fontSize: '14px',
|
||
fontWeight: 500,
|
||
whiteSpace: 'nowrap',
|
||
}}
|
||
>
|
||
{copied ? 'Copied!' : 'Copy link'}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
) : (
|
||
<div
|
||
style={{
|
||
padding: '16px',
|
||
background: 'var(--bg-soft)',
|
||
borderRadius: '8px',
|
||
marginBottom: '24px',
|
||
textAlign: 'center',
|
||
color: 'var(--muted)',
|
||
fontSize: '14px',
|
||
}}
|
||
>
|
||
Please log in to get your referral link
|
||
</div>
|
||
)}
|
||
|
||
<div
|
||
style={{
|
||
padding: '12px',
|
||
background: 'var(--bg-soft)',
|
||
borderRadius: '8px',
|
||
marginBottom: '24px',
|
||
fontSize: '13px',
|
||
color: 'var(--muted)',
|
||
textAlign: 'center',
|
||
}}
|
||
>
|
||
Friends must sign up to count.
|
||
</div>
|
||
|
||
<div
|
||
style={{
|
||
textAlign: 'center',
|
||
fontSize: '16px',
|
||
fontWeight: 500,
|
||
color: 'var(--text)',
|
||
marginBottom: '24px',
|
||
}}
|
||
>
|
||
{status.referralsRemaining} referral{status.referralsRemaining !== 1 ? 's' : ''} to go
|
||
</div>
|
||
|
||
<button
|
||
onClick={onClose}
|
||
style={{
|
||
width: '100%',
|
||
padding: '12px 24px',
|
||
background: 'var(--accent)',
|
||
color: '#000',
|
||
border: 'none',
|
||
borderRadius: '14px',
|
||
cursor: 'pointer',
|
||
fontSize: '15px',
|
||
fontWeight: 500,
|
||
}}
|
||
>
|
||
Close
|
||
</button>
|
||
</>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|