diff --git a/public/images/events/event-placeholder.png b/public/images/events/event-placeholder.png
new file mode 100644
index 00000000000..4a15165452a
Binary files /dev/null and b/public/images/events/event-placeholder.png differ
diff --git a/src/components/EventCard.tsx b/src/components/EventCard.tsx
index 5dbca466c14..e4da86a39b6 100644
--- a/src/components/EventCard.tsx
+++ b/src/components/EventCard.tsx
@@ -1,8 +1,11 @@
import React from "react"
-import { Box, Heading } from "@chakra-ui/react"
+import { useRouter } from "next/router"
+import { useTranslation } from "react-i18next"
+import { BsCalendar3 } from "react-icons/bs"
+import { Box, Flex, Heading, Icon } from "@chakra-ui/react"
+import { Image } from "@chakra-ui/react"
import { ButtonLink } from "./Buttons"
-import Emoji from "./Emoji"
import Text from "./OldText"
const clearStyles = {
@@ -16,87 +19,113 @@ export type EventCardProps = {
title: string
href: string
date: string
+ startDate: string
+ endDate: string
description: string
className?: string
location: string
- isEven: boolean
+ imageUrl?: string
}
const EventCard = ({
title,
href,
- date,
description,
className,
location,
- isEven,
-}: EventCardProps) => (
-
-
+ imageUrl,
+ endDate,
+ startDate,
+}: EventCardProps) => {
+ const { locale } = useRouter()
+ const { t } = useTranslation("page-community")
+ const formatedDate = new Intl.DateTimeFormat(locale, {
+ day: "2-digit",
+ month: "short",
+ }).formatRange(
+ // .replace(/-/g, "/") ==> Fixes Safari Invalid date
+ new Date(startDate?.replace(/-/g, "/")),
+ new Date(endDate?.replace(/-/g, "/"))
+ )
+
+ return (
-
- {date}
-
-
-
-
- {location}
-
-
-
-
- {title}
-
- {description}
- View Event
+
+
+
+
+
+
+ {formatedDate}
+
+
+
+ {/* TODO : add image hostname to next config or add event image to public dir */}
+
+
+
+
+
+
+ {title}
+
+
+ {location}
+
+
+
+ {description}
+
+
+
+
+
+ {t("page-community-upcoming-events-view-event")}
+
+
+
-
-)
+ )
+}
export default EventCard
diff --git a/src/components/MeetupList.tsx b/src/components/MeetupList.tsx
index 6b4c9ed3472..7e98f285706 100644
--- a/src/components/MeetupList.tsx
+++ b/src/components/MeetupList.tsx
@@ -1,8 +1,10 @@
import { useState } from "react"
import sortBy from "lodash/sortBy"
+import { FaChevronRight } from "react-icons/fa6"
import {
Box,
Flex,
+ Icon,
LinkBox,
LinkOverlay,
List,
@@ -23,8 +25,6 @@ import { trackCustomEvent } from "@/lib/utils/matomo"
import meetups from "@/data/community-meetups.json"
-import { useRtlFlip } from "@/hooks/useRtlFlip"
-
export interface Meetup {
title: string
emoji: string
@@ -49,13 +49,7 @@ const sortedMeetups: Array = sortBy(meetups, ["emoji", "location"])
// TODO prop if ordered list or unordered
const MeetupList = () => {
const [searchField, setSearchField] = useState("")
- const { flipForRtl } = useRtlFlip()
const filteredMeetups = filterMeetups(searchField)
- const listBoxShadow = useColorModeValue("tableBox.light", "tableBox.dark")
- const listItemBoxShadow = useColorModeValue(
- "tableItemBox.light",
- "tableItemBox.dark"
- )
const handleSearch = (event: React.ChangeEvent): void => {
setSearchField(event.target.value)
@@ -81,14 +75,18 @@ const MeetupList = () => {
results update as you type
-
+
{filteredMeetups.map((meetup, idx) => (
{
boxShadow: `0 0 1px ${primaryBaseColor}`,
bg: "tableBackgroundHover",
}}
+ borderBottom={"2px solid"}
+ borderColor={"offBackground"}
>
@@ -133,16 +133,14 @@ const MeetupList = () => {
{meetup.location}
-
+
+
+
))}
diff --git a/src/components/UpcomingEventsList.tsx b/src/components/UpcomingEventsList.tsx
index 51bedc6e34e..1bc062cc221 100644
--- a/src/components/UpcomingEventsList.tsx
+++ b/src/components/UpcomingEventsList.tsx
@@ -1,7 +1,8 @@
import { useEffect, useState } from "react"
+import _ from "lodash"
import { useRouter } from "next/router"
import { useTranslation } from "next-i18next"
-import { Box } from "@chakra-ui/react"
+import { Box, Grid, Heading } from "@chakra-ui/react"
import type { CommunityConference, Lang } from "@/lib/types"
@@ -15,19 +16,14 @@ import { getLocaleTimestamp } from "@/lib/utils/time"
import communityEvents from "@/data/community-events.json"
-type OrderedUpcomingEvent = CommunityConference & {
- date: string
- formattedDetails: string
-}
-
const UpcomingEventsList = () => {
const { locale } = useRouter()
const { t } = useTranslation("page-community")
- const eventsPerLoad = 10
- const [orderedUpcomingEvents, setOrderedUpcomingEvents] = useState<
- OrderedUpcomingEvent[]
- >([])
- const [maxRange, setMaxRange] = useState(eventsPerLoad)
+ const monthsPerLoad = 2
+
+ const [monthGroupedEvents, setMonthGroupedEvents] = useState({})
+
+ const [maxRange, setMaxRange] = useState(monthsPerLoad)
// Create Date object from each YYYY-MM-DD JSON date string
const dateParse = (dateString: string): Date => {
@@ -73,13 +69,27 @@ const UpcomingEventsList = () => {
formattedDetails: details,
}
})
+ const groupedEvents = _.groupBy(formattedEvents, ({ startDate }) => {
+ // .replace(/-/g, "/") ==> Fixes Safari Invalid date
+ const start = new Date(startDate.replace(/-/g, "/"))
+ const formatYearMonth = new Intl.DateTimeFormat(locale, {
+ month: "short",
+ year: "numeric",
+ }).format(start)
+ return `${formatYearMonth}`
+ })
+
+ setMonthGroupedEvents(groupedEvents)
- setOrderedUpcomingEvents(formattedEvents)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const loadMoreEvents = () => {
- setMaxRange((counter) => counter + eventsPerLoad)
+ setMaxRange((counter) => {
+ if (counter + monthsPerLoad > Object.keys(monthGroupedEvents)?.length)
+ return Object.keys(monthGroupedEvents)?.length
+ return counter + monthsPerLoad
+ })
trackCustomEvent({
eventCategory: "more events button",
eventAction: "click",
@@ -87,7 +97,7 @@ const UpcomingEventsList = () => {
})
}
- if (orderedUpcomingEvents.length === 0) {
+ if (Object.keys(monthGroupedEvents)?.length === 0) {
return (
{t("page-community-upcoming-events-no-events")}{" "}
@@ -100,56 +110,87 @@ const UpcomingEventsList = () => {
return (
<>
+ {Object.keys(monthGroupedEvents)
+ ?.slice(0, maxRange)
+ ?.map((month) => {
+ const events = monthGroupedEvents[month]
+ return (
+
+
+ {month}
+
+
+ {events.map(
+ (
+ {
+ title,
+ to,
+ href,
+ formattedDetails,
+ date,
+ location,
+ imageUrl,
+ startDate,
+ endDate,
+ },
+ idx
+ ) => (
+
+ )
+ )}
+
+
+ )
+ })}
+
- {orderedUpcomingEvents
- ?.slice(0, maxRange)
- .map(({ title, href, formattedDetails, date, location }, idx) => {
- return (
-
- )
- })}
-
-
- {maxRange <= orderedUpcomingEvents.length && (
+ >
+ {Object.keys(monthGroupedEvents)?.length !== maxRange && (
+
- )}
-
+
+ )}
>
)
}
diff --git a/src/intl/en/page-community.json b/src/intl/en/page-community.json
index 6e2435fd642..488aacc7dbc 100644
--- a/src/intl/en/page-community.json
+++ b/src/intl/en/page-community.json
@@ -44,6 +44,7 @@
"page-community-try-ethereum": "Try Ethereum for yourself",
"page-community-upcoming-events-no-events": "We're not aware of any upcoming events. Know of one?",
"page-community-upcoming-events-load-more": "Load more",
+ "page-community-upcoming-events-view-event": "View event",
"page-community-why-get-involved-title": "Why get involved?",
"page-community-why-get-involved-card-1-title": "Find your tribe",
"page-community-why-get-involved-card-1-description": "There is a tribe for everyone. Find and connect with like minded individuals to discuss, ponder, and celebrate Ethereum together.",