import React, { useState, useEffect } from "react";
import { base44 } from "@/api/base44Client";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { ArrowRight, Sparkles, CheckCircle, Crown } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Link } from "react-router-dom";
import { createPageUrl } from "@/utils";
import { format, differenceInDays, parseISO } from "date-fns";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent } from "@/components/ui/card";
import DailyChallengeCard from "../components/today/DailyChallengeCard";
import JournalCard from "../components/today/JournalCard";
import StreakCard from "../components/progress/StreakCard";
import Day30Celebration from "../components/celebration/Day30Celebration";
export default function TodayPage() {
const queryClient = useQueryClient();
const [user, setUser] = useState(null);
const [showCelebration, setShowCelebration] = useState(false);
const [showPaywall, setShowPaywall] = useState(false);
useEffect(() => {
const loadUser = async () => {
const currentUser = await base44.auth.me();
setUser(currentUser);
};
loadUser();
}, []);
const currentDay = user?.current_day || 1;
// Check if user hit paywall at day 8
useEffect(() => {
if (user && user.membership_tier === 'free' && currentDay >= 8) {
setShowPaywall(true);
}
}, [user, currentDay]);
const { data: challenges } = useQuery({
queryKey: ['challenges'],
queryFn: () => base44.entities.DailyChallenge.list(),
initialData: [],
});
const { data: journalEntries } = useQuery({
queryKey: ['journal-entries'],
queryFn: () => base44.entities.JournalEntry.filter({ created_by: user?.email }),
initialData: [],
enabled: !!user,
});
const updateUserMutation = useMutation({
mutationFn: (userData) => base44.auth.updateMe(userData),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['user'] });
// Re-fetch user to get updated state for local component
base44.auth.me().then(updatedUser => setUser(updatedUser));
},
});
const createJournalMutation = useMutation({
mutationFn: (entryData) => base44.entities.JournalEntry.create(entryData),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['journal-entries'] });
},
});
const todayChallenge = challenges.find(c => c.day_number === currentDay);
const todayEntry = journalEntries.find(e => e.day_number === currentDay);
const getDailyMotivation = () => {
if (currentDay <= 5) {
return {
phase: "Awareness & Resistance",
message: "You're waking up to your walls. Uncomfortable? Good. That's how you know you're breaking through.",
emoji: "ποΈ"
};
} else if (currentDay <= 15) {
return {
phase: "Building Momentum",
message: `Day ${currentDay}. You're not the same person who started. Face it to break it. Keep moving.`,
emoji: "πͺ"
};
} else if (currentDay <= 25) {
return {
phase: "Faith Over Feelings",
message: "Most people quit here. Not you. Pressure reveals strength. You're built for this.",
emoji: "π₯"
};
} else {
return {
phase: "Breakthrough Zone",
message: "Almost there. Don't stop now. Your becoming is on the other side of this wall.",
emoji: "π"
};
}
};
const motivation = getDailyMotivation();
const updateStreak = () => {
const today = format(new Date(), 'yyyy-MM-dd');
const lastActivity = user?.last_activity_date;
let newStreak = user?.streak_count || 0;
if (lastActivity) {
const daysSince = differenceInDays(new Date(today), parseISO(lastActivity));
if (daysSince === 1) {
newStreak += 1;
} else if (daysSince > 1) {
newStreak = 1;
}
} else {
newStreak = 1;
}
return { newStreak, today };
};
const awardBadges = (newStreak, totalWalls) => {
const badges = [...(user?.badges_earned || [])];
const badgeIds = badges.map(b => b.badge_id);
// Streak badges
if (newStreak >= 3 && !badgeIds.includes('three_day_streak')) {
badges.push({ badge_id: 'three_day_streak', badge_name: '3-Day Streak', earned_date: new Date().toISOString(), description: '3 consecutive days' });
}
if (newStreak >= 7 && !badgeIds.includes('seven_day_streak')) {
badges.push({ badge_id: 'seven_day_streak', badge_name: 'Week Warrior', earned_date: new Date().toISOString(), description: '7 consecutive days' });
}
if (newStreak >= 14 && !badgeIds.includes('two_week_streak')) {
badges.push({ badge_id: 'two_week_streak', badge_name: 'Unstoppable', earned_date: new Date().toISOString(), description: '14 consecutive days' });
}
// Wall badges
if (totalWalls === 1 && !badgeIds.includes('first_step')) {
badges.push({ badge_id: 'first_step', badge_name: 'First Step', earned_date: new Date().toISOString(), description: 'Started your journey' });
}
if (totalWalls >= 5 && !badgeIds.includes('wall_smasher')) {
badges.push({ badge_id: 'wall_smasher', badge_name: 'Wall Smasher', earned_date: new Date().toISOString(), description: '5 walls broken' });
}
if (totalWalls >= 10 && !badgeIds.includes('breakthrough_champion')) {
badges.push({ badge_id: 'breakthrough_champion', badge_name: 'Breakthrough Champion', earned_date: new Date().toISOString(), description: '10 walls broken' });
}
// Journey complete
if (currentDay >= 30 && !badgeIds.includes('journey_complete')) {
badges.push({ badge_id: 'journey_complete', badge_name: 'Journey Complete', earned_date: new Date().toISOString(), description: 'Completed all 30 days' });
}
if (currentDay >= 30 && newStreak >= 30 && !badgeIds.includes('consistency_champ')) { // Check newStreak for this specific badge
badges.push({ badge_id: 'consistency_champ', badge_name: 'Consistency Champ', earned_date: new Date().toISOString(), description: 'Perfect 30-day streak' });
}
return badges;
};
const handleSaveJournal = async (entryData) => {
await createJournalMutation.mutateAsync(entryData);
const { newStreak, today } = updateStreak();
const newTotalWalls = (user?.total_walls_broken || 0) + 1;
const newBadges = awardBadges(newStreak, newTotalWalls);
const isComplete = currentDay >= 30;
await updateUserMutation.mutateAsync({
last_activity_date: today,
streak_count: newStreak,
total_walls_broken: newTotalWalls,
current_day: Math.min(currentDay + 1, 30), // Cap at 30
badges_earned: newBadges,
completed_journey: isComplete,
completion_date: isComplete ? today : user?.completion_date
});
// Only show celebration if journey is now complete and wasn't before
if (isComplete && !user?.completed_journey) {
setTimeout(() => setShowCelebration(true), 1000); // Small delay for UX
}
};
if (!user || !todayChallenge) {
return (
);
}
if (showPaywall) {
return (
You're Not Done Yet
You just finished 7 days. That's powerful. But here's the truth β
you're just getting started. The real breakthroughs? They're in the next 23 days.
Don't stop now. Upgrade to Pro and finish what you started.
What You Get with Pro:
All 30 days unlocked β finish your journey
Extended video lessons & audio affirmations
Monthly live Freedom Sessions with Angel V
Faith Reflection mode with daily scripture
Digital certificate when you finish
$9.99
/ month
$79
/ year
Save $40
Stripe integration coming soon. Contact support@angelvinspires.com to upgrade early.
"The walls you break become the bridges you build for others."
β Angel V
);
}
return (
<>
{showCelebration && user?.completed_journey && (
setShowCelebration(false)}
/>
)}
{motivation.phase} {motivation.emoji}
Day {currentDay}: Let's Break This Wall
{format(new Date(), 'EEEE, MMMM d, yyyy')}
{motivation.message}
{!todayEntry && (
You're Built For This
You don't need perfect faith to break a wall. Just a willing step. Do the work. Trust the process. Watch what happens.
No wall too big.
)}
{todayEntry && (
Wall Broken Today! π
You showed up. You faced it. That's how walls come down β one willing step at a time.
{user.streak_count}
Day Streak
{user.total_walls_broken}
Walls Broken
You're becoming. Come back tomorrow. More walls to break.
)}
>
);
}