234 lines
9.5 KiB
TypeScript
234 lines
9.5 KiB
TypeScript
|
|
"use client"
|
|||
|
|
|
|||
|
|
import { useState, useEffect } from "react"
|
|||
|
|
import Link from "next/link"
|
|||
|
|
import { ChevronLeft, Copy, Share2, Users, Wallet, MessageCircle, ImageIcon } from "lucide-react"
|
|||
|
|
import { Button } from "@/components/ui/button"
|
|||
|
|
import { useStore, type Purchase } from "@/lib/store"
|
|||
|
|
import { PosterModal } from "@/components/modules/referral/poster-modal"
|
|||
|
|
import { WithdrawalModal } from "@/components/modules/referral/withdrawal-modal"
|
|||
|
|
|
|||
|
|
export default function ReferralPage() {
|
|||
|
|
const { user, isLoggedIn, settings, getAllPurchases, getAllUsers } = useStore()
|
|||
|
|
const [copied, setCopied] = useState(false)
|
|||
|
|
const [showPoster, setShowPoster] = useState(false)
|
|||
|
|
const [showWithdrawal, setShowWithdrawal] = useState(false)
|
|||
|
|
const [referralPurchases, setReferralPurchases] = useState<Purchase[]>([])
|
|||
|
|
const [referralUsers, setReferralUsers] = useState<number>(0)
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
if (user?.referralCode) {
|
|||
|
|
const allPurchases = getAllPurchases()
|
|||
|
|
const allUsers = getAllUsers()
|
|||
|
|
const usersWithMyCode = allUsers.filter((u) => u.referredBy === user.referralCode)
|
|||
|
|
const userIds = usersWithMyCode.map((u) => u.id)
|
|||
|
|
const myReferralPurchases = allPurchases.filter((p) => userIds.includes(p.userId))
|
|||
|
|
setReferralPurchases(myReferralPurchases)
|
|||
|
|
setReferralUsers(usersWithMyCode.length)
|
|||
|
|
}
|
|||
|
|
}, [user, getAllPurchases, getAllUsers])
|
|||
|
|
|
|||
|
|
if (!isLoggedIn || !user) {
|
|||
|
|
return (
|
|||
|
|
<div className="min-h-screen bg-app-bg text-app-text flex items-center justify-center pb-20">
|
|||
|
|
<div className="text-center">
|
|||
|
|
<p className="text-app-text-muted mb-4">请先登录</p>
|
|||
|
|
<Link href="/" className="text-app-brand hover:underline">
|
|||
|
|
返回首页
|
|||
|
|
</Link>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const referralLink = `${typeof window !== "undefined" ? window.location.origin : ""}?ref=${user.referralCode}`
|
|||
|
|
const distributorShare = settings?.distributorShare || 90
|
|||
|
|
const totalEarnings = user.earnings || 0
|
|||
|
|
const pendingEarnings = user.pendingEarnings || 0
|
|||
|
|
|
|||
|
|
const handleCopy = () => {
|
|||
|
|
navigator.clipboard.writeText(referralLink)
|
|||
|
|
setCopied(true)
|
|||
|
|
setTimeout(() => setCopied(false), 2000)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const handleShare = async () => {
|
|||
|
|
const shareText = `我正在读《一场SOUL的创业实验场》,每天6-9点的真实商业故事,推荐给你!${referralLink}`
|
|||
|
|
try {
|
|||
|
|
if (typeof navigator.share === 'function' && typeof navigator.canShare === 'function') {
|
|||
|
|
await navigator.share({
|
|||
|
|
title: "一场SOUL的创业实验场",
|
|||
|
|
text: "来自Soul派对房的真实商业故事",
|
|||
|
|
url: referralLink,
|
|||
|
|
})
|
|||
|
|
} else {
|
|||
|
|
await navigator.clipboard.writeText(shareText)
|
|||
|
|
alert("分享文案已复制,快去朋友圈或Soul派对分享吧!")
|
|||
|
|
}
|
|||
|
|
} catch {
|
|||
|
|
await navigator.clipboard.writeText(shareText)
|
|||
|
|
alert("分享文案已复制!")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const handleShareToWechat = async () => {
|
|||
|
|
const shareText = `📖 推荐一本好书《一场SOUL的创业实验场》
|
|||
|
|
|
|||
|
|
这是卡若每天早上6-9点在Soul派对房分享的真实商业故事,55个真实案例,讲透创业的底层逻辑。
|
|||
|
|
|
|||
|
|
👉 点击阅读: ${referralLink}
|
|||
|
|
|
|||
|
|
#创业 #商业思维 #Soul派对`
|
|||
|
|
await navigator.clipboard.writeText(shareText)
|
|||
|
|
alert("朋友圈文案已复制!\n\n打开微信 → 发朋友圈 → 粘贴即可")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const handleShareToSoul = async () => {
|
|||
|
|
const shareText = `在Soul派对房听卡若讲了好多真实的创业故事,他把这些故事整理成了一本书《一场SOUL的创业实验场》,推荐给你们~
|
|||
|
|
|
|||
|
|
每天早上6-9点直播,这本书就是直播内容的精华版。
|
|||
|
|
|
|||
|
|
链接: ${referralLink}`
|
|||
|
|
await navigator.clipboard.writeText(shareText)
|
|||
|
|
alert("Soul分享文案已复制!\n\n打开Soul → 发动态 → 粘贴即可")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="min-h-screen bg-app-bg text-app-text pb-24">
|
|||
|
|
{/* Header */}
|
|||
|
|
<header className="sticky top-0 z-50 bg-app-bg/90 backdrop-blur-md border-b border-app-border">
|
|||
|
|
<div className="max-w-xs mx-auto px-4 py-3 flex items-center">
|
|||
|
|
<Link href="/my" className="flex items-center gap-1 text-app-text-muted hover:text-app-text">
|
|||
|
|
<ChevronLeft className="w-5 h-5" />
|
|||
|
|
</Link>
|
|||
|
|
<h1 className="flex-1 text-center text-sm font-semibold">分销中心</h1>
|
|||
|
|
<div className="w-5" />
|
|||
|
|
</div>
|
|||
|
|
</header>
|
|||
|
|
|
|||
|
|
<main className="max-w-xs mx-auto px-4 py-4">
|
|||
|
|
{/* Earnings Card */}
|
|||
|
|
<div className="bg-gradient-to-br from-app-brand/20 to-app-card rounded-xl p-4 border border-app-brand/30 mb-3">
|
|||
|
|
<div className="flex items-center justify-between mb-3">
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<Wallet className="w-4 h-4 text-app-brand" />
|
|||
|
|
<span className="text-app-text-muted text-xs">累计收益</span>
|
|||
|
|
</div>
|
|||
|
|
<span className="text-app-brand text-xs">{distributorShare}%返利</span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<p className="text-2xl font-bold text-app-text mb-0.5">¥{totalEarnings.toFixed(2)}</p>
|
|||
|
|
<p className="text-app-text-muted text-xs mb-3">待结算: ¥{pendingEarnings.toFixed(2)}</p>
|
|||
|
|
|
|||
|
|
<Button
|
|||
|
|
disabled={totalEarnings < 10}
|
|||
|
|
onClick={() => setShowWithdrawal(true)}
|
|||
|
|
className="w-full bg-app-brand hover:bg-app-brand-hover text-white h-8 text-xs"
|
|||
|
|
>
|
|||
|
|
{totalEarnings < 10 ? `满10元可提现` : "申请提现"}
|
|||
|
|
</Button>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Stats */}
|
|||
|
|
<div className="grid grid-cols-2 gap-2 mb-3">
|
|||
|
|
<div className="bg-app-card/60 rounded-lg p-2.5 text-center">
|
|||
|
|
<Users className="w-4 h-4 text-app-brand mx-auto mb-1" />
|
|||
|
|
<p className="text-base font-bold text-app-text">{referralUsers}</p>
|
|||
|
|
<p className="text-app-text-muted text-xs">邀请人数</p>
|
|||
|
|
</div>
|
|||
|
|
<div className="bg-app-card/60 rounded-lg p-2.5 text-center">
|
|||
|
|
<Share2 className="w-4 h-4 text-app-brand mx-auto mb-1" />
|
|||
|
|
<p className="text-base font-bold text-app-text">{referralPurchases.length}</p>
|
|||
|
|
<p className="text-app-text-muted text-xs">成交订单</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Referral link */}
|
|||
|
|
<div className="bg-app-card/60 rounded-xl p-3 border border-app-border mb-3">
|
|||
|
|
<p className="text-app-text text-xs font-medium mb-2">我的专属链接</p>
|
|||
|
|
<div className="flex gap-2 mb-2">
|
|||
|
|
<div className="flex-1 bg-app-bg rounded-lg px-2.5 py-1.5 text-app-text-muted text-xs truncate font-mono">
|
|||
|
|
{referralLink}
|
|||
|
|
</div>
|
|||
|
|
<Button
|
|||
|
|
onClick={handleCopy}
|
|||
|
|
size="sm"
|
|||
|
|
variant="outline"
|
|||
|
|
className="border-app-border text-app-text hover:bg-app-card bg-transparent text-xs h-7 px-2"
|
|||
|
|
>
|
|||
|
|
<Copy className="w-3 h-3 mr-1" />
|
|||
|
|
{copied ? "已复制" : "复制"}
|
|||
|
|
</Button>
|
|||
|
|
</div>
|
|||
|
|
<p className="text-app-text-muted text-xs">
|
|||
|
|
邀请码: <span className="text-app-brand font-mono">{user.referralCode}</span>
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Share buttons - improved for WeChat/Soul */}
|
|||
|
|
<div className="space-y-2 mb-3">
|
|||
|
|
<Button
|
|||
|
|
onClick={() => setShowPoster(true)}
|
|||
|
|
className="w-full bg-indigo-600 hover:bg-indigo-700 text-white py-4 text-xs"
|
|||
|
|
>
|
|||
|
|
<ImageIcon className="w-4 h-4 mr-2" />
|
|||
|
|
生成推广海报
|
|||
|
|
</Button>
|
|||
|
|
<Button
|
|||
|
|
onClick={handleShareToWechat}
|
|||
|
|
className="w-full bg-green-600 hover:bg-green-700 text-white py-4 text-xs"
|
|||
|
|
>
|
|||
|
|
<MessageCircle className="w-4 h-4 mr-2" />
|
|||
|
|
分享到朋友圈
|
|||
|
|
</Button>
|
|||
|
|
<Button
|
|||
|
|
onClick={handleShare}
|
|||
|
|
variant="outline"
|
|||
|
|
className="w-full border-app-border text-app-text hover:bg-app-card bg-transparent py-4 text-xs"
|
|||
|
|
>
|
|||
|
|
更多分享方式
|
|||
|
|
</Button>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<PosterModal
|
|||
|
|
isOpen={showPoster}
|
|||
|
|
onClose={() => setShowPoster(false)}
|
|||
|
|
referralLink={referralLink}
|
|||
|
|
referralCode={user.referralCode}
|
|||
|
|
nickname={user.nickname}
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<WithdrawalModal
|
|||
|
|
isOpen={showWithdrawal}
|
|||
|
|
onClose={() => setShowWithdrawal(false)}
|
|||
|
|
availableAmount={totalEarnings}
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
{/* Recent earnings */}
|
|||
|
|
{referralPurchases.length > 0 && (
|
|||
|
|
<div className="bg-app-card/60 rounded-xl border border-app-border">
|
|||
|
|
<div className="p-2.5 border-b border-app-border">
|
|||
|
|
<p className="text-app-text text-xs font-medium">收益明细</p>
|
|||
|
|
</div>
|
|||
|
|
<div className="divide-y divide-app-border max-h-40 overflow-auto">
|
|||
|
|
{referralPurchases.slice(0, 5).map((purchase) => (
|
|||
|
|
<div key={purchase.id} className="p-2.5 flex items-center justify-between">
|
|||
|
|
<div>
|
|||
|
|
<p className="text-app-text text-xs">{purchase.type === "fullbook" ? "整本书" : "单节"}</p>
|
|||
|
|
<p className="text-app-text-muted text-xs">
|
|||
|
|
{new Date(purchase.createdAt).toLocaleDateString("zh-CN")}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
<p className="text-app-brand text-sm font-semibold">
|
|||
|
|
+¥{(purchase.referrerEarnings || 0).toFixed(2)}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
</main>
|
|||
|
|
</div>
|
|||
|
|
)
|
|||
|
|
}
|