Skip to content
This repository has been archived by the owner on Jun 10, 2024. It is now read-only.

Commit

Permalink
fix: optimized event filtering (#9889)
Browse files Browse the repository at this point in the history
* fix: optimized event filtering

proposed changes:
* created a new file `filterEvent.js` to store re-usable filtering logic
* added a new state variable `eventsToShow` and `eventsOptions`
* implemented `useMemo` hook to avoid redundant computations and enhance overall performance

* refactor: EventTabs props
  • Loading branch information
badrivlog committed Jan 12, 2024
1 parent 39fd7b2 commit b318c05
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 75 deletions.
6 changes: 3 additions & 3 deletions components/event/EventTabs.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import Link from "@components/Link";
import Select from "@components/form/Select";
import { classNames } from "@services/utils/classNames";
export function EventTabs({ tabs, eventType, setEventType }) {
export function EventTabs({ tabs, eventType, onEventTypeChange }) {
const changeTab = (e, value) => {
e.preventDefault();
setEventType(value);
onEventTypeChange(value);
if (!value) {
setEventType(tabs.find((tab) => tab.title === e.target.value).key);
onEventTypeChange(tabs.find((tab) => tab.title === e.target.value).key);
}
};

Expand Down
95 changes: 35 additions & 60 deletions components/user/UserEvents.js
Original file line number Diff line number Diff line change
@@ -1,76 +1,51 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import EventCard from "@components/event/EventCard";
import Alert from "@components/Alert";
import Select from "@components/form/Select";
import {
filterByEventType,
getFilteredEvents,
} from "@services/utils/event/filterEvent";

const allEventOptions = [
{ value: "all", name: "All Events" },
{ value: "future", name: "Future Events" },
{ value: "ongoing", name: "Ongoing Events" },
{ value: "virtual", name: "Virtual Events" },
{ value: "inPerson", name: "In-Person Events" },
{ value: "cfpOpen", name: "Events with open CFP" },
{ value: "free", name: "Free Events" },
{ value: "paid", name: "Paid Events" },
{ value: "past", name: "Past Events" },
];

export default function UserEvents({
manage = false,
events,
filter = "future",
}) {
const [eventType, setEventType] = useState(filter);
const [eventsToShow, setEventsToShow] = useState([]);
const [eventOptions, setEventOptions] = useState([]);

const eventOptions = [
{ value: "all", name: "All Events" },
{ value: "future", name: "Future Events" },
{ value: "ongoing", name: "Ongoing Events" },
{ value: "virtual", name: "Virtual Events" },
{ value: "inPerson", name: "In-Person Events" },
{ value: "cfpOpen", name: "Events with open CFP" },
{ value: "free", name: "Free Events" },
{ value: "paid", name: "Paid Events" },
{ value: "past", name: "Past Events" },
];
const handleEventTypeChange = (event) => {
setEventType(event.target.value);
};

const filterByEventType = (event, eventType) => {
switch (eventType) {
case "future":
return event.date.future;
case "ongoing":
return event.date.ongoing;
case "virtual":
return event.date.future && event.isVirtual;
case "inPerson":
return event.date.future && event.isInPerson;
case "cfpOpen":
return event.date.cfpOpen;
case "free":
return event.price?.startingFrom === 0;
case "paid":
return event.price?.startingFrom > 0;
case "past":
return !event.date.future;
default:
useEffect(() => {
setEventsToShow(getFilteredEvents(events, "future"));
const filteredEventOptions = allEventOptions.filter((option) => {
if (option.value === "all") {
return true;
}
};
const getFilteredEvents = () => {
if (eventType === "all") {
return events;
}
let filteredEvents = events.filter((event) =>
filterByEventType(event, eventType),
);
if (eventType === "future" && filteredEvents.length === 0) {
filteredEvents = events.filter((event) =>
filterByEventType(event, "all"),
}
const filterEvents = events.filter((event) =>
filterByEventType(event, option.value),
);
}
return filteredEvents;
return filterEvents.length > 0;
});
setEventOptions(filteredEventOptions);
}, [events]);

const handleEventTypeChange = (event) => {
setEventType(event.target.value);
setEventsToShow(getFilteredEvents(events, event.target.value));
};
const eventsToShow = getFilteredEvents();
const filteredEventOptions = eventOptions.filter((option) => {
if (option.value === "all") {
return true;
}
const filterEvents = events.filter((event) =>
filterByEventType(event, option.value),
);
return filterEvents.length > 0;
});

return (
<>
Expand All @@ -84,7 +59,7 @@ export default function UserEvents({
value={eventType}
label="Select an event type"
onChange={handleEventTypeChange}
options={filteredEventOptions.map((option) => ({
options={eventOptions.map((option) => ({
label: option.name,
value: option.value,
}))}
Expand Down
34 changes: 22 additions & 12 deletions pages/events.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from "react";
import { useState, useMemo } from "react";
import { FaListUl, FaMicrophoneLines } from "react-icons/fa6";
import { MdOutlineOnlinePrediction, MdOutlinePeople } from "react-icons/md";
import { TbCoin, TbCoinOff } from "react-icons/tb";
Expand All @@ -10,6 +10,7 @@ import Page from "@components/Page";
import { EventTabs } from "@components/event/EventTabs";
import PageHead from "@components/PageHead";
import { PROJECT_NAME } from "@constants/index";
import { getFilteredEvents } from "@services/utils/event/filterEvent";

export async function getServerSideProps() {
let events = await getEvents();
Expand All @@ -20,14 +21,25 @@ export async function getServerSideProps() {
}

export default function Events({ events }) {
let categorizedEvents = {
all: events,
virtual: events.filter((event) => event.isVirtual === true),
inPerson: events.filter((event) => event.isInPerson === true),
cfpOpen: events.filter((event) => event.date.cfpOpen === true),
free: events.filter((event) => event.price?.startingFrom === 0),
paid: events.filter((event) => event.price?.startingFrom > 0),
const [eventType, setEventType] = useState("all");
const [eventsToShow, setEventsToShow] = useState(events);

const categorizedEvents = useMemo(() => {
return {
all: events,
virtual: events.filter((event) => event.isVirtual),
inPerson: events.filter((event) => event.isInPerson),
cfpOpen: events.filter((event) => event.date.cfpOpen),
free: events.filter((event) => event.price?.startingFrom === 0),
paid: events.filter((event) => event.price?.startingFrom > 0),
};
}, [events]);

const handleEventChange = (eventTypeVal) => {
setEventType(eventTypeVal);
setEventsToShow(getFilteredEvents(events, eventTypeVal));
};

const tabFilters = [
{
title: "Show all",
Expand Down Expand Up @@ -73,8 +85,6 @@ export default function Events({ events }) {
},
];

const [eventType, setEventType] = useState("all");

return (
<>
<PageHead
Expand All @@ -87,13 +97,13 @@ export default function Events({ events }) {
<EventTabs
tabs={tabFilters}
eventType={eventType}
setEventType={setEventType}
onEventTypeChange={handleEventChange}
/>
<h2 className="text-md md:text-2xl text-lg text-primary-high font-bold md:mb-6 mb-3">
{tabFilters.find((filter) => filter.key === eventType).description}
</h2>
<ul role="list" className="mt-6">
{categorizedEvents[eventType]?.map((event) => (
{eventsToShow.map((event) => (
<EventCard
event={event}
usernames={event.usernames}
Expand Down
37 changes: 37 additions & 0 deletions services/utils/event/filterEvent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
export function filterByEventType(event, eventType) {
switch (eventType) {
case "future":
return event.date.future;
case "ongoing":
return event.date.ongoing;
case "virtual":
return (event.date.future && event.isVirtual) || event.isVirtual;
case "inPerson":
return (event.date.future && event.isInPerson) || event.isInPerson;
case "cfpOpen":
return event.date.cfpOpen;
case "free":
return event.price?.startingFrom === 0;
case "paid":
return event.price?.startingFrom > 0;
case "past":
return !event.date.future;
default:
return true;
}
}

export function getFilteredEvents(events, eventType) {
if (eventType === "all") {
return events;
}
let filteredEvents = events.filter((event) =>
filterByEventType(event, eventType),
);
if (eventType === "future" && filteredEvents.length === 0) {
filteredEvents = events.filter((event) =>
filterByEventType(event, eventType),
);
}
return filteredEvents;
}

0 comments on commit b318c05

Please sign in to comment.