126 lines
5.7 KiB
TypeScript
126 lines
5.7 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Flame, Sparkles } from "lucide-react";
|
|
import { useActiveUser } from "@/hooks/useActiveUser";
|
|
import { useTheme } from "next-themes";
|
|
|
|
export function StreakOnboardingModal() {
|
|
const { user, loading } = useActiveUser();
|
|
const { theme } = useTheme();
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (loading || !user) return;
|
|
|
|
// Check sessionStorage
|
|
const hasSeen = sessionStorage.getItem(`hasSeenStreakPopup_${user.id}`);
|
|
if (!hasSeen) {
|
|
setIsOpen(true);
|
|
}
|
|
}, [user, loading]);
|
|
|
|
if (!isOpen || !user) return null;
|
|
|
|
const streak = user.streak_count;
|
|
const targetExam = user.target_exam?.replace("_", " ") || "JEE/NEET";
|
|
|
|
// Streak-based wishes and titles
|
|
let wishTitle = "Welcome to PragatiVeer! 🌟";
|
|
let wishMessage = `Prepare yourself to conquer ${targetExam}. Your daily practice starts here!`;
|
|
|
|
if (streak === 0) {
|
|
wishTitle = "Start Your Streak Today! 🚀";
|
|
wishMessage = "Today is Day 1 of your journey. Establish your streak now and build the consistency needed for IIT/AIIMS!";
|
|
} else if (streak < 4) {
|
|
wishTitle = "Keep the Fire Burning! 🔥";
|
|
wishMessage = `Great job! You have maintained a ${streak}-day study streak. Keep practicing daily to build solid muscle memory!`;
|
|
} else {
|
|
wishTitle = "Unstoppable Dedication! ⚡";
|
|
wishMessage = `Incredible! A ${streak}-day streak shows true championship discipline. You are outperforming the competition. Let's make today count!`;
|
|
}
|
|
|
|
const handleEnter = () => {
|
|
sessionStorage.setItem(`hasSeenStreakPopup_${user.id}`, "true");
|
|
setIsOpen(false);
|
|
};
|
|
|
|
// Calculate trial days left
|
|
let trialDaysLeft = 0;
|
|
if (user.trial_end) {
|
|
const end = new Date(user.trial_end);
|
|
const now = new Date();
|
|
const diffTime = end.getTime() - now.getTime();
|
|
trialDaysLeft = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
}
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-background/85 backdrop-blur-md animate-in fade-in duration-300">
|
|
|
|
{/* Centered Modal Card Container covering 80% screen size (w-[80vw] h-[80vh]) */}
|
|
<div className="bg-background border border-border/80 shadow-[0_0_60px_-10px_rgba(0,240,255,0.25)] rounded-3xl w-[80vw] max-w-5xl h-[80vh] max-h-[800px] relative overflow-hidden animate-in zoom-in-95 slide-in-from-bottom-4 duration-300 z-20 pointer-events-auto mx-4 flex flex-col justify-start">
|
|
|
|
{/* Subtle background glow */}
|
|
<div className="absolute -right-20 -top-20 size-48 bg-[#00F0FF]/5 rounded-full blur-3xl pointer-events-none" />
|
|
<div className="absolute -left-20 -bottom-20 size-48 bg-primary/5 rounded-full blur-3xl pointer-events-none" />
|
|
|
|
{/* Top Celebration Animation Panel (Iframe with height 60%, matching bg) */}
|
|
<div className="relative w-full h-[60%] z-10 pointer-events-none overflow-hidden bg-background">
|
|
<iframe
|
|
src={`/streak-animation.html?streak=${streak}&theme=${theme === 'light' ? 'light' : 'dark'}`}
|
|
className="w-full h-full border-none"
|
|
title="Streak Celebration"
|
|
allowtransparency="true"
|
|
/>
|
|
</div>
|
|
|
|
{/* Bottom Greetings & Action Panel (height 40%, matching bg) */}
|
|
<div className="p-8 text-center flex-1 flex flex-col justify-between bg-background z-20">
|
|
|
|
<div className="space-y-4">
|
|
{/* Badge Indicators */}
|
|
<div className="flex flex-col items-center gap-3">
|
|
{streak > 0 ? (
|
|
<div className="inline-flex items-center gap-2 px-4 py-1.5 bg-orange-500/10 border border-orange-500/30 text-orange-500 text-sm md:text-base font-extrabold rounded-full tracking-wider uppercase">
|
|
<Flame size={16} className="fill-current animate-bounce" /> {streak} Day Streak Active
|
|
</div>
|
|
) : (
|
|
<div className="inline-flex items-center gap-2 px-4 py-1.5 bg-blue-500/10 border border-blue-500/30 text-blue-400 text-sm md:text-base font-extrabold rounded-full tracking-wider uppercase">
|
|
<Sparkles size={16} className="animate-spin" style={{ animationDuration: '4s' }} /> Day 1 Awaits
|
|
</div>
|
|
)}
|
|
|
|
{trialDaysLeft > 0 && (
|
|
<div className="inline-flex items-center gap-2 px-4 py-1.5 bg-emerald-500/10 border border-emerald-500/30 text-emerald-400 text-sm md:text-base font-semibold rounded-full tracking-wider">
|
|
🎁 Free Trial: {trialDaysLeft} {trialDaysLeft === 1 ? "day" : "days"} remaining
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Greetings Text */}
|
|
<div className="space-y-3">
|
|
<h3 className="text-2xl md:text-3xl font-black tracking-tight bg-gradient-to-r dark:from-white dark:via-white dark:to-gray-400 from-black via-black to-gray-600 bg-clip-text text-transparent">
|
|
{wishTitle}
|
|
</h3>
|
|
<p className="text-muted-foreground text-sm md:text-base leading-relaxed max-w-lg mx-auto">
|
|
{wishMessage}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Action Button */}
|
|
<div className="pt-2 max-w-sm w-full mx-auto">
|
|
<Button
|
|
onClick={handleEnter}
|
|
className="w-full h-12 rounded-xl text-base font-black bg-[#00F0FF] text-black hover:bg-[#00F0FF]/90 shadow-[0_0_15px_-3px_#00F0FF] hover:shadow-[0_0_25px_#00F0FF] hover:-translate-y-0.5 transition-all duration-300"
|
|
>
|
|
Enter Workspace
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|