Files
soul/components/modules/marketing/qr-code-modal.tsx

124 lines
4.4 KiB
TypeScript

"use client"
import { X, MessageCircle, Users, Music } from "lucide-react"
import { useStore } from "@/lib/store"
import { Button } from "@/components/ui/button"
import Image from "next/image"
import { useState, useEffect } from "react"
interface QRCodeModalProps {
isOpen: boolean
onClose: () => void
}
export function QRCodeModal({ isOpen, onClose }: QRCodeModalProps) {
const { settings, getLiveQRCodeUrl } = useStore()
const [isJoining, setIsJoining] = useState(false)
const [qrCodeUrl, setQrCodeUrl] = useState("/images/party-group-qr.png") // Default fallback
// Fetch config on mount
useEffect(() => {
const fetchConfig = async () => {
try {
const res = await fetch('/api/config')
const data = await res.json()
if (data.marketing?.partyGroup?.qrCode) {
setQrCodeUrl(data.marketing.partyGroup.qrCode)
}
} catch (e) {
console.error("Failed to load QR config", e)
}
}
fetchConfig()
}, [])
if (!isOpen) return null
const handleJoin = () => {
setIsJoining(true)
// 获取活码随机URL
const url = getLiveQRCodeUrl("party-group")
if (url) {
window.open(url, "_blank")
}
setTimeout(() => setIsJoining(false), 1000)
}
return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
<div className="absolute inset-0 bg-black/80 backdrop-blur-md" onClick={onClose} />
{/* iOS Style Modal */}
<div className="relative w-full max-w-[320px] bg-[#1a1a1a] rounded-3xl border border-white/10 overflow-hidden shadow-2xl animate-in fade-in zoom-in-95 duration-200">
{/* Header Background Effect */}
<div className="absolute top-0 left-0 right-0 h-32 bg-gradient-to-b from-[#7000ff]/20 to-transparent pointer-events-none" />
<button
onClick={onClose}
className="absolute top-4 right-4 p-2 text-white/50 hover:text-white transition-colors z-10 bg-black/20 rounded-full backdrop-blur-sm"
>
<X className="w-5 h-5" />
</button>
<div className="p-8 flex flex-col items-center text-center relative">
{/* Icon Badge */}
<div className="w-16 h-16 mb-6 rounded-full bg-gradient-to-tr from-[#7000ff] to-[#bd00ff] p-[2px] shadow-lg shadow-purple-500/20">
<div className="w-full h-full rounded-full bg-[#1a1a1a] flex items-center justify-center">
<Music className="w-8 h-8 text-[#bd00ff]" />
</div>
</div>
<h3 className="text-xl font-bold text-white mb-2 tracking-tight">
Soul
</h3>
<div className="flex items-center gap-2 mb-6">
<span className="px-2 py-0.5 rounded-full bg-white/10 text-[10px] text-white/70 border border-white/5">
Live
</span>
<p className="text-white/60 text-xs">
{settings.authorInfo?.liveTime || "06:00-09:00"} · {settings.authorInfo?.name || "卡若"}
</p>
</div>
{/* QR Code Container - Enhanced Visibility */}
<div className="bg-white p-3 rounded-2xl shadow-xl mb-6 transform transition-transform hover:scale-105 duration-300">
<div className="relative w-48 h-48">
<Image
src={qrCodeUrl}
alt="派对群二维码"
fill
className="object-contain"
/>
</div>
</div>
<p className="text-white/40 text-xs mb-6 px-4">
<br/>100
</p>
<Button
onClick={handleJoin}
disabled={isJoining}
className="w-full bg-gradient-to-r from-[#7000ff] to-[#bd00ff] hover:opacity-90 text-white font-medium rounded-xl h-12 shadow-lg shadow-purple-900/20 border-0 transition-all active:scale-95"
>
{isJoining ? (
<span className="flex items-center gap-2">
<Users className="w-4 h-4 animate-pulse" />
...
</span>
) : (
<span className="flex items-center gap-2">
<MessageCircle className="w-4 h-4" />
</span>
)}
</Button>
</div>
</div>
</div>
)
}