mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-04 11:55:50 +00:00
Compare commits
10 Commits
31ff09c093
...
contentful
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
182b84e84e | ||
|
|
b82afc8ce4 | ||
|
|
85c173a470 | ||
|
|
da63775f3e | ||
|
|
fbf97c74a1 | ||
|
|
d7e558187f | ||
|
|
729065f940 | ||
|
|
8bf7857fb1 | ||
|
|
83df78b748 | ||
|
|
cafb129947 |
@@ -1,25 +1,28 @@
|
|||||||
import { indexPages } from './plugins/index-pages.js';
|
import { indexPages } from './plugins/index-pages.js';
|
||||||
import { codeSamples } from './plugins/code-samples.js';
|
import { codeSamples } from './plugins/code-samples.js';
|
||||||
import { blogPosts } from './plugins/blog-posts.js';
|
import { blogPosts } from './plugins/blog-posts.js';
|
||||||
|
import { eventsContentful } from './plugins/events-contentful.js';
|
||||||
|
|
||||||
export default function customPlugin() {
|
export default function customPlugin() {
|
||||||
const indexPagesInst = indexPages();
|
const indexPagesInst = indexPages();
|
||||||
const codeSamplesInst = codeSamples();
|
const codeSamplesInst = codeSamples();
|
||||||
const blogPostsInst = blogPosts();
|
const blogPostsInst = blogPosts();
|
||||||
|
const eventsContentfulInst = eventsContentful();
|
||||||
|
|
||||||
|
/** @type {import("@redocly/realm/dist/server/plugins/types").LifecyclePluginInstance } */
|
||||||
|
|
||||||
/** @type {import("@redocly/realm/dist/server/plugins/types").PluginInstance } */
|
|
||||||
const pluginInstance = {
|
const pluginInstance = {
|
||||||
processContent: async (content, actions) => {
|
id: 'xrpl',
|
||||||
await indexPagesInst.processContent?.(content, actions);
|
processContent: async (actions, context) => {
|
||||||
await codeSamplesInst.processContent?.(content, actions);
|
await indexPagesInst.processContent?.(actions, context);
|
||||||
await blogPostsInst.processContent?.(content, actions);
|
await codeSamplesInst.processContent?.(actions, context);
|
||||||
|
await blogPostsInst.processContent?.(actions, context);
|
||||||
|
await eventsContentfulInst.processContent?.(actions, context);
|
||||||
},
|
},
|
||||||
afterRoutesCreated: async (content, actions) => {
|
afterRoutesCreated: async (actions, context) => {
|
||||||
await indexPagesInst.afterRoutesCreated?.(content, actions);
|
await indexPagesInst.afterRoutesCreated?.(actions, context);
|
||||||
await codeSamplesInst.afterRoutesCreated?.(content, actions);
|
await codeSamplesInst.afterRoutesCreated?.(actions, context);
|
||||||
await blogPostsInst.afterRoutesCreated?.(content, actions);
|
await blogPostsInst.afterRoutesCreated?.(actions, context);
|
||||||
|
await eventsContentfulInst.afterRoutesCreated?.(actions, context);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
26
@theme/plugins/events-contentful.js
Normal file
26
@theme/plugins/events-contentful.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// @ts-check
|
||||||
|
import path from 'node:path';
|
||||||
|
const EVENTS_SERVER_PROPS_ID = 'contentful-events';
|
||||||
|
|
||||||
|
export function eventsContentful() {
|
||||||
|
/** @type {import("@redocly/realm/dist/server/plugins/types").LifecyclePluginInstance } */
|
||||||
|
const instance = {
|
||||||
|
id: 'events-contentful',
|
||||||
|
processContent: async (actions, { fs }) => {
|
||||||
|
actions.registerServerPropsGetter(EVENTS_SERVER_PROPS_ID, path.join(fs.cwd, 'community/events.server.ts'));
|
||||||
|
},
|
||||||
|
afterRoutesCreated: async (actions, context) => {
|
||||||
|
const routes = [
|
||||||
|
actions.getRouteByFsPath('community/events.page.tsx'),
|
||||||
|
actions.getRouteByFsPath('community/index.page.tsx')
|
||||||
|
];
|
||||||
|
routes.forEach(route => {
|
||||||
|
if (route) {
|
||||||
|
route.serverPropsGetterIds = [...(route.serverPropsGetterIds || []), EVENTS_SERVER_PROPS_ID];
|
||||||
|
console.log('worked for route:', route.fsPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { useState, useMemo } from "react";
|
import { useState, useMemo } from "react";
|
||||||
import { useThemeHooks } from "@redocly/theme/core/hooks";
|
import { useThemeHooks } from "@redocly/theme/core/hooks";
|
||||||
|
|
||||||
const moment = require("moment");
|
const moment = require("moment");
|
||||||
const amaImage = require("../static/img/events/AMAs.png");
|
const amaImage = require("../static/img/events/AMAs.png");
|
||||||
const hackathon = require("../static/img/events/Hackathons.png");
|
const hackathon = require("../static/img/events/Hackathons.png");
|
||||||
@@ -11,6 +12,17 @@ const calls = require("../static/img/events/CommunityCalls.png");
|
|||||||
const brazil = require("../static/img/events/event-meetup-brazil.png");
|
const brazil = require("../static/img/events/event-meetup-brazil.png");
|
||||||
const korea = require("../static/img/events/SouthKoreaMeetup.png");
|
const korea = require("../static/img/events/SouthKoreaMeetup.png");
|
||||||
const infoSession = require("../static/img/events/InfoSessions.png");
|
const infoSession = require("../static/img/events/InfoSessions.png");
|
||||||
|
|
||||||
|
export const imageLookup = {
|
||||||
|
hackathon: require("../static/img/events/Hackathons.png"),
|
||||||
|
meetup: require("../static/img/events/event-meetup-san-diego@2x.jpg"), // Assuming this represents a meetup
|
||||||
|
AMA: require("../static/img/events/AMAs.png"),
|
||||||
|
conference: require("../static/img/events/Conference.png"),
|
||||||
|
"community-call": require("../static/img/events/CommunityCalls.png"),
|
||||||
|
"xrpl-zone": require("../static/img/events/XRPLZone.png"),
|
||||||
|
"info-session": require("../static/img/events/InfoSessions.png"),
|
||||||
|
};
|
||||||
|
|
||||||
export const frontmatter = {
|
export const frontmatter = {
|
||||||
seo: {
|
seo: {
|
||||||
title: "Events",
|
title: "Events",
|
||||||
@@ -20,30 +32,41 @@ export const frontmatter = {
|
|||||||
};
|
};
|
||||||
export const sortEvents = (arr, asc = true) => {
|
export const sortEvents = (arr, asc = true) => {
|
||||||
return arr.sort((a, b) => {
|
return arr.sort((a, b) => {
|
||||||
const dateA = moment(a.end_date, "MMMM D, YYYY");
|
const dateA = moment(a.endDate);
|
||||||
const dateB = moment(b.end_date, "MMMM D, YYYY");
|
const dateB = moment(b.endDate);
|
||||||
return asc ? dateB.diff(dateA) : dateA.diff(dateB); // Returns a negative value if dateA is before dateB, positive if after, and 0 if the same
|
return asc ? dateA.diff(dateB) : dateB.diff(dateA); // Sorting in ascending or descending order
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
function categorizeDates(arr) {
|
function categorizeDates(arr) {
|
||||||
const past = [];
|
const past = [];
|
||||||
const upcoming = [];
|
const upcoming = [];
|
||||||
const today = moment().startOf("day"); // set the time to midnight
|
const today = moment().startOf("day"); // Set the time to midnight
|
||||||
|
|
||||||
arr.forEach((obj) => {
|
arr.forEach((obj) => {
|
||||||
const endDate = moment(obj.end_date, "MMMM D, YYYY"); // parse the 'end_date' string into a moment object
|
const startDate = moment.utc(obj.startDate); // Parse the 'startDate' string into a moment object
|
||||||
if (endDate.isBefore(today)) {
|
const endDate = moment.utc(obj.endDate); // Parse the 'endDate' string into a moment object
|
||||||
obj.type = `${obj.type}-past`;
|
let clone = { ...obj };
|
||||||
past.push(obj);
|
// Determine the date format based on whether startDate and endDate are the same or in the same month
|
||||||
|
if (startDate.isSame(endDate, 'day')) {
|
||||||
|
clone.date = startDate.format("MMMM D, YYYY");
|
||||||
|
} else if (startDate.isSame(endDate, 'month')) {
|
||||||
|
clone.date = `${startDate.format("MMMM D")} - ${endDate.format("D, YYYY")}`;
|
||||||
} else {
|
} else {
|
||||||
obj.type = `${obj.type}-upcoming`;
|
clone.date = `${startDate.format("MMMM D, YYYY")} - ${endDate.format("MMMM D, YYYY")}`;
|
||||||
upcoming.push(obj);
|
}
|
||||||
|
if (endDate.isBefore(today)) {
|
||||||
|
clone.type = obj.category;
|
||||||
|
clone.category = obj.category.map((cat) => `${cat}-past`);
|
||||||
|
past.push(clone);
|
||||||
|
} else {
|
||||||
|
clone.type = obj.category;
|
||||||
|
clone.category = obj.category.map((cat) => `${cat}-upcoming`);
|
||||||
|
upcoming.push(clone);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return { past: sortEvents(past), upcoming: sortEvents(upcoming, false) };
|
return { past: sortEvents(past), upcoming: sortEvents(upcoming, false) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const events = [
|
const events = [
|
||||||
{
|
{
|
||||||
name: "Hackathon: 2021",
|
name: "Hackathon: 2021",
|
||||||
@@ -736,7 +759,7 @@ const events = [
|
|||||||
link: "https://ripple.swoogo.com/xrpl-zone-seoul",
|
link: "https://ripple.swoogo.com/xrpl-zone-seoul",
|
||||||
location: "Seongdong-su, Seoul",
|
location: "Seongdong-su, Seoul",
|
||||||
date: "September 4, 2024",
|
date: "September 4, 2024",
|
||||||
image: require('../static/img/events/event-meetup-zone-day.png'),
|
image: require("../static/img/events/event-meetup-zone-day.png"),
|
||||||
end_date: "September 4, 2024",
|
end_date: "September 4, 2024",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -747,7 +770,7 @@ const events = [
|
|||||||
link: "https://lu.ma/mbg067j3",
|
link: "https://lu.ma/mbg067j3",
|
||||||
location: "Seongdong-su, Seoul",
|
location: "Seongdong-su, Seoul",
|
||||||
date: "September 4, 2024",
|
date: "September 4, 2024",
|
||||||
image: require('../static/img/events/event-meetup-zone-night.png'),
|
image: require("../static/img/events/event-meetup-zone-night.png"),
|
||||||
end_date: "September 4, 2024",
|
end_date: "September 4, 2024",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -791,7 +814,7 @@ const events = [
|
|||||||
link: "https://events.xrplresources.org/toyko-community-2024",
|
link: "https://events.xrplresources.org/toyko-community-2024",
|
||||||
location: "Shinagawa, Tokyo",
|
location: "Shinagawa, Tokyo",
|
||||||
date: "September 6, 2024",
|
date: "September 6, 2024",
|
||||||
image: require('../static/img/events/event-meetup-tokyo-day.png'),
|
image: require("../static/img/events/event-meetup-tokyo-day.png"),
|
||||||
end_date: "September 6, 2024",
|
end_date: "September 6, 2024",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -802,7 +825,7 @@ const events = [
|
|||||||
link: "https://lu.ma/84do37p7",
|
link: "https://lu.ma/84do37p7",
|
||||||
location: "Shinagawa, Tokyo",
|
location: "Shinagawa, Tokyo",
|
||||||
date: "September 6, 2024",
|
date: "September 6, 2024",
|
||||||
image: require('../static/img/events/event-meetup-tokyo-night.png'),
|
image: require("../static/img/events/event-meetup-tokyo-night.png"),
|
||||||
end_date: "September 6, 2024",
|
end_date: "September 6, 2024",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -813,24 +836,24 @@ const events = [
|
|||||||
link: "https://lu.ma/74dulzff",
|
link: "https://lu.ma/74dulzff",
|
||||||
location: "Chicago, IL",
|
location: "Chicago, IL",
|
||||||
date: "September 12, 2024",
|
date: "September 12, 2024",
|
||||||
image: require('../static/img/events/chicago-meetup.png'),
|
image: require("../static/img/events/chicago-meetup.png"),
|
||||||
end_date: "September 12, 2024",
|
end_date: "September 12, 2024",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function Events() {
|
export default function Events({pageProps}) {
|
||||||
|
const {data, errors} = pageProps.contentfulEvents;
|
||||||
const { useTranslate } = useThemeHooks();
|
const { useTranslate } = useThemeHooks();
|
||||||
const { translate } = useTranslate();
|
const { translate } = useTranslate();
|
||||||
const { past, upcoming } = useMemo(() => categorizeDates(events), []);
|
const { past, upcoming } = useMemo(() => categorizeDates(data?.eventsCollection?.items || []), [data]);
|
||||||
|
|
||||||
const [upcomingFilters, setUpcomingFilters] = useState({
|
const [upcomingFilters, setUpcomingFilters] = useState({
|
||||||
conference: true,
|
conference: true,
|
||||||
meetup: true,
|
meetup: true,
|
||||||
hackathon: true,
|
hackathon: true,
|
||||||
ama: true,
|
ama: true,
|
||||||
cc: true,
|
cc: true,
|
||||||
zone: true,
|
zone: true,
|
||||||
"info": true,
|
info: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [pastFilters, setPastFilters] = useState({
|
const [pastFilters, setPastFilters] = useState({
|
||||||
@@ -840,18 +863,18 @@ export default function Events() {
|
|||||||
ama: true,
|
ama: true,
|
||||||
cc: true,
|
cc: true,
|
||||||
zone: true,
|
zone: true,
|
||||||
"info": true,
|
info: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const filteredUpcoming = useMemo(() => {
|
const filteredUpcoming = useMemo(() => {
|
||||||
return upcoming.filter(
|
return upcoming.filter(
|
||||||
(event) => upcomingFilters[event.type.split("-")[0]] !== false
|
(event) => upcomingFilters[event.category[0].split("-")[0]] !== false
|
||||||
);
|
);
|
||||||
}, [upcoming, upcomingFilters]);
|
}, [upcoming, upcomingFilters]);
|
||||||
|
|
||||||
const filteredPast = useMemo(() => {
|
const filteredPast = useMemo(() => {
|
||||||
return past.filter(
|
return past.filter(
|
||||||
(event) => pastFilters[event.type.split("-")[0]] !== false
|
(event) => pastFilters[event.category[0].split("-")[0]] !== false
|
||||||
);
|
);
|
||||||
}, [past, pastFilters]);
|
}, [past, pastFilters]);
|
||||||
|
|
||||||
@@ -862,7 +885,7 @@ export default function Events() {
|
|||||||
[name.replace("-upcoming", "")]: checked,
|
[name.replace("-upcoming", "")]: checked,
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePastFilterChange = (event) => {
|
const handlePastFilterChange = (event) => {
|
||||||
const { name, checked } = event.target;
|
const { name, checked } = event.target;
|
||||||
setPastFilters((prevFilters) => ({
|
setPastFilters((prevFilters) => ({
|
||||||
@@ -870,7 +893,11 @@ export default function Events() {
|
|||||||
[name.replace("-past", "")]: checked,
|
[name.replace("-past", "")]: checked,
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (errors) {
|
||||||
|
return <div style={{color: 'red', padding: '20px'}}>{errors[0]?.message}</div>
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="landing page-events">
|
<div className="landing page-events">
|
||||||
<div>
|
<div>
|
||||||
@@ -967,7 +994,9 @@ export default function Events() {
|
|||||||
checked={upcomingFilters.meetup}
|
checked={upcomingFilters.meetup}
|
||||||
onChange={handleUpcomingFilterChange}
|
onChange={handleUpcomingFilterChange}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="meetup-upcoming">{translate("Meetups")}</label>
|
<label htmlFor="meetup-upcoming">
|
||||||
|
{translate("Meetups")}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-check form-check-inline">
|
<div className="form-check form-check-inline">
|
||||||
<input
|
<input
|
||||||
@@ -1019,7 +1048,9 @@ export default function Events() {
|
|||||||
checked={upcomingFilters.zone}
|
checked={upcomingFilters.zone}
|
||||||
onChange={handleUpcomingFilterChange}
|
onChange={handleUpcomingFilterChange}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="zone-upcoming">{translate("XRPL Zone")}</label>
|
<label htmlFor="zone-upcoming">
|
||||||
|
{translate("XRPL Zone")}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-check form-check-inline">
|
<div className="form-check form-check-inline">
|
||||||
<input
|
<input
|
||||||
@@ -1042,7 +1073,7 @@ export default function Events() {
|
|||||||
{filteredUpcoming.map((event, i) => (
|
{filteredUpcoming.map((event, i) => (
|
||||||
<a
|
<a
|
||||||
key={event.name + i}
|
key={event.name + i}
|
||||||
className={`event-card ${event.type}`}
|
className={`event-card ${event.category[0]}`}
|
||||||
href={event.link}
|
href={event.link}
|
||||||
style={{}}
|
style={{}}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -1050,7 +1081,7 @@ export default function Events() {
|
|||||||
<div
|
<div
|
||||||
className="event-card-header"
|
className="event-card-header"
|
||||||
style={{
|
style={{
|
||||||
background: `url(${event.image}) no-repeat`,
|
background: `url(${event.type.includes('meetup') ? event?.image?.url || imageLookup['meetup'] : imageLookup[event.type[0]]}) no-repeat`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="event-card-title">
|
<div className="event-card-title">
|
||||||
@@ -1143,7 +1174,9 @@ export default function Events() {
|
|||||||
checked={pastFilters.cc}
|
checked={pastFilters.cc}
|
||||||
onChange={handlePastFilterChange}
|
onChange={handlePastFilterChange}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="cc-past">{translate("Community Calls")}</label>
|
<label htmlFor="cc-past">
|
||||||
|
{translate("Community Calls")}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-check form-check-inline">
|
<div className="form-check form-check-inline">
|
||||||
<input
|
<input
|
||||||
@@ -1167,9 +1200,7 @@ export default function Events() {
|
|||||||
checked={pastFilters["info"]}
|
checked={pastFilters["info"]}
|
||||||
onChange={handlePastFilterChange}
|
onChange={handlePastFilterChange}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="info-past">
|
<label htmlFor="info-past">{translate("Info Session")}</label>
|
||||||
{translate("Info Session")}
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1184,7 +1215,7 @@ export default function Events() {
|
|||||||
<div
|
<div
|
||||||
className="event-card-header"
|
className="event-card-header"
|
||||||
style={{
|
style={{
|
||||||
background: `url(${event.image}) no-repeat`,
|
background: `url(${event.type.includes('meetup') ? event?.image?.url || imageLookup['meetup'] : imageLookup[event.type[0]]}) no-repeat`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="event-card-title">
|
<div className="event-card-title">
|
||||||
@@ -1208,3 +1239,4 @@ export default function Events() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
55
community/events.server.ts
Normal file
55
community/events.server.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import type { PageRouteDetails } from '@redocly/realm/dist/server/plugins/types';
|
||||||
|
|
||||||
|
const cache = {
|
||||||
|
response: null,
|
||||||
|
expiresAt: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
async function fetchGql(query: string) {
|
||||||
|
return fetch(`https://graphql.contentful.com/content/v1/spaces/${process.env.PUBLIC_CONTENTFUL_SPACE_ID}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${process.env.CONTENTFUL_ACCESS_TOKEN}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ query, variables: {}, operationName: 'GetEvents' }),
|
||||||
|
}).then(res => res.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
const GET_EVENTS = `
|
||||||
|
query GetEvents {
|
||||||
|
eventsCollection(order: startDate_ASC) {
|
||||||
|
items {
|
||||||
|
_id
|
||||||
|
name
|
||||||
|
description
|
||||||
|
category
|
||||||
|
link
|
||||||
|
location
|
||||||
|
startDate
|
||||||
|
endDate
|
||||||
|
community
|
||||||
|
image {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
|
||||||
|
export default async function getServerProps(route: PageRouteDetails, data: { props: any }) {
|
||||||
|
try {
|
||||||
|
if (cache.expiresAt <= Date.now()) {
|
||||||
|
cache.response = await fetchGql(GET_EVENTS);
|
||||||
|
cache.expiresAt = Date.now() + 1000 * 60 * 1; // 5 minutes naive cache
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to fetch events', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...data.props,
|
||||||
|
contentfulEvents: cache.response,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import React, { useState } from "react";
|
|||||||
import { useThemeHooks } from "@redocly/theme/core/hooks";
|
import { useThemeHooks } from "@redocly/theme/core/hooks";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { Link } from "@redocly/theme/components/Link/Link";
|
import { Link } from "@redocly/theme/components/Link/Link";
|
||||||
|
import { imageLookup } from "./events.page";
|
||||||
|
|
||||||
const infoSession = require("../static/img/events/InfoSessions.png");
|
const infoSession = require("../static/img/events/InfoSessions.png");
|
||||||
|
|
||||||
@@ -22,253 +23,271 @@ const findNearestUpcomingEvent = (events) => {
|
|||||||
let nearestEvent = null;
|
let nearestEvent = null;
|
||||||
let nearestDateDiff = Infinity;
|
let nearestDateDiff = Infinity;
|
||||||
let index;
|
let index;
|
||||||
events.forEach((event, i) => {
|
let eventsClone = [];
|
||||||
const eventStartDate = moment(event.start_date, "MMMM DD, YYYY");
|
events?.forEach((event, i) => {
|
||||||
|
const startDate = moment.utc(event.startDate); // Use the updated key `startDate`
|
||||||
|
const endDate = moment.utc(event.endDate); // Parse the 'endDate' string into a moment object
|
||||||
const currentDate = moment();
|
const currentDate = moment();
|
||||||
const diff = eventStartDate.diff(currentDate, "days");
|
const diff = startDate.diff(currentDate, "days");
|
||||||
|
let clone = { ...event };
|
||||||
if (diff >= 0 && diff < nearestDateDiff) {
|
// Determine the date format based on whether startDate and endDate are the same or in the same month
|
||||||
nearestEvent = event;
|
if (startDate.isSame(endDate, "day")) {
|
||||||
nearestDateDiff = diff;
|
clone.date = startDate.format("MMMM D, YYYY");
|
||||||
index = i
|
} else if (startDate.isSame(endDate, "month")) {
|
||||||
|
clone.date = `${startDate.format("MMMM D")} - ${endDate.format(
|
||||||
|
"D, YYYY"
|
||||||
|
)}`;
|
||||||
|
} else {
|
||||||
|
clone.date = `${startDate.format("MMMM D, YYYY")} - ${endDate.format(
|
||||||
|
"MMMM D, YYYY"
|
||||||
|
)}`;
|
||||||
}
|
}
|
||||||
|
if (diff >= 0 && diff < nearestDateDiff) {
|
||||||
|
nearestEvent = clone;
|
||||||
|
nearestDateDiff = diff;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
eventsClone.push(clone);
|
||||||
});
|
});
|
||||||
|
|
||||||
return { nearestEvent, nearestDateDiff, index };
|
return { nearestEvent, nearestDateDiff, index, events: eventsClone };
|
||||||
};
|
};
|
||||||
|
|
||||||
const events = [
|
// const events = [
|
||||||
{
|
// {
|
||||||
name: "New Horizon: Innovate Without Limits: New Horizons Await",
|
// name: "New Horizon: Innovate Without Limits: New Horizons Await",
|
||||||
description:
|
// description:
|
||||||
"Join our EVM-compatible chain launch for a chance to win $50,000 in prizes! Unleash your creativity in DeFi and NFTs, with judging criteria focused on novelty, impact, and community engagement.",
|
// "Join our EVM-compatible chain launch for a chance to win $50,000 in prizes! Unleash your creativity in DeFi and NFTs, with judging criteria focused on novelty, impact, and community engagement.",
|
||||||
type: "hackathon",
|
// type: "hackathon",
|
||||||
link: "https://newhorizon.devpost.com/",
|
// link: "https://newhorizon.devpost.com/",
|
||||||
location: "Virtual",
|
// location: "Virtual",
|
||||||
date: "October 19, 2023 - December 22, 2023",
|
// date: "October 19, 2023 - December 22, 2023",
|
||||||
image: hackathon,
|
// image: hackathon,
|
||||||
end_date: "December 22, 2023",
|
// end_date: "December 22, 2023",
|
||||||
start_date: "October 19, 2023",
|
// start_date: "October 19, 2023",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "XRPL Community Report Launch Party",
|
// name: "XRPL Community Report Launch Party",
|
||||||
description:
|
// description:
|
||||||
"Celebrate the XRPL Community Report launch at 7pm! Join blockchain enthusiasts, connect with experts, and discover opportunities in the XRP Ledger ecosystem. Limited space available, so register now for a night of celebration and networking!",
|
// "Celebrate the XRPL Community Report launch at 7pm! Join blockchain enthusiasts, connect with experts, and discover opportunities in the XRP Ledger ecosystem. Limited space available, so register now for a night of celebration and networking!",
|
||||||
type: "meetup",
|
// type: "meetup",
|
||||||
link: "https://www.eventbrite.fr/e/billets-xrpl-community-report-launch-party-753788370307",
|
// link: "https://www.eventbrite.fr/e/billets-xrpl-community-report-launch-party-753788370307",
|
||||||
location: "Paris, France",
|
// location: "Paris, France",
|
||||||
date: "November 28, 7pm - 9pm",
|
// date: "November 28, 7pm - 9pm",
|
||||||
image: require("../static/img/events/paris.png"),
|
// image: require("../static/img/events/paris.png"),
|
||||||
end_date: "November 28, 2023",
|
// end_date: "November 28, 2023",
|
||||||
start_date: "November 28, 2023",
|
// start_date: "November 28, 2023",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "XRPL Grants Info Session: Decentralized Exchange (DEX) Focused",
|
// name: "XRPL Grants Info Session: Decentralized Exchange (DEX) Focused",
|
||||||
description:
|
// description:
|
||||||
"Watch the recorded information session and Q&A on applying to XRPL Grants Wave 7. This session will provide a general overview of the XRPL Grants application for Wave 7, with a focus on Decentralized Exchange (DEX) projects.",
|
// "Watch the recorded information session and Q&A on applying to XRPL Grants Wave 7. This session will provide a general overview of the XRPL Grants application for Wave 7, with a focus on Decentralized Exchange (DEX) projects.",
|
||||||
type: "info-session",
|
// type: "info-session",
|
||||||
link: "https://www.youtube.com/watch?v=BbGu0QC5WEE",
|
// link: "https://www.youtube.com/watch?v=BbGu0QC5WEE",
|
||||||
location: "Virtual - Zoom",
|
// location: "Virtual - Zoom",
|
||||||
date: "September 06, 2023",
|
// date: "September 06, 2023",
|
||||||
image: infoSession,
|
// image: infoSession,
|
||||||
end_date: "September 06, 2023",
|
// end_date: "September 06, 2023",
|
||||||
start_date: "September 06, 2023",
|
// start_date: "September 06, 2023",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "XRPL Developers Reddit AMA: Real World Assets",
|
// name: "XRPL Developers Reddit AMA: Real World Assets",
|
||||||
description:
|
// description:
|
||||||
"Join us for a live chat on Reddit and learn more about how developers are building real world assets with confidence on the XRP Ledger.",
|
// "Join us for a live chat on Reddit and learn more about how developers are building real world assets with confidence on the XRP Ledger.",
|
||||||
type: "ama",
|
// type: "ama",
|
||||||
link: "https://xrplresources.org/rwa-ama?utm_source=web&utm_medium=web&utm_campaign=bwc",
|
// link: "https://xrplresources.org/rwa-ama?utm_source=web&utm_medium=web&utm_campaign=bwc",
|
||||||
location: "Virtual - Reddit",
|
// location: "Virtual - Reddit",
|
||||||
date: "October 17, 2023",
|
// date: "October 17, 2023",
|
||||||
image: amaImage,
|
// image: amaImage,
|
||||||
end_date: "October 17, 2023",
|
// end_date: "October 17, 2023",
|
||||||
start_date: "October 17, 2023",
|
// start_date: "October 17, 2023",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "XRP Ledger Zone ETHDenver",
|
// name: "XRP Ledger Zone ETHDenver",
|
||||||
description:
|
// description:
|
||||||
"XRPL Zone: your all-in-one location for creating and collaborating on XRP Ledger (XRPL) projects. Details coming soon!",
|
// "XRPL Zone: your all-in-one location for creating and collaborating on XRP Ledger (XRPL) projects. Details coming soon!",
|
||||||
type: "zone",
|
// type: "zone",
|
||||||
link: "http://xrplzone-ethdenver.splashthat.com",
|
// link: "http://xrplzone-ethdenver.splashthat.com",
|
||||||
location: "Denver, Colorado",
|
// location: "Denver, Colorado",
|
||||||
date: "February 27, 2024",
|
// date: "February 27, 2024",
|
||||||
image: zone,
|
// image: zone,
|
||||||
end_date: "February 27, 2024",
|
// end_date: "February 27, 2024",
|
||||||
start_date: "February 27, 2024",
|
// start_date: "February 27, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "XRPL Developers Discord AMA: Apex 2024",
|
// name: "XRPL Developers Discord AMA: Apex 2024",
|
||||||
description:
|
// description:
|
||||||
"Join the DevRel team at Ripple to learn more about APEX 2024.",
|
// "Join the DevRel team at Ripple to learn more about APEX 2024.",
|
||||||
type: "ama",
|
// type: "ama",
|
||||||
link: "https://discord.gg/gszzRTxV?event=1215341725825110089",
|
// link: "https://discord.gg/gszzRTxV?event=1215341725825110089",
|
||||||
location: "XRPL Developers Discord",
|
// location: "XRPL Developers Discord",
|
||||||
date: "March 13, 2024 13:00 EST",
|
// date: "March 13, 2024 13:00 EST",
|
||||||
image: amaImage,
|
// image: amaImage,
|
||||||
start_date: "March 13, 2024",
|
// start_date: "March 13, 2024",
|
||||||
end_date: "March 13, 2024",
|
// end_date: "March 13, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "Paris Blockchain Week",
|
// name: "Paris Blockchain Week",
|
||||||
description:
|
// description:
|
||||||
"Paris Blockchain Week is Europe's biggest blockchain & digital assets event that covers all aspects of blockchain technology.",
|
// "Paris Blockchain Week is Europe's biggest blockchain & digital assets event that covers all aspects of blockchain technology.",
|
||||||
type: "conference",
|
// type: "conference",
|
||||||
link: "https://www.parisblockchainweek.com/",
|
// link: "https://www.parisblockchainweek.com/",
|
||||||
location: "Paris, France",
|
// location: "Paris, France",
|
||||||
date: "April 9 - 12, 2024",
|
// date: "April 9 - 12, 2024",
|
||||||
image: conference,
|
// image: conference,
|
||||||
end_date: "April 12, 2024",
|
// end_date: "April 12, 2024",
|
||||||
start_date: "April 9, 2024",
|
// start_date: "April 9, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "Consensus",
|
// name: "Consensus",
|
||||||
description:
|
// description:
|
||||||
"Join us at Consensus! This event is the world's largest, longest-running and most influential gathering that brings together all sides of the cryptocurrency, blockchain and Web3 community.",
|
// "Join us at Consensus! This event is the world's largest, longest-running and most influential gathering that brings together all sides of the cryptocurrency, blockchain and Web3 community.",
|
||||||
type: "conference",
|
// type: "conference",
|
||||||
link: "https://consensus.coindesk.com/?utm_campaign=&utm_content=c24&utm_medium=sponsored&utm_source=XRPLEventsPage%20&utm_term=organic",
|
// link: "https://consensus.coindesk.com/?utm_campaign=&utm_content=c24&utm_medium=sponsored&utm_source=XRPLEventsPage%20&utm_term=organic",
|
||||||
location: "Austin, Texas",
|
// location: "Austin, Texas",
|
||||||
date: "May 29 - June 1, 2024",
|
// date: "May 29 - June 1, 2024",
|
||||||
image: conference,
|
// image: conference,
|
||||||
end_date: "June 1, 2024",
|
// end_date: "June 1, 2024",
|
||||||
start_date: "May 29, 2024",
|
// start_date: "May 29, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "EasyA Ripple Hackathon",
|
// name: "EasyA Ripple Hackathon",
|
||||||
description:
|
// description:
|
||||||
"Join the XRPL community at the Ripple x EasyA Hackathon in Amsterdam, where startups can compete for a $20,000 prize and a chance to present at the prestigious APEX Conference alongside industry leaders. Secure your spot now! ",
|
// "Join the XRPL community at the Ripple x EasyA Hackathon in Amsterdam, where startups can compete for a $20,000 prize and a chance to present at the prestigious APEX Conference alongside industry leaders. Secure your spot now! ",
|
||||||
type: "hackathon",
|
// type: "hackathon",
|
||||||
link: "https://www.eventbrite.co.uk/e/easya-x-ripple-apex-hackathon-win-20000-tickets-882724261027?aff=oddtdtcreator",
|
// link: "https://www.eventbrite.co.uk/e/easya-x-ripple-apex-hackathon-win-20000-tickets-882724261027?aff=oddtdtcreator",
|
||||||
location: "Amsterdam",
|
// location: "Amsterdam",
|
||||||
date: "June 8 - 9, 2024",
|
// date: "June 8 - 9, 2024",
|
||||||
image: hackathon,
|
// image: hackathon,
|
||||||
start_date: "June 8, 2024",
|
// start_date: "June 8, 2024",
|
||||||
end_date: "June 9, 2024",
|
// end_date: "June 9, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "APEX 2024: The XRPL Developer Summit",
|
// name: "APEX 2024: The XRPL Developer Summit",
|
||||||
description:
|
// description:
|
||||||
"Apex XRPL Developer Summit is the annual event where developers, contributors, and thought leaders come together to learn, build, share, network, and celebrate all things XRP Ledger.",
|
// "Apex XRPL Developer Summit is the annual event where developers, contributors, and thought leaders come together to learn, build, share, network, and celebrate all things XRP Ledger.",
|
||||||
type: "conference",
|
// type: "conference",
|
||||||
link: "http://apexdevsummit.com",
|
// link: "http://apexdevsummit.com",
|
||||||
location: "Amsterdam",
|
// location: "Amsterdam",
|
||||||
date: "June 11 - 13, 2024",
|
// date: "June 11 - 13, 2024",
|
||||||
image: conference,
|
// image: conference,
|
||||||
end_date: "June 13, 2024",
|
// end_date: "June 13, 2024",
|
||||||
start_date: "June 11, 2024",
|
// start_date: "June 11, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "SwissHacks",
|
// name: "SwissHacks",
|
||||||
description:
|
// description:
|
||||||
"Transform Fintech with XRPL at SwissHacks 2024! Prototype and collaborate with fellow builders to reinvent finance for a brighter future",
|
// "Transform Fintech with XRPL at SwissHacks 2024! Prototype and collaborate with fellow builders to reinvent finance for a brighter future",
|
||||||
type: "hackathon",
|
// type: "hackathon",
|
||||||
link: "https://airtable.com/app61tk91vkuwKhGx/pagCN29Br8RdxTvp7/form",
|
// link: "https://airtable.com/app61tk91vkuwKhGx/pagCN29Br8RdxTvp7/form",
|
||||||
location: "Zurich",
|
// location: "Zurich",
|
||||||
date: "June 28 - 30, 2024",
|
// date: "June 28 - 30, 2024",
|
||||||
image: hackathon,
|
// image: hackathon,
|
||||||
start_date: "June 28, 2024",
|
// start_date: "June 28, 2024",
|
||||||
end_date: "June 30, 2024",
|
// end_date: "June 30, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "XRPL Meetup Blockchain Rio",
|
// name: "XRPL Meetup Blockchain Rio",
|
||||||
description:
|
// description:
|
||||||
"Get ready to kick off Blockchain Rio with a bang at the XRP Ledger Dev Meetup! Hosted by the the XRP Ledger team, this warm-up event is the perfect chance for devs and builders to connect, share ideas, and get hyped for the main event. Expect a night filled with great conversations, delicious drinks, and the vibrant energy of Rio de Janeiro. Don't miss out on this fantastic opportunity to network and have a blast with fellow tech enthusiasts. See you there!",
|
// "Get ready to kick off Blockchain Rio with a bang at the XRP Ledger Dev Meetup! Hosted by the the XRP Ledger team, this warm-up event is the perfect chance for devs and builders to connect, share ideas, and get hyped for the main event. Expect a night filled with great conversations, delicious drinks, and the vibrant energy of Rio de Janeiro. Don't miss out on this fantastic opportunity to network and have a blast with fellow tech enthusiasts. See you there!",
|
||||||
type: "meetup",
|
// type: "meetup",
|
||||||
link: "https://lu.ma/4uxpkd11",
|
// link: "https://lu.ma/4uxpkd11",
|
||||||
location: "Rio de Janeiro",
|
// location: "Rio de Janeiro",
|
||||||
date: "July 23, 2024",
|
// date: "July 23, 2024",
|
||||||
image: brazil,
|
// image: brazil,
|
||||||
start_date: "July 23, 2024",
|
// start_date: "July 23, 2024",
|
||||||
end_date: "July 23, 2024",
|
// end_date: "July 23, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "XRPL Builder Office Hours",
|
// name: "XRPL Builder Office Hours",
|
||||||
description:
|
// description:
|
||||||
"XRPL Builder Office Hours is an open forum hosted monthly by Developer Advocates to answer technical and business questions from community members.",
|
// "XRPL Builder Office Hours is an open forum hosted monthly by Developer Advocates to answer technical and business questions from community members.",
|
||||||
type: "info-session",
|
// type: "info-session",
|
||||||
link: "https://ripple.zoom.us/meeting/register/tJMscOCsrDoiHNUN6hZLpFVR69OcfG9rXtIA#/registration",
|
// link: "https://ripple.zoom.us/meeting/register/tJMscOCsrDoiHNUN6hZLpFVR69OcfG9rXtIA#/registration",
|
||||||
location: "Virtual - Zoom",
|
// location: "Virtual - Zoom",
|
||||||
date: "August 23, 2024",
|
// date: "August 23, 2024",
|
||||||
image: infoSession,
|
// image: infoSession,
|
||||||
start_date: "August 23, 2024",
|
// start_date: "August 23, 2024",
|
||||||
end_date: "August 23, 2024",
|
// end_date: "August 23, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "XRP Ledger Hackathon Seoul 2024",
|
// name: "XRP Ledger Hackathon Seoul 2024",
|
||||||
description:
|
// description:
|
||||||
"Calling all developers in Korea or attending Korea Blockchain Week! Join us for an exclusive pre-KBW meetup in Gangnam, Seoul! Be part of an exciting opportunity to collaborate with fellow builders leveraging the XRP Ledger. Don’t miss this chance to connect with industry peers, explore local funding initiatives, and fuel your projects with new insights just before the main KBW event!",
|
// "Calling all developers in Korea or attending Korea Blockchain Week! Join us for an exclusive pre-KBW meetup in Gangnam, Seoul! Be part of an exciting opportunity to collaborate with fellow builders leveraging the XRP Ledger. Don’t miss this chance to connect with industry peers, explore local funding initiatives, and fuel your projects with new insights just before the main KBW event!",
|
||||||
type: "hackathon",
|
// type: "hackathon",
|
||||||
link: "https://lu.ma/1viq6evg",
|
// link: "https://lu.ma/1viq6evg",
|
||||||
location: "Seoul, South Korea",
|
// location: "Seoul, South Korea",
|
||||||
date: "August 31 - September 1, 2024",
|
// date: "August 31 - September 1, 2024",
|
||||||
image: hackathon,
|
// image: hackathon,
|
||||||
start_date: "August 31, 2024",
|
// start_date: "August 31, 2024",
|
||||||
end_date: "September 1, 2024",
|
// end_date: "September 1, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "XRPL Zone Seoul",
|
// name: "XRPL Zone Seoul",
|
||||||
description:
|
// description:
|
||||||
"Join us at XRPL Zone Seoul where developers, corporates, fintechs, banks, VCs, academia, and the XRP community come together under one roof for the biggest XRPL event in South Korea!",
|
// "Join us at XRPL Zone Seoul where developers, corporates, fintechs, banks, VCs, academia, and the XRP community come together under one roof for the biggest XRPL event in South Korea!",
|
||||||
type: "zone",
|
// type: "zone",
|
||||||
link: "https://ripple.swoogo.com/xrpl-zone-seoul",
|
// link: "https://ripple.swoogo.com/xrpl-zone-seoul",
|
||||||
location: "Seongdong-su, Seoul",
|
// location: "Seongdong-su, Seoul",
|
||||||
date: "September 4, 2024",
|
// date: "September 4, 2024",
|
||||||
image: require('../static/img/events/event-meetup-zone-day.png'),
|
// image: require("../static/img/events/event-meetup-zone-day.png"),
|
||||||
start_date: "September 4, 2024",
|
// start_date: "September 4, 2024",
|
||||||
end_date: "September 4, 2024",
|
// end_date: "September 4, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "XRPL Zone Seoul After Hours",
|
// name: "XRPL Zone Seoul After Hours",
|
||||||
description:
|
// description:
|
||||||
"Celebrate with the XRP Community during Korea Blockchain Week! Don't miss this opportunity to mingle with the vibrant XRP community, visionary XRPL developers, trailblazing innovators, and influential investors.",
|
// "Celebrate with the XRP Community during Korea Blockchain Week! Don't miss this opportunity to mingle with the vibrant XRP community, visionary XRPL developers, trailblazing innovators, and influential investors.",
|
||||||
type: "meetup",
|
// type: "meetup",
|
||||||
link: "https://lu.ma/mbg067j3",
|
// link: "https://lu.ma/mbg067j3",
|
||||||
location: "Seongdong-su, Seoul",
|
// location: "Seongdong-su, Seoul",
|
||||||
date: "September 4, 2024",
|
// date: "September 4, 2024",
|
||||||
image: require('../static/img/events/event-meetup-zone-night.png'),
|
// image: require("../static/img/events/event-meetup-zone-night.png"),
|
||||||
start_date: "September 4, 2024",
|
// start_date: "September 4, 2024",
|
||||||
end_date: "September 4, 2024",
|
// end_date: "September 4, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "XRP Community Day Tokyo",
|
// name: "XRP Community Day Tokyo",
|
||||||
description:
|
// description:
|
||||||
"Join senior execs from Ripple, prominent Japanese institutions, and the XRP community for a day of inspiration, networking and insights.",
|
// "Join senior execs from Ripple, prominent Japanese institutions, and the XRP community for a day of inspiration, networking and insights.",
|
||||||
type: "meetup",
|
// type: "meetup",
|
||||||
link: "https://events.xrplresources.org/toyko-community-2024",
|
// link: "https://events.xrplresources.org/toyko-community-2024",
|
||||||
location: "Shinagawa, Tokyo",
|
// location: "Shinagawa, Tokyo",
|
||||||
date: "September 6, 2024",
|
// date: "September 6, 2024",
|
||||||
image: require('../static/img/events/event-meetup-tokyo-day.png'),
|
// image: require("../static/img/events/event-meetup-tokyo-day.png"),
|
||||||
start_date: "September 6, 2024",
|
// start_date: "September 6, 2024",
|
||||||
end_date: "September 6, 2024",
|
// end_date: "September 6, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "XRP Community Night Tokyo",
|
// name: "XRP Community Night Tokyo",
|
||||||
description:
|
// description:
|
||||||
"Celebrate with the XRP Community in Tokyo! Don't miss this opportunity to mingle with the vibrant XRP community, visionary developers, trailblazing innovators, and influential VCs.",
|
// "Celebrate with the XRP Community in Tokyo! Don't miss this opportunity to mingle with the vibrant XRP community, visionary developers, trailblazing innovators, and influential VCs.",
|
||||||
type: "meetup",
|
// type: "meetup",
|
||||||
link: "https://lu.ma/84do37p7",
|
// link: "https://lu.ma/84do37p7",
|
||||||
location: "Shinagawa, Tokyo",
|
// location: "Shinagawa, Tokyo",
|
||||||
date: "September 6, 2024",
|
// date: "September 6, 2024",
|
||||||
image: require('../static/img/events/event-meetup-tokyo-night.png'),
|
// image: require("../static/img/events/event-meetup-tokyo-night.png"),
|
||||||
start_date: "September 6, 2024",
|
// start_date: "September 6, 2024",
|
||||||
end_date: "September 6, 2024",
|
// end_date: "September 6, 2024",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "Chicago XRP Ledger Meet Up",
|
// name: "Chicago XRP Ledger Meet Up",
|
||||||
description:
|
// description:
|
||||||
"Hey Chicago XRP Ledger community! We’re hosting a meetup soon—come hang out, share ideas, and talk all things XRPL. Would love to see you there!",
|
// "Hey Chicago XRP Ledger community! We’re hosting a meetup soon—come hang out, share ideas, and talk all things XRPL. Would love to see you there!",
|
||||||
type: "meetup",
|
// type: "meetup",
|
||||||
link: "https://lu.ma/74dulzff",
|
// link: "https://lu.ma/74dulzff",
|
||||||
location: "Chicago, IL",
|
// location: "Chicago, IL",
|
||||||
date: "September 12, 2024",
|
// date: "September 12, 2024",
|
||||||
image: require('../static/img/events/chicago-meetup.png'),
|
// image: require("../static/img/events/chicago-meetup.png"),
|
||||||
start_date: "September 12, 2024",
|
// start_date: "September 12, 2024",
|
||||||
end_date: "September 12, 2024",
|
// end_date: "September 12, 2024",
|
||||||
},
|
// },
|
||||||
];
|
// ];
|
||||||
const { nearestDateDiff, nearestEvent, index } = findNearestUpcomingEvent(events);
|
|
||||||
const XrplEventsAndCarouselSection = ({ events }) => {
|
const XrplEventsAndCarouselSection = ({ eventsData}) => {
|
||||||
|
const { nearestDateDiff, nearestEvent, index, events } =
|
||||||
|
findNearestUpcomingEvent(eventsData);
|
||||||
|
|
||||||
const { useTranslate } = useThemeHooks();
|
const { useTranslate } = useThemeHooks();
|
||||||
const { translate } = useTranslate();
|
const { translate } = useTranslate();
|
||||||
const [currentIndex, setCurrentIndex] = useState(index); // use nearest event's index as init state
|
const [currentIndex, setCurrentIndex] = useState(index); // use nearest event's index as init state
|
||||||
@@ -363,14 +382,14 @@ const XrplEventsAndCarouselSection = ({ events }) => {
|
|||||||
<img
|
<img
|
||||||
id="left-image"
|
id="left-image"
|
||||||
alt="Left Event Image"
|
alt="Left Event Image"
|
||||||
src={prevEvent ? prevEvent.image : ""}
|
src={!!prevEvent?.image ? prevEvent?.image?.url : imageLookup[prevEvent?.category[0]] }
|
||||||
style={{ visibility: prevEvent ? "visible" : "hidden" }}
|
style={{ visibility: prevEvent ? "visible" : "hidden" }}
|
||||||
/>
|
/>
|
||||||
<div className="center-image-wrapper">
|
<div className="center-image-wrapper">
|
||||||
<img
|
<img
|
||||||
id="center-image"
|
id="center-image"
|
||||||
alt="Featured Event Image"
|
alt="Featured Event Image"
|
||||||
src={currentEvent ? currentEvent.image : ""}
|
src={!!currentEvent?.image ? currentEvent?.image?.url : imageLookup[currentEvent?.category[0]] }
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
currentEvent && window.open(currentEvent.link, "_blank")
|
currentEvent && window.open(currentEvent.link, "_blank")
|
||||||
}
|
}
|
||||||
@@ -392,7 +411,7 @@ const XrplEventsAndCarouselSection = ({ events }) => {
|
|||||||
<img
|
<img
|
||||||
id="right-image"
|
id="right-image"
|
||||||
alt="Right Event Image"
|
alt="Right Event Image"
|
||||||
src={nextEvent ? nextEvent.image : ""}
|
src={!!nextEvent?.image ? nextEvent?.image?.url : imageLookup[nextEvent?.category[0]] }
|
||||||
style={{ visibility: nextEvent ? "visible" : "hidden" }}
|
style={{ visibility: nextEvent ? "visible" : "hidden" }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -410,7 +429,9 @@ const XrplEventsAndCarouselSection = ({ events }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const CommunityPage: React.FC = () => {
|
const CommunityPage = ({ pageProps }) => {
|
||||||
|
const { data, errors } = pageProps?.contentfulEvents
|
||||||
|
const eventsData = data?.eventsCollection?.items.filter((item) => item.community) || []
|
||||||
const { useTranslate } = useThemeHooks();
|
const { useTranslate } = useThemeHooks();
|
||||||
const { translate } = useTranslate();
|
const { translate } = useTranslate();
|
||||||
return (
|
return (
|
||||||
@@ -560,7 +581,7 @@ const CommunityPage: React.FC = () => {
|
|||||||
</table>
|
</table>
|
||||||
</section>
|
</section>
|
||||||
{/* XRPL Events Carousel Section */}
|
{/* XRPL Events Carousel Section */}
|
||||||
<XrplEventsAndCarouselSection events={events} />
|
<XrplEventsAndCarouselSection eventsData={eventsData} />
|
||||||
{/* Community Funding Section */}
|
{/* Community Funding Section */}
|
||||||
<section className="community-funding">
|
<section className="community-funding">
|
||||||
<Link
|
<Link
|
||||||
@@ -706,16 +727,17 @@ const CommunityPage: React.FC = () => {
|
|||||||
{/* Bottom Cards Section 2 cards */}
|
{/* Bottom Cards Section 2 cards */}
|
||||||
<section className="bottom-cards-section bug-bounty">
|
<section className="bottom-cards-section bug-bounty">
|
||||||
<div className="com-card">
|
<div className="com-card">
|
||||||
<img className="top-right-img bug-bounty-card-bg" alt="Top Right Image" />
|
<img
|
||||||
|
className="top-right-img bug-bounty-card-bg"
|
||||||
|
alt="Top Right Image"
|
||||||
|
/>
|
||||||
<div className="card-content">
|
<div className="card-content">
|
||||||
<h6 className="card-title">
|
<h6 className="card-title">
|
||||||
{translate("RippleX Bug Bounty Program")}
|
{translate("RippleX Bug Bounty Program")}
|
||||||
</h6>
|
</h6>
|
||||||
<h6 className="card-subtitle">
|
<h6 className="card-subtitle">
|
||||||
{translate(
|
{translate("Contribute to the XRP Ledger's")}
|
||||||
"Contribute to the XRP Ledger's"
|
<br />
|
||||||
)}
|
|
||||||
<br/>
|
|
||||||
Security
|
Security
|
||||||
</h6>
|
</h6>
|
||||||
<p className="card-description">
|
<p className="card-description">
|
||||||
@@ -723,14 +745,14 @@ const CommunityPage: React.FC = () => {
|
|||||||
"RippleX’s Bug Bounty, part of Ripple's 1 Billion XRP pledge, strengthens XRP Ledger security and supports its ecosystem."
|
"RippleX’s Bug Bounty, part of Ripple's 1 Billion XRP pledge, strengthens XRP Ledger security and supports its ecosystem."
|
||||||
)}
|
)}
|
||||||
<p className="card-description">
|
<p className="card-description">
|
||||||
{
|
{translate(
|
||||||
translate("Use this program to report bugs in RippleX/rippled. Send a detailed report of a qualifying bug to ")
|
"Use this program to report bugs in RippleX/rippled. Send a detailed report of a qualifying bug to "
|
||||||
}
|
)}
|
||||||
<a href="mailto:bugs@ripple.com">bugs@ripple.com</a>
|
<a href="mailto:bugs@ripple.com">bugs@ripple.com</a>
|
||||||
{
|
{translate(" and use the ")}
|
||||||
translate(" and use the ")
|
<a href="https://ripple.com/files/bug-bounty.asc">
|
||||||
}
|
Public Key.
|
||||||
<a href="https://ripple.com/files/bug-bounty.asc">Public Key.</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</p>
|
</p>
|
||||||
<div className="card-links">
|
<div className="card-links">
|
||||||
@@ -745,13 +767,14 @@ const CommunityPage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="com-card">
|
<div className="com-card">
|
||||||
<img className="bottom-right-img bug-bounty-card-bg-2" alt="Bottom Right Image" />
|
<img
|
||||||
|
className="bottom-right-img bug-bounty-card-bg-2"
|
||||||
|
alt="Bottom Right Image"
|
||||||
|
/>
|
||||||
<div className="card-content">
|
<div className="card-content">
|
||||||
<h6 className="card-title">{translate("Report a Scam")}</h6>
|
<h6 className="card-title">{translate("Report a Scam")}</h6>
|
||||||
<h6 className="card-subtitle pr-bt28">
|
<h6 className="card-subtitle pr-bt28">
|
||||||
{translate(
|
{translate("Report Scams to Safeguard Our Community")}
|
||||||
"Report Scams to Safeguard Our Community"
|
|
||||||
)}
|
|
||||||
</h6>
|
</h6>
|
||||||
<p className="card-description">
|
<p className="card-description">
|
||||||
{translate(
|
{translate(
|
||||||
|
|||||||
55
community/index.server.ts
Normal file
55
community/index.server.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import type { PageRouteDetails } from '@redocly/realm/dist/server/plugins/types';
|
||||||
|
|
||||||
|
const cache = {
|
||||||
|
response: null,
|
||||||
|
expiresAt: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
async function fetchGql(query: string) {
|
||||||
|
return fetch(`https://graphql.contentful.com/content/v1/spaces/${process.env.PUBLIC_CONTENTFUL_SPACE_ID}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${process.env.CONTENTFUL_ACCESS_TOKEN}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ query, variables: {}, operationName: 'GetEvents' }),
|
||||||
|
}).then(res => res.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
const GET_EVENTS = `
|
||||||
|
query GetEvents {
|
||||||
|
eventsCollection(order: startDate_ASC, where: {community: true}) {
|
||||||
|
items {
|
||||||
|
_id
|
||||||
|
name
|
||||||
|
description
|
||||||
|
category
|
||||||
|
link
|
||||||
|
location
|
||||||
|
startDate
|
||||||
|
endDate
|
||||||
|
community
|
||||||
|
image {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
|
||||||
|
export default async function getServerProps(route: PageRouteDetails, data: { props: any }) {
|
||||||
|
try {
|
||||||
|
if (cache.expiresAt <= Date.now()) {
|
||||||
|
cache.response = await fetchGql(GET_EVENTS);
|
||||||
|
cache.expiresAt = Date.now() + 1000 * 60 * 1; // 5 minutes naive cache
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to fetch events', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...data.props,
|
||||||
|
contentfulEvents: cache.response,
|
||||||
|
};
|
||||||
|
}
|
||||||
879
package-lock.json
generated
879
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -15,12 +15,13 @@
|
|||||||
"@codemirror/state": "6.4.1",
|
"@codemirror/state": "6.4.1",
|
||||||
"@codemirror/view": "^6.22.2",
|
"@codemirror/view": "^6.22.2",
|
||||||
"@lezer/highlight": "^1.2.0",
|
"@lezer/highlight": "^1.2.0",
|
||||||
"@redocly/realm": "0.91.3",
|
"@redocly/realm": "0.96.0",
|
||||||
"@uiw/codemirror-themes": "4.21.21",
|
"@uiw/codemirror-themes": "4.21.21",
|
||||||
"@uiw/react-codemirror": "^4.21.21",
|
"@uiw/react-codemirror": "^4.21.21",
|
||||||
"@xrplf/isomorphic": "^1.0.0-beta.1",
|
"@xrplf/isomorphic": "^1.0.0-beta.1",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
|
"graphql": "^15.9.0",
|
||||||
"lottie-react": "^2.4.0",
|
"lottie-react": "^2.4.0",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user