diff --git a/frontend/src/constants/RouteConstants.js b/frontend/src/constants/RouteConstants.js index d4a86bb..4025a7c 100644 --- a/frontend/src/constants/RouteConstants.js +++ b/frontend/src/constants/RouteConstants.js @@ -139,6 +139,7 @@ export const communityCoffeeChatsPath = `${communityBase}/coffeechats`; export const communityRegionalHubsPath = `${communityBase}/regionalhubs`; export const communityAmbassadorPath = `${communityBase}/ambassador`; export const communityStartChapterPath = `${communityBase}/start-a-chapter`; +export const communityCreateEventPath = `${communityBase}/admin/create-event`; // ── CUSTOMERS BASE ─────────────────────────────────────────────── export const customersBase = "/customers"; diff --git a/frontend/src/landing_page/landing_page_armor/ArmorCoffeeChats.js b/frontend/src/landing_page/landing_page_armor/ArmorCoffeeChats.js index d854ba2..c3e061f 100644 --- a/frontend/src/landing_page/landing_page_armor/ArmorCoffeeChats.js +++ b/frontend/src/landing_page/landing_page_armor/ArmorCoffeeChats.js @@ -3,7 +3,7 @@ import { FaEnvelope, FaLinkedin } from "react-icons/fa"; import SEO from "../../util/SEO"; const SHEET_ID = "1Tr9-EvVLRroabQN7r5Xdu1W9gGKve4_WF4Lp8mZcEU4"; -const API_KEY = "AIzaSyAgE4vhIZ-PR4XuGVRd8PZpyRFMfXIjNFM"; +const API_KEY = "AIzaSyCjxXVDGAolugKgrTXpJ0HmAjL0lLxLN1E"; const SHEET_NAME = "Anote Alumni For Coffee Chats"; export default function ArmorCoffeeChats() { diff --git a/frontend/src/landing_page/landing_page_armor/ArmorEvents.js b/frontend/src/landing_page/landing_page_armor/ArmorEvents.js index a1c9935..7733a4c 100644 --- a/frontend/src/landing_page/landing_page_armor/ArmorEvents.js +++ b/frontend/src/landing_page/landing_page_armor/ArmorEvents.js @@ -44,6 +44,24 @@ import { BrowserRouter, } from "react-router-dom"; +// ─── Google Calendar live feed ─────────────────────────────────────────────── +// 1. Create a Google Calendar for Anote events and make it public: +// calendar.google.com → three-dot menu → Settings → Share → "Make available to public" +// 2. Copy the Calendar ID: +// Settings → Integrate calendar → Calendar ID +// 3. Ensure the Google Calendar API is enabled for this project's API key in Google Cloud Console. +const GCAL_ID = "e88890e803003d95935e56c48dc68aedfd5311e3204360f781830c06287f4f24@group.calendar.google.com"; +const GCAL_API_KEY = "AIzaSyCjxXVDGAolugKgrTXpJ0HmAjL0lLxLN1E"; + +// For calendar events that also have a dedicated community page, map event title +// → internal route + image. Events not listed here link to the Google Calendar page. +const EVENT_ROUTE_MAP = { + "Anote World Cup Finals Watch Party": { + path: worldCupPartyPath, + image: "/events_images/worldcup.png", + }, +}; + const eventsData = [ // { // path: feb2026Path, @@ -268,8 +286,61 @@ const eventsData = [ } ]; +function formatDisplayDate(isoString) { + const d = new Date(isoString); + return d.toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" }); +} + +function parseCalendarEvent(gcalEvent) { + const startISO = gcalEvent.start?.dateTime || gcalEvent.start?.date; + const endISO = gcalEvent.end?.dateTime || gcalEvent.end?.date; + const title = gcalEvent.summary || "Untitled Event"; + const override = EVENT_ROUTE_MAP[title] || {}; + + // Support an optional "image: /path.png" first line in the calendar description. + let rawDesc = gcalEvent.description || ""; + let image = override.image || "/events_images/aiday.png"; + const imageMatch = rawDesc.match(/^image:\s*(\S+)\s*\n?/i); + if (imageMatch) { + image = imageMatch[1]; + rawDesc = rawDesc.replace(imageMatch[0], "").trim(); + } + + return { + title, + date: formatDisplayDate(startISO), + description: rawDesc || title, + startISO, + endISO, + location: gcalEvent.location || "", + image, + path: override.path || gcalEvent.htmlLink, + external: !override.path, + fromCalendar: true, + }; +} + const ArmorEvents = () => { const navigate = useNavigate(); + const [calendarEvents, setCalendarEvents] = useState([]); + + useEffect(() => { + if (GCAL_ID === "REPLACE_WITH_YOUR_CALENDAR_ID") return; + const now = new Date().toISOString(); + const url = + `https://www.googleapis.com/calendar/v3/calendars/${encodeURIComponent(GCAL_ID)}/events` + + `?key=${GCAL_API_KEY}&singleEvents=true&orderBy=startTime&timeMin=${now}&maxResults=20`; + + fetch(url) + .then((r) => r.json()) + .then((data) => { + if (data.items) { + setCalendarEvents(data.items.map(parseCalendarEvent)); + } + }) + .catch(() => {}); // silently fall back to hardcoded list + }, []); + const getToday = () => { const now = new Date(); return new Date(now.getFullYear(), now.getMonth(), now.getDate()); @@ -296,7 +367,14 @@ const ArmorEvents = () => { // .map(event => ({ ...event, dateObject: parseDate(event.date) })) // .sort((a, b) => a.dateObject - b.dateObject); - const sortedEvents = eventsData + // Merge live calendar events with hardcoded list. + // Calendar events take precedence; deduplicate by title so the World Cup + // Party (which is hardcoded AND may appear in the calendar) shows only once. + const calendarTitles = new Set(calendarEvents.map((e) => e.title)); + const dedupedStatic = eventsData.filter((e) => !calendarTitles.has(e.title)); + const mergedEvents = [...calendarEvents, ...dedupedStatic]; + + const sortedEvents = mergedEvents .map(event => ({ ...event, dateObject: parseDate(event.date) })) .sort((a, b) => b.dateObject - a.dateObject); @@ -305,6 +383,7 @@ const ArmorEvents = () => { const [query, setQuery] = useState(""); const [filterType, setFilterType] = useState("all"); + const [viewMode, setViewMode] = useState("cards"); // "cards" | "calendar" const applyFilter = (ev) => { @@ -330,18 +409,19 @@ const ArmorEvents = () => { path="/community/events" />
- {/* Tabs */} -
- {[ + {/* Toolbar: filter tabs + view toggle */} +
+
+ {[ { label: "All", value: "all" }, { label: "Upcoming", value: "upcoming" }, { label: "Past", value: "past" }, ].map(({ label, value }) => ( - ))} +
+
- {/* setQuery(e.target.value)} - className="w-full sm:w-64 px-4 py-2 rounded-md bg-gray-800 border border-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500" - /> */} -
+ + {/* Google Calendar embed */} + {viewMode === "calendar" && ( +
+