diff --git a/package-lock.json b/package-lock.json
index 274f82a..e285cd3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -806,6 +806,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz",
"integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==",
+ "license": "MIT",
"peerDependencies": {
"react": ">= 16 || ^19.0.0-rc"
}
diff --git a/src/components/dashboard/Dashboard.tsx b/src/components/dashboard/Dashboard.tsx
index 39a8614..8e07cbf 100644
--- a/src/components/dashboard/Dashboard.tsx
+++ b/src/components/dashboard/Dashboard.tsx
@@ -11,6 +11,7 @@ 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 { ActivityIcon, getActivityIconConfig } from "@/utils/activityIcons";
type SortOption = "newest" | "oldest" | "highest_impact" | "lowest_impact";
@@ -38,12 +39,13 @@ function StatCard({ title, value, change, icon, color }: StatCardProps) {
{value}
{change !== undefined && (
0
+ className={`text-sm mt-1 ${
+ change > 0
? "text-red-600"
: change < 0
- ? "text-green-600"
- : "text-gray-600"
- }`}
+ ? "text-green-600"
+ : "text-gray-600"
+ }`}
>
{change > 0 ? "↗" : change < 0 ? "↘" : "→"}{" "}
{Math.abs(change).toFixed(1)}% from last week
@@ -322,14 +324,14 @@ export default function Dashboard({
)}
- {/* Recent Activities / Activity History (UPDATED SECTION) */}
+ {/* Recent Activities / Activity History (UPDATED WITH ICONS) */}
{activityHistory.length > 0 && (
Activity History
- {/* NEW: Sort Dropdown UI */}
+ {/* Sort Dropdown UI */}
Sort by:
@@ -344,38 +346,77 @@ export default function Dashboard({
))}
- {/* Custom chevron/sort icon */}
- {/* Sorted Activity List */}
+ {/* Sorted Activity List with Icons */}
{activityHistory.map((entry: any) => (
-
-
-
- {/* Using toLocaleString for better date/time display */}
- {entry.timestamp.toLocaleString()}
-
-
- +{formatCO2Amount(entry.result.totalCO2)}
+
+
+
+ {entry.timestamp.toLocaleString('en-US', {
+ weekday: 'short',
+ month: 'short',
+ day: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit'
+ })}
+
+ Total CO₂:
+
+ +{formatCO2Amount(entry.result.totalCO2)}
+
+
+
{Object.entries(entry.activities).map(
- ([activity, value]) =>
- (value as number) > 0 ? (
-
{
+ if ((value as number) <= 0) return null;
+
+ // Map activity input names to ActivityType
+ const activityType =
+ activity === 'streamingHours' ? 'streaming' :
+ activity === 'codingHours' ? 'coding' :
+ activity === 'videoCallHours' ? 'video_calls' :
+ activity === 'cloudStorageGB' ? 'cloud_storage' :
+ activity === 'gamingHours' ? 'gaming' :
+ activity === 'socialMediaHours' ? 'social_media' :
+ 'emails';
+
+ const config = getActivityIconConfig(activityType as ActivityType);
+
+ return (
+
- {activity}: {value as number}
-
- ) : null
+
+
+ {activity.replace(/Hours|GB/, '')}: {value as number}
+ {activity.includes('Hours') ? 'h' :
+ activity.includes('GB') ? 'GB' : ''}
+
+
+ );
+ }
)}
diff --git a/src/components/forms/ActivityForm.tsx b/src/components/forms/ActivityForm.tsx
index 48684d4..5bcde20 100644
--- a/src/components/forms/ActivityForm.tsx
+++ b/src/components/forms/ActivityForm.tsx
@@ -4,6 +4,7 @@ import { useState } from 'react';
import { ActivityInput } from '@/types';
import { calculateCarbonFootprint } from '@/lib/calculations/carbonFootprint';
import { ACTIVITY_LABELS, ACTIVITY_DESCRIPTIONS } from '@/constants/co2Factors';
+import { ActivityIcon, getActivityIconConfig } from '@/utils/activityIcons';
interface ActivityFormProps {
onSubmit: (
@@ -13,7 +14,7 @@ interface ActivityFormProps {
breakdown: Record;
equivalents: Array<{ description: string; value: number; unit: string }>;
},
- customToastMessage?: string // <-- Add this optional property
+ customToastMessage?: string
) => void;
initialValues?: Partial;
}
@@ -131,59 +132,59 @@ export default function ActivityForm({ onSubmit, initialValues }: ActivityFormPr
const formFields = [
{
key: 'emails' as keyof ActivityInput,
+ activityType: 'emails' as const,
label: ACTIVITY_LABELS.emails,
description: ACTIVITY_DESCRIPTIONS.emails,
max: 500,
step: 1,
- icon: '📧',
},
{
key: 'streamingHours' as keyof ActivityInput,
+ activityType: 'streaming' as const,
label: ACTIVITY_LABELS.streaming,
description: ACTIVITY_DESCRIPTIONS.streaming,
max: 24,
step: 0.5,
- icon: '📺',
},
{
key: 'codingHours' as keyof ActivityInput,
+ activityType: 'coding' as const,
label: ACTIVITY_LABELS.coding,
description: ACTIVITY_DESCRIPTIONS.coding,
max: 24,
step: 0.5,
- icon: '💻',
},
{
key: 'videoCallHours' as keyof ActivityInput,
+ activityType: 'video_calls' as const,
label: ACTIVITY_LABELS.video_calls,
description: ACTIVITY_DESCRIPTIONS.video_calls,
max: 24,
step: 0.5,
- icon: '📹',
},
{
key: 'cloudStorageGB' as keyof ActivityInput,
+ activityType: 'cloud_storage' as const,
label: ACTIVITY_LABELS.cloud_storage,
description: ACTIVITY_DESCRIPTIONS.cloud_storage,
max: 1000,
step: 1,
- icon: '☁️',
},
{
key: 'gamingHours' as keyof ActivityInput,
+ activityType: 'gaming' as const,
label: ACTIVITY_LABELS.gaming,
description: ACTIVITY_DESCRIPTIONS.gaming,
max: 24,
step: 0.5,
- icon: '🎮',
},
{
key: 'socialMediaHours' as keyof ActivityInput,
+ activityType: 'social_media' as const,
label: ACTIVITY_LABELS.social_media,
description: ACTIVITY_DESCRIPTIONS.social_media,
max: 24,
step: 0.5,
- icon: '📱',
},
];
@@ -197,98 +198,137 @@ export default function ActivityForm({ onSubmit, initialValues }: ActivityFormPr
Enter your digital activities for today to calculate your carbon footprint
+