diff --git a/frontend/src/components/event-action-buttons/event-action-buttons.tsx b/frontend/src/components/event-action-buttons/event-action-buttons.tsx
index 820d23c..3c3acd1 100644
--- a/frontend/src/components/event-action-buttons/event-action-buttons.tsx
+++ b/frontend/src/components/event-action-buttons/event-action-buttons.tsx
@@ -1,10 +1,19 @@
-import { useContext, useState } from "react";
+import { useState } from "react";
import classNames from "classnames";
+import isEqual from "lodash.isequal";
import { toast } from "react-toastify";
import { Icon } from "semantic-ui-react";
import IconLoader from "../icon-loader";
-import { SingleEventContext } from "../../context-providers";
import { resolveApiError } from "../../utils/error-utils";
+import { useAppDispatch, useAppSelector } from "../../redux/hooks";
+import {
+ useCreateEventSignUp,
+ useCreateEventLike,
+ useDeleteEventSignUp,
+ useDeleteEventLike,
+ useGetSingleEvent,
+} from "../../custom-hooks/api/events-api";
+import { setEvent } from "../../redux/slices/single-event-slice";
import styles from "./event-action-buttons.module.scss";
type Props = {
@@ -13,17 +22,37 @@ type Props = {
function EventActionButtons({ onClickComment }: Props) {
const {
- event: { hasLiked, hasSignedUp } = { hasLiked: false, hasSignedUp: false },
- createEventSignUp,
- createEventLike,
- deleteEventSignUp,
- deleteEventLike,
- } = useContext(SingleEventContext);
+ id: eventId,
+ hasLiked,
+ hasSignedUp,
+ } = useAppSelector(
+ ({ singleEvent: { event: { id, hasSignedUp, hasLiked } = {} } }) => ({
+ id,
+ hasLiked,
+ hasSignedUp,
+ }),
+ isEqual,
+ ) as { id: number; hasLiked: boolean; hasSignedUp: boolean };
+ const dispatch = useAppDispatch();
+
+ const { getSingleEvent } = useGetSingleEvent();
+ const { createEventSignUp } = useCreateEventSignUp();
+ const { createEventLike } = useCreateEventLike();
+ const { deleteEventSignUp } = useDeleteEventSignUp();
+ const { deleteEventLike } = useDeleteEventLike();
const [isSigningUp, setSigningUp] = useState(false);
const [isLiking, setLiking] = useState(false);
const [isWithdrawing, setWithdrawing] = useState(false);
const [isUnliking, setUnliking] = useState(false);
+ const updateEvent = async (
+ updateFunction: (data: { eventId: number }) => Promise
,
+ ) => {
+ await updateFunction({ eventId });
+ const updatedEvent = await getSingleEvent(eventId);
+ dispatch(setEvent(updatedEvent));
+ };
+
const onCreateEventSignUp = async () => {
if (isSigningUp || isWithdrawing) {
return;
@@ -32,7 +61,7 @@ function EventActionButtons({ onClickComment }: Props) {
try {
setSigningUp(true);
- await createEventSignUp();
+ await updateEvent(createEventSignUp);
toast.success("You have joined for the event.");
} catch (error) {
@@ -50,7 +79,7 @@ function EventActionButtons({ onClickComment }: Props) {
try {
setLiking(true);
- await createEventLike();
+ await updateEvent(createEventLike);
toast.success("You have liked the event.");
} catch (error) {
@@ -68,7 +97,7 @@ function EventActionButtons({ onClickComment }: Props) {
try {
setWithdrawing(true);
- await deleteEventSignUp();
+ await updateEvent(deleteEventSignUp);
toast.success("You have withdrawn from the event.");
} catch (error) {
@@ -86,7 +115,7 @@ function EventActionButtons({ onClickComment }: Props) {
try {
setUnliking(true);
- await deleteEventLike();
+ await updateEvent(deleteEventLike);
toast.success("You have unliked the event.");
} catch (error) {
diff --git a/frontend/src/components/event-body/event-body.tsx b/frontend/src/components/event-body/event-body.tsx
index cb9541e..320415a 100644
--- a/frontend/src/components/event-body/event-body.tsx
+++ b/frontend/src/components/event-body/event-body.tsx
@@ -1,20 +1,27 @@
-import { useContext, useEffect, useState } from "react";
+import { useEffect } from "react";
+import { useParams } from "react-router-dom";
import PlaceholderWrapper from "../placeholder-wrapper";
import NoEventBanner from "../no-event-banner";
-import { SingleEventContext } from "../../context-providers";
import EventInfoView from "../event-info-view";
+import { useAppDispatch, useAppSelector } from "../../redux/hooks";
+import { useGetSingleEvent } from "../../custom-hooks/api/events-api";
+import { setEvent } from "../../redux/slices/single-event-slice";
function EventBody() {
- const { event, getSingleEvent } = useContext(SingleEventContext);
- const [isLoading, setLoading] = useState(false);
+ const event = useAppSelector(({ singleEvent }) => singleEvent.event);
+ const dispatch = useAppDispatch();
+ const { eventId } = useParams<{ eventId: string }>();
+ const { isLoading, getSingleEvent } = useGetSingleEvent();
useEffect(() => {
(async () => {
- setLoading(true);
- await getSingleEvent();
- setLoading(false);
+ dispatch(setEvent(await getSingleEvent(eventId)));
})();
- }, [getSingleEvent]);
+
+ return () => {
+ dispatch(setEvent(undefined));
+ };
+ }, [eventId, getSingleEvent, dispatch]);
return (
void;
};
function EventCommentInput({ onClickCancel }: Props) {
- const { createEventComment, inputComment, setInputComment } =
- useContext(SingleEventContext);
+ const inputComment = useAppSelector(
+ ({ singleEvent }) => singleEvent.inputComment,
+ );
+ const eventId = useAppSelector(
+ ({ singleEvent }) => singleEvent.event?.id,
+ ) as number;
+ const dispatch = useAppDispatch();
+
+ const { getSingleEvent } = useGetSingleEvent();
+ const { createEventComment } = useCreateEventComment();
const [isSending, setSending] = useState(false);
const onSend = async () => {
@@ -21,9 +37,10 @@ function EventCommentInput({ onClickCancel }: Props) {
}
setSending(true);
- await createEventComment({ content: inputComment });
+ await createEventComment({ eventId, content: inputComment });
+ dispatch(setEvent(await getSingleEvent(eventId)));
setSending(false);
- setInputComment("");
+ dispatch(setInputComment(""));
};
return (
@@ -39,7 +56,7 @@ function EventCommentInput({ onClickCancel }: Props) {
setInputComment(value)}
+ onChange={(_, { value }) => dispatch(setInputComment(value))}
value={inputComment}
/>
diff --git a/frontend/src/components/local-storage-user-manager/index.ts b/frontend/src/components/local-storage-user-manager/index.ts
new file mode 100644
index 0000000..ed1fd57
--- /dev/null
+++ b/frontend/src/components/local-storage-user-manager/index.ts
@@ -0,0 +1 @@
+export { default } from "./local-storage-user-manager";
diff --git a/frontend/src/components/local-storage-user-manager/local-storage-user-manager.tsx b/frontend/src/components/local-storage-user-manager/local-storage-user-manager.tsx
new file mode 100644
index 0000000..9065373
--- /dev/null
+++ b/frontend/src/components/local-storage-user-manager/local-storage-user-manager.tsx
@@ -0,0 +1,15 @@
+import { useEffect } from "react";
+import { useAppSelector } from "../../redux/hooks";
+import { saveToLocalStorage } from "../../utils/localStorage-utils";
+
+function LocalStorageUserManager() {
+ const user = useAppSelector(({ user }) => user);
+
+ useEffect(() => {
+ saveToLocalStorage(user);
+ }, [user]);
+
+ return null;
+}
+
+export default LocalStorageUserManager;
diff --git a/frontend/src/components/pages/events-page/events-page.module.scss b/frontend/src/components/pages/events-page/events-page.module.scss
new file mode 100644
index 0000000..ab5b6d1
--- /dev/null
+++ b/frontend/src/components/pages/events-page/events-page.module.scss
@@ -0,0 +1,5 @@
+.eventsPage {
+ .pusherContainer.important:after {
+ opacity: 0 !important;
+ }
+}
diff --git a/frontend/src/components/pages/events-page/events-page.tsx b/frontend/src/components/pages/events-page/events-page.tsx
index c66add0..c026705 100644
--- a/frontend/src/components/pages/events-page/events-page.tsx
+++ b/frontend/src/components/pages/events-page/events-page.tsx
@@ -1,25 +1,65 @@
-import { useContext } from "react";
import { Sidebar } from "semantic-ui-react";
-import { SearchContext } from "../../../context-providers";
+import { startOfToday } from "date-fns";
+import classNames from "classnames";
import EventList from "../../event-list";
import TopBar from "../../top-bar";
import PageBody from "../../page-body";
import FullPageContainer from "../../full-page-container";
import SearchSidebar from "../../search-sidebar";
import SearchTab from "../../search-tab";
+import { useAppDispatch, useAppSelector } from "../../../redux/hooks";
+import {
+ loadCategories,
+ loadDates,
+ setLoadingCategories,
+ setSidebarOpened,
+} from "../../../redux/slices/search-slice";
+import { useGetEventCategories } from "../../../custom-hooks/api/events-api";
+import useSearchQueryParams from "../../../custom-hooks/use-search-query-params";
+import { getDatePeriods } from "../../../utils/date-time-utils";
+import styles from "./events-page.module.scss";
function EventsPage() {
- const { isSidebarOpened, setSidebarOpened } = useContext(SearchContext);
+ const { getEventCategories } = useGetEventCategories();
+ const isSidebarOpened = useAppSelector(
+ ({ search }) => search.isSidebarOpened,
+ );
+ const dispatch = useAppDispatch();
+ const { searchQuery } = useSearchQueryParams();
+
+ const onClickSearchTab = async () => {
+ dispatch(setSidebarOpened(true));
+ dispatch(
+ loadDates({
+ datePeriods: getDatePeriods({
+ currentDateTime: startOfToday().getTime(),
+ }),
+ searchQuery,
+ }),
+ );
+ dispatch(setLoadingCategories(true));
+
+ const categories = await getEventCategories();
+
+ dispatch(
+ loadCategories({
+ categories,
+ searchQuery,
+ }),
+ );
+ dispatch(setLoadingCategories(false));
+ };
return (
-