Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions src/components/dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import FootprintChart from "@/components/charts/FootprintChart";
import ComparisonSection from "@/components/dashboard/ComparisonSection";
import ShareButton from "@/components/ui/ShareButton";
import { getUserFootprints } from "@/lib/firebase/firestore";
import { getUserFootprints, subscribeToUserActivitiesCount } from "@/lib/firebase/firestore";
import { exportToCSV, ActivityHistoryEntry } from "@/utils/exportCSV";
import { ArrowDownTrayIcon } from "@heroicons/react/24/outline";

Expand All @@ -29,11 +29,12 @@ interface StatCardProps {
change?: number;
icon: string;
color: string;
tooltip?: string;
}

function StatCard({ title, value, change, icon, color }: StatCardProps) {
function StatCard({ title, value, change, icon, color, tooltip }: StatCardProps) {
return (
<div className="bg-white rounded-xl shadow-lg p-6">
<div className="bg-white rounded-xl shadow-lg p-6 hover:shadow-xl transition" title={tooltip}>
<div className="flex items-center justify-between">
<div>
<p className="text-gray-600 text-sm font-medium">{title}</p>
Expand Down Expand Up @@ -100,6 +101,7 @@ export default function Dashboard({
null
);
const [loading, setLoading] = useState(true);
const [activitiesCount, setActivitiesCount] = useState(0);
const [exportStatus, setExportStatus] = useState<{
show: boolean;
success: boolean;
Expand Down Expand Up @@ -212,6 +214,12 @@ export default function Dashboard({
}
}, [propDashboardData]);

// Real-time subscription to activities count
useEffect(() => {
if (!user) return;
const unsubscribe = subscribeToUserActivitiesCount(user.id, setActivitiesCount);
return () => unsubscribe();
}, [user, activityHistory.length]);
// Handle CSV export
const handleExportCSV = () => {
const result = exportToCSV(activityHistory as ActivityHistoryEntry[]);
Expand Down Expand Up @@ -259,6 +267,11 @@ export default function Dashboard({

const equivalentIcons = ["πŸš—", "πŸ“±", "β˜•", "πŸ’‘"];

// Format join date for tooltip
const joinDateLabel = user?.createdAt
? new Date(user.createdAt).toLocaleDateString()
: '';

return (
<div className="min-h-screen bg-gradient-to-br from-green-50 to-emerald-100 p-6">
<div className="max-w-7xl mx-auto space-y-8">
Expand All @@ -280,7 +293,7 @@ export default function Dashboard({
</div>

{/* Stats Cards */}
<div className="grid md:grid-cols-3 gap-6">
<div className="grid md:grid-cols-4 gap-6">
<StatCard
title="Today's Footprint"
value={formatCO2Amount(dashboardData.todayFootprint)}
Expand All @@ -299,6 +312,13 @@ export default function Dashboard({
icon="πŸ“ˆ"
color="text-purple-600"
/>
<StatCard
title="Activities Tracked"
value={`${activitiesCount.toLocaleString()} activities tracked`}
icon="πŸ“ˆ"
color="text-indigo-600"
tooltip={`since ${joinDateLabel}`}
/>
</div>

{/* Comparison Section */}
Expand Down
27 changes: 27 additions & 0 deletions src/lib/firebase/firestore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
limit,
getDocs,
Timestamp,
onSnapshot,
} from 'firebase/firestore';
import { db } from './config';
import { Activity, CarbonFootprint, User, WeeklyGoal, Badge } from '@/types';
Expand Down Expand Up @@ -159,4 +160,30 @@ export const awardBadge = async (userId: string, badge: Omit<Badge, 'id' | 'achi
achieved: true,
achievedAt: Timestamp.now(),
});
};

// Real-time subscrition to count of user's carbon footprint submissions
export const subscribeToUserSubmissionCount = (
userId: string,
onCount: (count: number) => void
) => {
const footprintsRef = collection(db, 'carbon_footprints');
const q = query(footprintsRef, where('userId', '==', userId));
const unsubscribe = onSnapshot(q, (snapshot) => {
onCount(snapshot.size);
});
return unsubscribe;
};

// Real-time subscription to count of user's individual activities
export const subscribeToUserActivitiesCount = (
userId: string,
onCount: (count: number) => void
) => {
const activitiesRef = collection(db, 'activities');
const q = query(activitiesRef, where('userId', '==', userId));
const unsubscribe = onSnapshot(q, (snapshot) => {
onCount(snapshot.size);
});
return unsubscribe;
};