Skip to content

Commit

Permalink
feat: add events page
Browse files Browse the repository at this point in the history
  • Loading branch information
flmel committed Aug 6, 2024
1 parent c7296a7 commit 4824c13
Show file tree
Hide file tree
Showing 10 changed files with 587 additions and 46 deletions.
9 changes: 9 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,12 @@ NEXT_PUBLIC_SIDEBAR_LAYOUT=true
NEXT_PUBLIC_IDOS_CREATE_ACCOUNT_URL="https://app.fractal.id/authorize?client_id=PXAbBxPErSPMXiKmMYQ3ged8Qxwqg1Px7ymhsuhaGP4&redirect_uri=https%3A%2F%2Fdev.near.org%2Fsettings&response_type=code&scope=contact%3Aread%20verification.uniqueness%3Aread%20verification.uniqueness.details%3Aread%20verification.idos%3Aread%20verification.idos.details%3Aread%20verification.wallet-near%3Aread%20verification.wallet-near.details%3Aread"
# gleap support
NEXT_PUBLIC_GLEAP_SDK_TOKEN=
# EVENTS
NEXT_PUBLIC_GOOGLE_CALENDAR_API_KEY=
NEXT_PUBLIC_LUMA_API_URL="https://api.lu.ma"
NEXT_PUBLIC_LUMA_NEAR_CALENDAR_ID="cal-Nrz4EsmLDjXvjPp"
NEXT_PUBLIC_LUMA_NEAR_AI_CALENDAR_ID="cal-dzvTEx2EC4F2tk8"
NEXT_PUBLIC_LUMA_NEAR_HZN_CALENDAR_ID="cal-BOILOqC74o135WB"
NEXT_PUBLIC_DEVHUB_COMMUNITY_CALENDAR_ID="c_f54ed37fd92327acdc7e4343fe40722ae5797b6c82929ba93e9f3a89c69657ab@group.calendar.google.com"
NEXT_PUBLIC_LUMA_DEVHUB_HACKS_CALENDAR_ID="cal-O0HiPZ7GwczF4x0"
NEXT_PUBLIC_NEAR_TOWN_HALL_CALENDAR_ID="cal-F5SO498BSXZ6BNK"
3 changes: 1 addition & 2 deletions src/components/sidebar-navigation/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,9 @@ export const Sidebar = () => {
</Tooltip>

<Tooltip content="Events" side="right" disabled={tooltipsDisabled}>
<S.NavigationItem $active={false} $type="featured" href="https://near.org/events" target="_blank">
<S.NavigationItem $active={isNavigationItemActive('/events')} $type="featured" href="/events">
<i className="ph-calendar ph-bold" />
<span>Events</span>
<span className="ph-bold ph-arrow-square-out ms-auto outline-none" />
</S.NavigationItem>
</Tooltip>

Expand Down
61 changes: 61 additions & 0 deletions src/hooks/useEvents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useCallback, useEffect, useMemo, useState } from 'react';

import {
devhubCommunityCalendarId,
lumaDevHubHacksCalendarId,
lumaNearAICalendarId,
lumaNearCalendarId,
lumaNearHZNCalendarId,
nearTownHallCalendarId,
} from '@/utils/config';
import { formatEvents, sortEventsByDate } from '@/utils/events';
import type { FormatedEvent } from '@/utils/types';

import { useGoogleEvents } from './useGoogleEvents';
import { useLumaEvents } from './useLumaEvents';
const LIMIT = 6;

export function useEvents() {
const { lumaEvents: mainEvents } = useLumaEvents([lumaNearCalendarId, lumaDevHubHacksCalendarId], 1);
const { lumaEvents: otherLumaEvents } = useLumaEvents(
[lumaNearAICalendarId, lumaNearHZNCalendarId, nearTownHallCalendarId],
10,
);
const { googleEvents } = useGoogleEvents(devhubCommunityCalendarId, 100);

const [lastElements, setLastElements] = useState<FormatedEvent[]>([]);
const [communityEvents, setCommunityEvents] = useState<FormatedEvent[]>([]);
const [allEvents, setAllEvents] = useState<FormatedEvent[]>([]);

const hasMoreEvents = useMemo(
() => communityEvents.length + lastElements.length < allEvents.length,
[communityEvents, lastElements, allEvents],
);

const fetchMore = useCallback(() => {
const skipFrom = communityEvents.length + lastElements.length;
const skipTo = skipFrom + LIMIT;
const nextEvents = allEvents.slice(skipFrom, skipTo);

setCommunityEvents([...communityEvents, ...lastElements]);
setLastElements(nextEvents);
}, [allEvents, communityEvents, lastElements]);

useEffect(() => {
const sortedEvents = sortEventsByDate([...googleEvents, ...otherLumaEvents]);
const formattedEvents = formatEvents(sortedEvents);
setAllEvents(formattedEvents);
setCommunityEvents(formattedEvents.slice(0, LIMIT));
setLastElements([]);
}, [googleEvents, otherLumaEvents]);

const highlightedEvent = mainEvents[0];

return {
highlightedEvent,
communityEvents,
hasMoreEvents,
fetchMore,
lastElements,
};
}
40 changes: 40 additions & 0 deletions src/hooks/useGoogleEvents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useEffect, useMemo, useState } from 'react';

import { fetchGoogleCalendarEvents } from '@/utils/events';
import type { FormatedEvent } from '@/utils/types';

export function useGoogleEvents(calendarId: string, limit = 9) {
const [googleEvents, setGoogleEvents] = useState<FormatedEvent[]>([]);

const startFrom = useMemo(() => {
return new Date().toISOString();
}, []);

const loadData = async () => {
try {
const { items } = await fetchGoogleCalendarEvents(calendarId, startFrom, limit, '');

const formattedEvents = items.map((event) => {
return {
id: event.id,
title: event.summary,
start: event.start.dateTime,
thumbnail: `https://lh3.googleusercontent.com/d/${event.attachments?.[0]?.fileId}=w1000`,
location: '',
url: event.htmlLink,
};
});

setGoogleEvents(formattedEvents);
} catch (error) {
console.log(error);
}
};

useEffect(() => {
loadData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return { googleEvents };
}
58 changes: 58 additions & 0 deletions src/hooks/useLumaEvents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useEffect, useState } from 'react';

import { fetchLumaEvents } from '@/utils/events';
import type { FormatedEvent } from '@/utils/types';

export function useLumaEvents(calendarApiIds: string[], limit = 3) {
const aiEventsUrl = 'https://lu.ma';
const [lumaEvents, setLumaEvents] = useState<FormatedEvent[]>([]);
const [hasMoreEvents, setHasMoreEvents] = useState(false);

useEffect(() => {
const loadData = async () => {
try {
const allEvents = await Promise.all(calendarApiIds.map((id) => fetchLumaEvents(id, limit, 0)));

const combinedEvents = allEvents.flatMap((result) => result.entries);

const sortedEvents = [...combinedEvents]
.sort((a, b) => new Date(a.event.start_at).getTime() - new Date(b.event.start_at).getTime())
.slice(0, limit);

const formattedEvents = sortedEvents.map((item) => {
return {
id: item.event.api_id,
start: item.event.start_at,
location: formatLocation(item.event.geo_address_json ?? item.event.geo_address_info ?? ''),
thumbnail: item.event.cover_url,
title: item.event.name,
url: `${aiEventsUrl}/${item.event.url}`,
};
});

setLumaEvents(formattedEvents);
setHasMoreEvents(combinedEvents.length > limit);
} catch (error) {
console.error(error);
}
};

loadData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(calendarApiIds), limit]);

const formatLocation = (location: any) => {
if (location.city || location.city_state) {
return `${location.city ?? location.city_state}, ${location.country}`;
// Luma API returns "mode" as "obfuscated" when the address is hidden
} else if (location && location?.mode === 'obfuscated') {
return 'Register to See Address';
}
return location.address;
};

return {
lumaEvents,
hasMoreEvents,
};
}
Loading

0 comments on commit 4824c13

Please sign in to comment.