diff --git a/frontend/src/landing_page/landing_page_armor/ImpactDashboard.js b/frontend/src/landing_page/landing_page_armor/ImpactDashboard.js index fc5dc8b..43b23fa 100644 --- a/frontend/src/landing_page/landing_page_armor/ImpactDashboard.js +++ b/frontend/src/landing_page/landing_page_armor/ImpactDashboard.js @@ -3,19 +3,22 @@ import React, { useEffect, useRef, useState } from "react"; const ACCENT_YELLOW = "#defe47"; const ACCENT_BLUE = "#28b2fb"; -const stats = [ - { label: "Community Members", value: 2000, suffix: "+" }, - { label: "Cities Represented", value: 30, suffix: "+" }, - { label: "Events Hosted", value: 50, suffix: "+" }, - { label: "AI Agents in Gallery", value: 50, suffix: "+" }, - { label: "Academy Lectures", value: 10, suffix: "+" }, - { label: "AI Courses Available", value: 20, suffix: "+" }, +const API_KEY = "AIzaSyCjxXVDGAolugKgrTXpJ0HmAjL0lLxLN1E"; +const MEMBERS_SHEET_ID = "1IREd2vCxo7rDGOoDUYtzoywVGLqqUFCsu3qGsA0HsMc"; +const MEMBERS_SHEET_NAME = "Sheet-1"; +const CALENDAR_ID = "e88890e803003d95935e56c48dc68aedfd5311e3204360f781830c06287f4f24@group.calendar.google.com"; + +const STATIC_STATS = [ + { key: "cities", label: "Cities Represented", value: 30, suffix: "+" }, + { key: "agents", label: "AI Agents in Gallery", value: 50, suffix: "+" }, + { key: "lectures", label: "Academy Lectures", value: 10, suffix: "+" }, + { key: "courses", label: "AI Courses Available", value: 20, suffix: "+" }, ]; function useCountUp(target, duration, start) { const [count, setCount] = useState(0); useEffect(() => { - if (!start) return; + if (!start || !target) return; let startTime = null; const step = (timestamp) => { if (!startTime) startTime = timestamp; @@ -39,8 +42,7 @@ function StatCard({ label, value, suffix, animate }) { }} >
- {animate ? count : 0} - {suffix} + {animate ? count : 0}{suffix}
{label}
@@ -50,34 +52,91 @@ function StatCard({ label, value, suffix, animate }) { export default function ImpactDashboard() { const ref = useRef(null); const [animate, setAnimate] = useState(false); + const [memberCount, setMemberCount] = useState(2000); + const [eventCount, setEventCount] = useState(50); + // Live member count from Google Sheets + useEffect(() => { + const url = `https://sheets.googleapis.com/v4/spreadsheets/${MEMBERS_SHEET_ID}/values/${encodeURIComponent(MEMBERS_SHEET_NAME)}?key=${API_KEY}`; + fetch(url) + .then((r) => r.json()) + .then((data) => { + if (data.values && data.values.length > 1) { + setMemberCount(data.values.length - 1); // subtract header row + } + }) + .catch(() => {}); + }, []); + + // Live event count from Google Calendar + useEffect(() => { + const url = + `https://www.googleapis.com/calendar/v3/calendars/${encodeURIComponent(CALENDAR_ID)}/events` + + `?key=${API_KEY}&singleEvents=true&maxResults=250`; + fetch(url) + .then((r) => r.json()) + .then((data) => { + if (data.items && data.items.length > 0) { + setEventCount(data.items.length); + } + }) + .catch(() => {}); + }, []); + + // Trigger count-up animation on scroll into view useEffect(() => { const observer = new IntersectionObserver( - ([entry]) => { - if (entry.isIntersecting) setAnimate(true); - }, + ([entry]) => { if (entry.isIntersecting) setAnimate(true); }, { threshold: 0.2 } ); if (ref.current) observer.observe(ref.current); return () => observer.disconnect(); }, []); + const allStats = [ + { key: "members", label: "Community Members", value: memberCount, suffix: "+" }, + { key: "events", label: "Events Hosted", value: eventCount, suffix: "+" }, + ...STATIC_STATS, + ]; + + const shareText = `Join ${memberCount}+ AI builders at the Anote AI Community — ${eventCount}+ events hosted across 30+ cities. community.anote.ai`; + return (
-
-

- Community Impact -

-

- Growing together across the U.S. -

+
+
+

+ Community Impact +

+

+ Growing together across the U.S. +

+
+
+ + Share on X + + + Share on LinkedIn + +
- {stats.map((s) => ( - + {allStats.map((s) => ( + ))}