diff --git a/src/app/tips/page.tsx b/src/app/tips/page.tsx new file mode 100644 index 0000000..33df143 --- /dev/null +++ b/src/app/tips/page.tsx @@ -0,0 +1,32 @@ + +'use client'; + +import React from 'react'; +import { TIPS_DATABASE } from '@/constants/tips'; +import Link from 'next/link'; + +const AllTipsPage = () => { + return ( +
+
+
+

All Tips

+ Back to Dashboard +
+
+ {TIPS_DATABASE.map(tip => ( +
+
+ {tip.icon} +

{tip.title}

+
+

{tip.description}

+
+ ))} +
+
+
+ ); +}; + +export default AllTipsPage; diff --git a/src/components/dashboard/Dashboard.tsx b/src/components/dashboard/Dashboard.tsx index 53b6274..92ebf7f 100644 --- a/src/components/dashboard/Dashboard.tsx +++ b/src/components/dashboard/Dashboard.tsx @@ -14,6 +14,7 @@ import { getUserFootprints } from "@/lib/firebase/firestore"; import { exportToCSV, ActivityHistoryEntry } from "@/utils/exportCSV"; import { ArrowDownTrayIcon } from "@heroicons/react/24/outline"; import Spinner from "@/components/ui/Spinner"; +import TipOfTheDay from "@/components/tips/TipOfTheDay"; type SortOption = "newest" | "oldest" | "highest_impact" | "lowest_impact"; @@ -289,6 +290,31 @@ export default function Dashboard({ + {/* Tip of the Day */} + + + {/* Stats Cards */} +
+ + + +
+ {/* Stats Cards */}
{ + const [currentTip, setCurrentTip] = useState(null); + + useEffect(() => { + setCurrentTip(getTodaysTip()); + }, []); + + const handleNextTip = () => { + if (currentTip) { + const nextTip = getNextTip(currentTip.id); + setCurrentTip(nextTip); + } + }; + + if (!currentTip) { + return null; + } + + return ( +
+

+ 💡 Tip of the Day +

+
+

{currentTip.title}

+

{currentTip.description}

+
+
+ + + All Tips + +
+
+ ); +}; + +export default TipOfTheDay; diff --git a/src/utils/tipRotation.ts b/src/utils/tipRotation.ts new file mode 100644 index 0000000..7ad92a4 --- /dev/null +++ b/src/utils/tipRotation.ts @@ -0,0 +1,82 @@ + +import { Tip } from '@/types'; +import { TIPS_DATABASE } from '@/constants/tips'; + +const VIEWED_TIPS_KEY = 'viewedTips'; +const LAST_TIP_DATE_KEY = 'lastTipDate'; + +type ViewedTips = { + [id: string]: string; // { tipId: dateViewed } +}; + +const getPreviouslyViewedTips = (): ViewedTips => { + if (typeof window === 'undefined') { + return {}; + } + const viewedTips = localStorage.getItem(VIEWED_TIPS_KEY); + return viewedTips ? JSON.parse(viewedTips) : {}; +}; + +const saveViewedTip = (tipId: string) => { + if (typeof window === 'undefined') { + return; + } + const viewedTips = getPreviouslyViewedTips(); + viewedTips[tipId] = new Date().toISOString(); + localStorage.setItem(VIEWED_TIPS_KEY, JSON.stringify(viewedTips)); +}; + +const isTipRecent = (dateViewed: string): boolean => { + const thirtyDaysAgo = new Date(); + thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); + return new Date(dateViewed) > thirtyDaysAgo; +}; + +const getUnseenTips = (): Tip[] => { + const viewedTips = getPreviouslyViewedTips(); + const unseenTips = TIPS_DATABASE.filter(tip => { + const dateViewed = viewedTips[tip.id]; + return !dateViewed || !isTipRecent(dateViewed); + }); + return unseenTips.length > 0 ? unseenTips : TIPS_DATABASE; // Fallback to all tips if all have been seen +}; + +export const getTodaysTip = (): Tip => { + if (typeof window === 'undefined') { + return TIPS_DATABASE[0]; + } + const lastTipDate = localStorage.getItem(LAST_TIP_DATE_KEY); + const today = new Date().toDateString(); + + if (lastTipDate === today) { + const lastTipId = localStorage.getItem('lastTipId'); + const lastTip = TIPS_DATABASE.find(tip => tip.id === lastTipId); + if (lastTip) { + return lastTip; + } + } + + const unseenTips = getUnseenTips(); + const todaysTip = unseenTips[Math.floor(Math.random() * unseenTips.length)]; + + localStorage.setItem(LAST_TIP_DATE_KEY, today); + localStorage.setItem('lastTipId', todaysTip.id); + saveViewedTip(todaysTip.id); + + return todaysTip; +}; + +export const getNextTip = (currentTipId: string): Tip => { + const unseenTips = getUnseenTips(); + let nextTip = unseenTips[Math.floor(Math.random() * unseenTips.length)]; + + while (nextTip.id === currentTipId && unseenTips.length > 1) { + nextTip = unseenTips[Math.floor(Math.random() * unseenTips.length)]; + } + + saveViewedTip(nextTip.id); + localStorage.setItem('lastTipId', nextTip.id); + + + return nextTip; +};