From 06df3672778c4fb02d2dd31db13ef5d80656b342 Mon Sep 17 00:00:00 2001 From: Lucid Kobold <72232219+LucidKobold@users.noreply.github.com> Date: Mon, 13 Jun 2022 15:24:59 -0500 Subject: [PATCH] Moved stickers state to redux. Removed unneded type definitions. Refactored components to accomdate changes in types and interfaces. --- contexts/StickerContext.tsx | 61 ------------------ data/stickerSeeder.ts | 12 +++- src/app/store.ts | 4 +- src/components/calender/Day.tsx | 62 ++++++++---------- src/components/calender/index.tsx | 26 +++++--- .../calender/modals/AddUpdateSticker.tsx | 33 +++++----- .../calender/stickers/DemoStickers.tsx | 10 ++- src/features/calender/calender.ts | 6 +- src/features/calender/stickers.ts | 63 +++++++++++++++++++ src/pages/calendar/[...date].tsx | 9 +-- src/pages/index.tsx | 9 +-- types/CalenderContext.d.ts | 6 ++ types/StickerContext.d.ts | 12 +--- 13 files changed, 156 insertions(+), 157 deletions(-) delete mode 100644 contexts/StickerContext.tsx create mode 100644 src/features/calender/stickers.ts diff --git a/contexts/StickerContext.tsx b/contexts/StickerContext.tsx deleted file mode 100644 index 969a533..0000000 --- a/contexts/StickerContext.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import React, { createContext, useState, ReactNode } from "react"; -import { format, getDate, isSameDay } from "date-fns"; -import stickersSeeder from "../data/stickerSeeder"; - -const StickersContext = createContext({} as StickersContextState); - -const StickersContextProvider = ({ - children -}: { - children: ReactNode; -}): JSX.Element => { - const [stickersMonth, setStickersMonth] = useState( - stickersSeeder() - ); - - // TODO: Add stickers functions here. (Add and edit stickers). - const addEditSticker = (date: Date, sticker: ValidStickerVal): Sticker => { - const newStickersMonth = stickersMonth.slice(); - const index = getDate(date) - 1; - const currDate = newStickersMonth[index]; - - const edited = currDate.edited - ? true - : isSameDay(currDate.date, new Date()) - ? false - : true; - currDate.edited = edited; - // Add manual here when necessary. - - const id = format(date, "yyyyddLL") + sticker; - - const newSticker: Sticker = { - id: id, - date: date, - sticker: sticker, - edited: edited, - manual: false - }; - - newStickersMonth[index] = newSticker; - - setStickersMonth(newStickersMonth.slice()); - - return newSticker; - }; - - // TODO: Add stickers validation function here. - - const stickersContextValues = { - stickersMonth, - addEditSticker - }; - - return ( - - {children} - - ); -}; - -export { StickersContextProvider, StickersContext }; diff --git a/data/stickerSeeder.ts b/data/stickerSeeder.ts index 5639765..f6efddb 100644 --- a/data/stickerSeeder.ts +++ b/data/stickerSeeder.ts @@ -1,4 +1,10 @@ -import { format, getDaysInMonth, isBefore, setDate } from "date-fns"; +import { + format, + getDaysInMonth, + isBefore, + setDate, + startOfDay +} from "date-fns"; /** * This seeder is to simulate the date and sticker info from the database. @@ -23,7 +29,7 @@ const generateSticker = (): -2 | -1 | 0 | 1 | 2 => { const stickersSeeder = (): StickerDays => { const stickers = [] as Sticker[]; - const now = new Date(); + const now = startOfDay(new Date()); const daysOfThisMonth = getDaysInMonth(now); for (let i = 1; i <= daysOfThisMonth; i++) { @@ -36,7 +42,7 @@ const stickersSeeder = (): StickerDays => { const newSticker: Sticker = { id: id, - date: currDate, + date: currDate.toJSON(), sticker: sticker, edited: false, manual: false diff --git a/src/app/store.ts b/src/app/store.ts index 8b88779..db29048 100644 --- a/src/app/store.ts +++ b/src/app/store.ts @@ -1,9 +1,11 @@ import { configureStore } from "@reduxjs/toolkit"; import calenderReducer from "../features/calender/calender"; +import stickersReducer from "../features/calender/stickers"; export const store = configureStore({ reducer: { - calender: calenderReducer + calender: calenderReducer, + stickers: stickersReducer } }); diff --git a/src/components/calender/Day.tsx b/src/components/calender/Day.tsx index 5953a0e..8d9239e 100644 --- a/src/components/calender/Day.tsx +++ b/src/components/calender/Day.tsx @@ -10,15 +10,16 @@ import { } from "date-fns"; import router from "next/router"; import React, { Fragment, useState } from "react"; -import { StickersContextProvider } from "../../../contexts/StickerContext"; import AddUpdateSticker from "./modals/AddUpdateSticker"; import DemoStickers from "./stickers/DemoStickers"; +import { Provider } from "react-redux"; +import { store } from "../../app/store"; interface DayProps { isOverflow?: boolean; overflowDirection?: "next" | "prev" | null; sticker: StickerVal; - date: Date; + date: string; selectedDate: string; currDate: Date; isToday: boolean; @@ -26,12 +27,11 @@ interface DayProps { /** * The individual days in the calender component. - * @param props the props for this component. - * @param {boolean} props.isOverflow is the current date being given before or after the current month. - * @param {"next" | "prev" | null} props.overflowDirection the direction the overflow is. This will navigate the calender forward or backwards 1 month. - * @param {StickerVal} props.sticker the sticker for this date. - * @param {date} props.date the date for this day. - * @param {date} props.selectedDate the date for the selected month. + * @param {boolean} isOverflow is the current date being given before or after the current month. + * @param {"next" | "prev" | null} overflowDirection the direction the overflow is. This will navigate the calender forward or backwards 1 month. + * @param {StickerVal} sticker the sticker for this date. + * @param {date} string the date for this day. + * @param {date} selectedDate the date for the selected month. */ const Day = ({ isOverflow, @@ -43,6 +43,7 @@ const Day = ({ isToday }: DayProps): JSX.Element => { const selectedDateObj = new Date(selectedDate); + const currDateObj = new Date(date); const handleNav = (direction: "next" | "prev") => { if (direction === "next") { @@ -66,10 +67,6 @@ const Day = ({ // This handles the modal for the day. const [isOpen, setIsOpen] = useState(false); - // The current sticker to be displayed on the current date. - // * This is temporary. There should be no need for this once persistent storage is used. This is being used as a workaround to a bug. - const [stickerState, setStickerState] = useState(sticker); - // The step the modal is at. const [step, setStep] = useState(0); @@ -95,7 +92,9 @@ const Day = ({ w="100%" h="100%" _hover={{ - cursor: isBefore(date, endOfDay(currDate)) ? "pointer" : "default", + cursor: isBefore(currDateObj, endOfDay(currDate)) + ? "pointer" + : "default", background: "gray.700", border: "1px solid #FFF", color: "whiteAlpha.900" @@ -107,15 +106,10 @@ const Day = ({ pt={2} > - {`${getDate(date)}`} + {`${getDate(currDateObj)}`} - - + + )} @@ -134,7 +128,9 @@ const Day = ({ justifyContent="flex-start" pt={2} _hover={{ - cursor: isBefore(date, endOfDay(currDate)) ? "pointer" : "default", + cursor: isBefore(currDateObj, endOfDay(currDate)) + ? "pointer" + : "default", background: "gray.700", border: "1px solid #FFF" }} @@ -142,7 +138,7 @@ const Day = ({ 10 + ? getDate(currDateObj) > 10 ? "0px 6px 3px 6px" : "0px 9px 3px 9px" : "auto" @@ -152,24 +148,18 @@ const Day = ({ border={isToday ? "1px solid #0068ff" : "0px"} borderRadius={isToday ? "100px" : "0px"} > - {`${getDate(date)}`} + {`${getDate(currDateObj)}`} - - + + - - {isBefore(date, endOfDay(currDate)) && ( + + {isBefore(currDateObj, endOfDay(currDate)) && ( )} - + )} diff --git a/src/components/calender/index.tsx b/src/components/calender/index.tsx index e09d6dd..daceec6 100644 --- a/src/components/calender/index.tsx +++ b/src/components/calender/index.tsx @@ -1,25 +1,29 @@ -import React, { useContext, useEffect } from "react"; +import React, { useEffect } from "react"; import { Box, HStack, SimpleGrid, Text, VStack } from "@chakra-ui/react"; import { isSameDay, format } from "date-fns"; import { useAppDispatch, useAppSelector } from "../../app/hooks"; import { updateCurrDate, updateMonth } from "../../features/calender/calender"; -import { StickersContext } from "../../../contexts/StickerContext"; import CalenderNav from "./CalenderNav"; import Day from "./Day"; const Calender = (newDate?: UpdateCalendarProps): JSX.Element => { + // * Month * // const currDate: string = useAppSelector((state) => state.calender.currDate); - const selectedDate = useAppSelector( + const selectedDate: SelectedDateInfo = useAppSelector( (state) => state.calender.selectedDateInfo ); const { layout } = selectedDate; - const dispatch = useAppDispatch(); - - const { stickersMonth } = useContext(StickersContext); - const currDateObj = new Date(currDate); + // * Stickers * // + + const stickersMonth: StickerDays = useAppSelector( + (state) => state.stickers.stickersMonth + ); + + const dispatch = useAppDispatch(); + useEffect(() => { if (newDate && newDate.year && newDate.month && newDate.day) { const { year, month, day } = newDate; @@ -46,7 +50,7 @@ const Calender = (newDate?: UpdateCalendarProps): JSX.Element => { } }, [currDate, dispatch]); - // Simulated user settings context + // Simulated user settings. const userSettings = { theme: "default", startOfWeek: "Sunday" @@ -103,7 +107,9 @@ const Calender = (newDate?: UpdateCalendarProps): JSX.Element => { let id = ""; stickersMonth.map((stickerDay) => { - if (isSameDay(stickerDay.date, toDateObj)) { + const { date: stickerDate } = stickerDay; + + if (isSameDay(new Date(stickerDate), toDateObj)) { sticker = stickerDay.sticker; id = stickerDay.id; @@ -115,7 +121,7 @@ const Calender = (newDate?: UpdateCalendarProps): JSX.Element => { isOverflow={isOverflow} overflowDirection={overflowDirection} sticker={sticker} - date={toDateObj} + date={date} selectedDate={selectedDate.date} currDate={currDateObj} isToday={isSameDay(currDateObj, toDateObj)} diff --git a/src/components/calender/modals/AddUpdateSticker.tsx b/src/components/calender/modals/AddUpdateSticker.tsx index 944ffa9..a657272 100644 --- a/src/components/calender/modals/AddUpdateSticker.tsx +++ b/src/components/calender/modals/AddUpdateSticker.tsx @@ -13,18 +13,18 @@ import { SimpleGrid, Box } from "@chakra-ui/react"; -import React, { useState, useContext, useRef } from "react"; +import React, { useState, useRef } from "react"; import { format, isSameDay } from "date-fns"; import { Icon } from "@iconify/react"; -import { StickersContext } from "../../../../contexts/StickerContext"; import StickerSelector from "./StickerSelector"; import DemoStickers from "../stickers/DemoStickers"; +import { useAppDispatch } from "../../../app/hooks"; +import { addEditSticker } from "../../../features/calender/stickers"; interface AddStickerProps { isOpen: boolean; updateIsOpen: React.Dispatch>; - date: Date; - updateSticker: React.Dispatch>; + date: string; currSticker: StickerVal; step: number; updateStep: React.Dispatch>; @@ -37,8 +37,7 @@ interface AddStickerProps { * Handles adding and modifying the stickers for the given month. * @param {boolean} isOpen Tells the component when the modal should be open. * @param {React.Dispatch>} updateIsOpen Used to close the modal. - * @param {date} date The date for which the sticker will be added or modified. - * @param {React.Dispatch>} updateSticker The react state function to update the sticker. + * @param {date} string The date for which the sticker will be added or modified. * @param {StickerVal} currSticker The current sticker for the date. * @param {number} step A numerical variable that represents the page the modal should be at. * @param {React.Dispatch>} updateStep Used to navigate the pages of the modal by updating the step the modal is on. @@ -48,7 +47,6 @@ const AddUpdateSticker = ({ isOpen, updateIsOpen, date, - updateSticker, currSticker, step, updateStep, @@ -56,14 +54,13 @@ const AddUpdateSticker = ({ updateSelectedSticker, currDate }: AddStickerProps): JSX.Element => { - // TODO: Import the stickers array from the calender context. - - const { addEditSticker } = useContext(StickersContext); + const dispatch = useAppDispatch(); + const currDateObj = new Date(date); // ! Update these states to say "add" and "edit" for easier reading. const [modalVariant] = useState<"currDate" | "notCurrDate">( - isSameDay(date, currDate) ? "currDate" : "notCurrDate" + isSameDay(currDateObj, currDate) ? "currDate" : "notCurrDate" ); const handleClose = () => { @@ -71,9 +68,8 @@ const AddUpdateSticker = ({ }; // TODO: Validate that the provided sticker is not the current sticker. Throw an error if the same sticker is attempted. - const handleSubmit = (sticker) => { - const newSticker: Sticker = addEditSticker(date, sticker); - updateSticker(newSticker.sticker); + const handleSubmit = (sticker: StickerVal) => { + dispatch(addEditSticker({ date, sticker })); handleClose(); }; @@ -85,7 +81,10 @@ const AddUpdateSticker = ({ const variants = { currDate: [ { - header: `Which sticker did you earn for ${format(date, "LLL d, y")}?`, + header: `Which sticker did you earn for ${format( + currDateObj, + "LLL d, y" + )}?`, body: ( = ({ stickerVal }: DemoStickersProps) => { + // If sticker is null return an empty space. if (stickerVal === null) { return  ; } + interface StickerToEmoji { [key: string]: JSX.Element; } + /** + * ? Temporarily using values -1 to 1. + * ? In the full app the values will be between -2 and 2. + */ let key = "0"; if (stickerVal > 0) { @@ -24,6 +30,7 @@ const DemoStickers: FC = ({ key = "-1"; } + // Link value to an emoji representing a sticker. const stickerToEmoji: StickerToEmoji = { "1": ( @@ -42,6 +49,7 @@ const DemoStickers: FC = ({ ) }; + // Return the appropriate sticker. return stickerToEmoji[`${key}`]; }; diff --git a/src/features/calender/calender.ts b/src/features/calender/calender.ts index edb0ee8..f811855 100644 --- a/src/features/calender/calender.ts +++ b/src/features/calender/calender.ts @@ -4,11 +4,7 @@ import populate from "../../../lib/populateMonth"; interface CalenderSlice { currDate: string; - selectedDateInfo: { - date: string; - title: string; - layout: MonthLayout; - }; + selectedDateInfo: SelectedDateInfo; } const getCurrDate = (): Date => new Date(); diff --git a/src/features/calender/stickers.ts b/src/features/calender/stickers.ts new file mode 100644 index 0000000..f4d9b5f --- /dev/null +++ b/src/features/calender/stickers.ts @@ -0,0 +1,63 @@ +import { createSlice, PayloadAction } from "@reduxjs/toolkit"; +import { format, getDate, isSameDay } from "date-fns"; +import stickersSeeder from "../../../data/stickerSeeder"; + +interface StickersSlice { + stickersMonth: StickerDays; +} + +interface UpdateStickerSlicePayload { + date: string; + sticker: StickerVal; +} + +const initialState: StickersSlice = { + stickersMonth: stickersSeeder() +}; + +const stickersSlice = createSlice({ + name: "Stickers", + initialState, + reducers: { + addEditSticker( + state: StickersSlice, + actions: PayloadAction + ) { + const { date, sticker } = actions.payload; + + const dateObj = new Date(date); + + // Getting index for the stickers array, sticker from the stickers array, and the date from the sticker. + const index: number = getDate(dateObj) - 1; + const currSticker: Sticker = state.stickersMonth[index]; + const { date: stickerDate } = currSticker; + + // Updating the edited status by checking if the sticker date is today's date. + const edited = currSticker.edited + ? true + : isSameDay(new Date(stickerDate), new Date()) + ? false + : true; + currSticker.edited = edited; + + // TODO: Add manually added here. + + // Updating the id of the sticker. + const id = format(dateObj, "yyyyddLL") + sticker; + + // Updating the information of the sticker. + const newSticker: Sticker = { + id: id, + date: date, + sticker: sticker, + edited: edited, + manual: false + }; + + state.stickersMonth[index] = newSticker; + } + } +}); + +export const { addEditSticker } = stickersSlice.actions; +export default stickersSlice.reducer; diff --git a/src/pages/calendar/[...date].tsx b/src/pages/calendar/[...date].tsx index 4009677..7f99984 100644 --- a/src/pages/calendar/[...date].tsx +++ b/src/pages/calendar/[...date].tsx @@ -15,7 +15,6 @@ import ErrorPage from "next/error"; import Calender from "../../components/calender"; import { Provider } from "react-redux"; import { store } from "../../app/store"; -import { StickersContextProvider } from "../../../contexts/StickerContext"; const DateRoute: React.FC = () => { const router = useRouter(); @@ -198,11 +197,9 @@ const DateRoute: React.FC = () => { ) : ( - - - - - + + + ); }; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 3f13881..8e5a536 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -3,7 +3,6 @@ import { Box } from "@chakra-ui/react"; import { format } from "date-fns"; import { Provider } from "react-redux"; import { store } from "../app/store"; -import { StickersContextProvider } from "../../contexts/StickerContext"; import Calender from "../components/calender"; const IndexPage = (): JSX.Element => { @@ -15,11 +14,9 @@ const IndexPage = (): JSX.Element => { return ( - - - - - + + + ); }; diff --git a/types/CalenderContext.d.ts b/types/CalenderContext.d.ts index a8f4632..b5e598b 100644 --- a/types/CalenderContext.d.ts +++ b/types/CalenderContext.d.ts @@ -44,3 +44,9 @@ interface UpdateCalendarProps { month: number; day: number; } + +interface SelectedDateInfo { + date: string; + title: string; + layout: MonthLayout; +} diff --git a/types/StickerContext.d.ts b/types/StickerContext.d.ts index 74ad45d..9a42cc1 100644 --- a/types/StickerContext.d.ts +++ b/types/StickerContext.d.ts @@ -1,8 +1,3 @@ -interface StickersContextState { - stickersMonth: StickerDays; - addEditSticker: (date: Date, sticker: ValidStickerVal) => Sticker; -} - type StickerVal = -2 | -1 | 0 | 1 | 2 | null; type ValidStickerVal = -2 | -1 | 0 | 1 | 2; @@ -14,15 +9,10 @@ interface AddEditStickerProps { interface Sticker { id: string; - date: Date; + date: string; sticker: StickerVal; edited: boolean; manual: boolean; } type StickerDays = Sticker[]; - -interface MonthSticker { - date: Date; - month: Sticker[]; -}