ai / components /SlashModal.tsx
Lianjx's picture
Upload 75 files
8fb4cca verified
import React, { useState, useEffect } from 'react';
import { X, Zap, Timer } from 'lucide-react';
import { Language, WeddingStyle, AdminConfig, UserAccount } from '../types';
import { TRANSLATIONS } from '../constants/translations';
interface SlashModalProps {
isVisible: boolean;
onClose: () => void;
language: Language;
style: WeddingStyle | null;
onUnlock: () => void;
adminConfig: AdminConfig;
user?: UserAccount;
onUpdateUser: (progress: Record<string, number>) => void;
onOpenShare: () => void;
}
export const SlashModal: React.FC<SlashModalProps> = ({
isVisible, onClose, language, style, onUnlock, adminConfig, user, onUpdateUser, onOpenShare
}) => {
const t = TRANSLATIONS[language];
const [progress, setProgress] = useState(98);
useEffect(() => {
if (isVisible && style) {
if (user?.slashProgress && user.slashProgress[style.id]) {
setProgress(user.slashProgress[style.id]);
} else {
setProgress(98);
}
}
}, [isVisible, style, user]);
if (!isVisible || !style) return null;
const styleName = (t.styles as any)[style.id] || style.name;
const handleInvite = () => {
onOpenShare();
// Update progress logic
const remaining = 100 - progress;
// Slash logic: Cut 50-80% of remaining
const cutPercent = 0.5 + Math.random() * 0.3;
let newProgress = progress + (remaining * cutPercent);
// If very close, complete it (e.g. > 99.5)
if (newProgress > 99.5) {
newProgress = 100;
}
setProgress(newProgress);
if (user) {
const newMap = { ...(user.slashProgress || {}), [style.id]: newProgress };
onUpdateUser(newMap);
}
if (newProgress >= 100) {
onUnlock();
}
onClose();
};
return (
<div className="fixed inset-0 z-[110] flex items-center justify-center p-4 bg-black/70 backdrop-blur-sm animate-fade-in">
<div className="bg-gradient-to-b from-orange-500 to-red-600 rounded-2xl shadow-2xl w-full max-w-sm overflow-hidden relative text-white">
<button onClick={onClose} className="absolute top-2 right-2 p-1.5 bg-black/20 rounded-full hover:bg-black/40 z-20">
<X className="w-4 h-4" />
</button>
<div className="p-6 text-center">
<div className="inline-block px-3 py-1 bg-black/30 rounded-full text-xs font-bold mb-4 flex items-center gap-1 mx-auto border border-white/20">
<Timer className="w-3 h-3" /> Ends in 23:59:10
</div>
<h2 className="text-2xl font-bold italic drop-shadow-md">{t.pddSlashTitle}</h2>
<p className="text-orange-100 text-sm mt-1">{t.pddSlashDesc}</p>
{/* Product Card */}
<div className="bg-white text-gray-900 rounded-xl p-3 mt-6 flex items-center gap-3 shadow-lg">
<div className="w-16 h-16 bg-gray-200 rounded-lg shrink-0 overflow-hidden relative">
<div className={`w-full h-full ${style.coverColor} opacity-50`}></div>
<div className="absolute inset-0 flex items-center justify-center">
<span className="text-xs font-bold text-gray-500">IMG</span>
</div>
</div>
<div className="text-left flex-1">
<p className="font-bold text-sm truncate">{styleName}</p>
<p className="text-xs text-gray-500">VIP Premium Collection</p>
<p className="text-red-500 font-bold text-sm mt-1">¥0.00 <span className="text-gray-400 line-through text-xs">¥199</span></p>
</div>
</div>
{/* Progress Bar */}
<div className="mt-6 relative">
<div className="flex justify-between text-xs font-bold mb-1">
<span className="text-yellow-200">{t.pddSlashProgress}</span>
<span>{progress.toFixed(2)}%</span>
</div>
<div className="h-4 bg-black/30 rounded-full overflow-hidden border border-white/20">
<div className="h-full bg-gradient-to-r from-yellow-300 to-yellow-500 relative" style={{ width: `${progress}%` }}>
<div className="absolute top-0 right-0 h-full w-2 bg-white/50 animate-pulse"></div>
</div>
</div>
<div className="absolute -right-2 -top-2 bg-red-100 text-red-600 text-[10px] font-bold px-1.5 rounded-full border border-red-500 shadow-sm animate-bounce">
Only {(100 - progress).toFixed(2)}% left!
</div>
</div>
<button
onClick={handleInvite}
className="w-full py-3 bg-yellow-400 hover:bg-yellow-300 text-red-700 font-extrabold text-lg rounded-full mt-6 shadow-xl shadow-orange-700/50 flex items-center justify-center gap-2 transform active:scale-95 transition-all"
>
<Zap className="w-5 h-5 fill-current" /> {t.pddSlashCta}
</button>
</div>
{/* Social Proof List */}
<div className="bg-white/10 p-4 border-t border-white/10">
<p className="text-xs text-white/60 mb-2 text-center">Friends who helped</p>
<div className="flex justify-center -space-x-2">
{[1,2,3].map(i => (
<div key={i} className="w-8 h-8 rounded-full bg-gray-200 border-2 border-orange-500"></div>
))}
<div className="w-8 h-8 rounded-full bg-gray-800 border-2 border-orange-500 flex items-center justify-center text-[10px] text-white">
+99
</div>
</div>
</div>
</div>
</div>
);
};