Merge pull request #60 from LucidKobold/redux

Redux
This commit is contained in:
Lucid Kobold
2022-06-14 18:01:11 -05:00
committed by GitHub
22 changed files with 1365 additions and 1210 deletions

View File

@@ -1,262 +0,0 @@
import React, { createContext, useState, ReactNode } from "react";
import {
format,
startOfMonth,
endOfMonth,
getDate,
add,
sub,
set,
isAfter,
isBefore,
compareAsc
} from "date-fns";
const CalenderContext = createContext({} as CalenderContextState);
const CalenderContextProvider = ({
children
}: {
children: ReactNode;
}): JSX.Element => {
const weekDays: WeekDays = {
sunday: [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
],
monday: [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
]
};
/**
* Using date-fns, this function checks if currDate is within the month of selectedDate or not.
* @param {Date} selectedDate The current month.
* @param {Date} currDate The date to be compared to the selected month.
* @returns True if currDate is outside of the month of selectedDate, false if otherwise.
*/
const isOverflow = (
selectedDate: Date,
currDate: Date
): {
isOverflow: boolean;
overflowDirection: "prev" | "next" | null;
} => {
let flag = false;
let direction: "next" | "prev" | null = null;
const start = startOfMonth(selectedDate);
const end = endOfMonth(selectedDate);
if (isBefore(currDate, start)) {
flag = true;
direction = "prev";
}
if (isAfter(currDate, end)) {
flag = true;
direction = "next";
}
return { isOverflow: flag, overflowDirection: direction };
};
/**
* A function that will return a month layout when given a date. It produces
* an object with 6 weeks that include overflow from the previous and next month
* with all dates aligned with the day of the week.
* @param selectedDate The date of the month to generate a month layout for.
*/
const populateMonth = (selectedDate: Date): MonthLayout => {
const endLastMonth = getDate(endOfMonth(sub(selectedDate, { months: 1 })));
const startOfSelectedMonth = format(startOfMonth(selectedDate), "iii");
const ISOToIndex = {
sunday: {
Sun: 0,
Mon: 1,
Tue: 2,
Wed: 3,
Thu: 4,
Fri: 5,
Sat: 6
},
monday: {
Mon: -1,
Tue: 0,
Wed: 1,
Thu: 2,
Fri: 3,
Sat: 4,
Sun: 5
}
};
const sundays = {
week1: new Array(7).fill(null),
week2: new Array(7).fill(null),
week3: new Array(7).fill(null),
week4: new Array(7).fill(null),
week5: new Array(7).fill(null),
week6: new Array(7).fill(null)
};
const sunStartDay =
endLastMonth - (ISOToIndex.sunday[startOfSelectedMonth] - 1);
let sunCurrDate = set(sub(selectedDate, { months: 1 }), {
date: sunStartDay
});
for (const week in sundays) {
const thisWeek = sundays[week];
thisWeek.forEach((e, i) => {
const overflowInfo = isOverflow(selectedDate, sunCurrDate);
const day: MonthDay = {
...overflowInfo,
date: sunCurrDate
};
sunCurrDate = add(sunCurrDate, {
days: 1
});
sundays[week][i] = day;
});
}
const mondays = {
week1: new Array(7).fill(null),
week2: new Array(7).fill(null),
week3: new Array(7).fill(null),
week4: new Array(7).fill(null),
week5: new Array(7).fill(null),
week6: new Array(7).fill(null)
};
const monStartDay = endLastMonth - ISOToIndex.monday[startOfSelectedMonth];
let monCurrDate = set(sub(selectedDate, { months: 1 }), {
date: monStartDay
});
for (const week in mondays) {
const thisWeek = mondays[week];
thisWeek.forEach((e, i) => {
const overflowInfo = isOverflow(selectedDate, monCurrDate);
const day: MonthDay = {
...overflowInfo,
date: monCurrDate
};
monCurrDate = add(monCurrDate, {
days: 1
});
mondays[week][i] = day;
});
}
const output = {
sunday: {
weekdays: weekDays.sunday,
month: sundays
},
monday: {
weekdays: weekDays.monday,
month: mondays
}
};
return output;
};
const [selectedDate, setSelectedDate] = useState<Date>(new Date());
const [selectedDateInfo, setSelectedMonthInfo] = useState<MonthContext>({
date: selectedDate,
title: format(selectedDate, "LLLL uuuu"),
layout: populateMonth(selectedDate)
});
/**
* Updates the selectedDateInfo state when given a date.
* @param {Date} newDate The date to set the selectedDateInfo state to.
*/
const updateDateInfo = (newDate: Date) => {
const output = { ...selectedDateInfo };
output.date = newDate;
output.title = format(newDate, "LLLL uuuu");
output.layout = populateMonth(newDate);
setSelectedMonthInfo(output);
};
// TODO: Add a function that validated if a date has at least one sticker in it. Use that within the nav function (when filter is enabled).
// TODO: Add a function that will give the closest date, if available, when the nav func detects an empty month.
// Use the chart creation date to aid with this. (When filter is enabled)
/**
* TODO: Add logic that prevents navigation to the future and too far in the past. (Use chart creation date)
* Update to use a promise and return appropriate errors. Display those errors on the front end.
* Update the use of this function on the front to handle the fails of the promise.
*/
// TODO: (When filter is enabled) Update the calender update function that will take in a direction so that the the navigation buttons will take the user to the next month with stickers. Assuming there was a gap with empty months.
/**
* Updated the selectedDate state when given the appropriate object.
* @param {UpdateCalendarProps} input An object with year, month,
* and day keys that the selectedDate state will be updated to.
*/
const updateDate = (input: UpdateCalendarProps) => {
const { year, month: inputMonth, day } = input;
if (!year || !inputMonth || day < 0 || day > 31) {
return false;
} else {
const month = inputMonth - 1;
const customDate: Date = new Date(year, month, day);
if (compareAsc(customDate, selectedDate) !== 0) {
setSelectedDate(customDate);
updateDateInfo(customDate);
}
}
};
// * Attempting to fix an issue with static generation where the date does not appear to be updating after initial generation.
const [currDate, setCurrDate] = useState<Date>(new Date());
const calenderContextValues: CalenderContextState = {
currDate,
setCurrDate,
selectedDate,
title: selectedDateInfo.title,
layout: selectedDateInfo.layout,
updateDate
};
return (
<CalenderContext.Provider value={calenderContextValues}>
{children}
</CalenderContext.Provider>
);
};
export { CalenderContextProvider, CalenderContext };

View File

@@ -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<StickerDays>(
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 (
<StickersContext.Provider value={stickersContextValues}>
{children}
</StickersContext.Provider>
);
};
export { StickersContextProvider, StickersContext };

View File

@@ -1,11 +1,15 @@
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. * Generated a valid sticker value for use when generating a sticker obj.
* Filling up an array for the current month with sticker from ths first to * @returns {ValidStickerVal} a number that will represent a valid sticker value.
* the day before the current date, leaving the rest of the month empty.
*/ */
const generateSticker = (): -2 | -1 | 0 | 1 | 2 => { const generateSticker = (): -2 | -1 | 0 | 1 | 2 => {
const sticker = Math.floor(Math.random() * (2 - -2 + 1)) + -2; const sticker = Math.floor(Math.random() * (2 - -2 + 1)) + -2;
@@ -20,10 +24,16 @@ const generateSticker = (): -2 | -1 | 0 | 1 | 2 => {
} }
}; };
/**
* This seeder is to simulate the date and sticker info from the database.
* Filling up an array for the current month with sticker from ths first to
* the day before the current date, leaving the rest of the month empty.
* @returns {StickerDays} an array with populated sticker objects that correspond to the current month's info.
*/
const stickersSeeder = (): StickerDays => { const stickersSeeder = (): StickerDays => {
const stickers = [] as Sticker[]; const stickers = [] as Sticker[];
const now = new Date(); const now = startOfDay(new Date());
const daysOfThisMonth = getDaysInMonth(now); const daysOfThisMonth = getDaysInMonth(now);
for (let i = 1; i <= daysOfThisMonth; i++) { for (let i = 1; i <= daysOfThisMonth; i++) {
@@ -36,7 +46,7 @@ const stickersSeeder = (): StickerDays => {
const newSticker: Sticker = { const newSticker: Sticker = {
id: id, id: id,
date: currDate, date: currDate.toJSON(),
sticker: sticker, sticker: sticker,
edited: false, edited: false,
manual: false manual: false

179
lib/populateMonth.ts Normal file
View File

@@ -0,0 +1,179 @@
import {
getDate,
endOfMonth,
format,
startOfMonth,
set,
isAfter,
isBefore,
subMonths,
addDays
} from "date-fns";
const weekDays: WeekDays = {
sunday: [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
],
monday: [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
]
};
/**
* Using date-fns, this function checks if currDate is within the month of selectedDate or not.
* @param {Date} selectedDate The current month.
* @param {Date} currDate The date to be compared to the selected month.
* @returns True if currDate is outside of the month of selectedDate, false if otherwise.
*/
const isOverflow = (
selectedDate: Date,
currDate: Date
): {
isOverflow: boolean;
overflowDirection: "prev" | "next" | null;
} => {
let flag = false;
let direction: "next" | "prev" | null = null;
const start = startOfMonth(selectedDate);
const end = endOfMonth(selectedDate);
if (isBefore(currDate, start)) {
flag = true;
direction = "prev";
}
if (isAfter(currDate, end)) {
flag = true;
direction = "next";
}
return { isOverflow: flag, overflowDirection: direction };
};
/**
* A function that will return a month layout when given a date. It produces
* an object with 6 weeks that include overflow from the previous and next month
* with all dates aligned with the day of the week.
* @param selectedDate The date of the month to generate a month layout for.
* @returns The month layout object for the provided month.
*/
const populateMonth = (selectedDate: Date): MonthLayout => {
const endLastMonth = getDate(endOfMonth(subMonths(selectedDate, 1)));
const startOfSelectedMonth = format(startOfMonth(selectedDate), "iii");
const ISOToIndex = {
sunday: {
Sun: 0,
Mon: 1,
Tue: 2,
Wed: 3,
Thu: 4,
Fri: 5,
Sat: 6
},
monday: {
Mon: -1,
Tue: 0,
Wed: 1,
Thu: 2,
Fri: 3,
Sat: 4,
Sun: 5
}
};
const sundays = {
week1: new Array(7).fill(null),
week2: new Array(7).fill(null),
week3: new Array(7).fill(null),
week4: new Array(7).fill(null),
week5: new Array(7).fill(null),
week6: new Array(7).fill(null)
};
// The date of the first day in the overflow
const sunStartDay =
endLastMonth - (ISOToIndex.sunday[startOfSelectedMonth] - 1);
let sunCurrDate = set(subMonths(selectedDate, 1), {
date: sunStartDay
});
for (const week in sundays) {
const thisWeek = sundays[week];
thisWeek.forEach((e, i) => {
const overflowInfo = isOverflow(selectedDate, sunCurrDate);
const day: MonthDay = {
...overflowInfo,
date: sunCurrDate.toJSON()
};
sunCurrDate = addDays(sunCurrDate, 1);
sundays[week][i] = day;
});
}
const mondays = {
week1: new Array(7).fill(null),
week2: new Array(7).fill(null),
week3: new Array(7).fill(null),
week4: new Array(7).fill(null),
week5: new Array(7).fill(null),
week6: new Array(7).fill(null)
};
// The date of the first day in the overflow
const monStartDay = endLastMonth - ISOToIndex.monday[startOfSelectedMonth];
let monCurrDate = set(subMonths(selectedDate, 1), {
date: monStartDay
});
for (const week in mondays) {
const thisWeek = mondays[week];
thisWeek.forEach((e, i) => {
const overflowInfo = isOverflow(selectedDate, monCurrDate);
const day: MonthDay = {
...overflowInfo,
date: monCurrDate.toJSON()
};
monCurrDate = addDays(monCurrDate, 1);
mondays[week][i] = day;
});
}
const output = {
sunday: {
weekdays: weekDays.sunday,
month: sundays
},
monday: {
weekdays: weekDays.monday,
month: mondays
}
};
return output;
};
export default populateMonth;

View File

@@ -2,7 +2,7 @@
"private": true, "private": true,
"name": "lucid-creations-media-potty-chart", "name": "lucid-creations-media-potty-chart",
"homepage": "https://lucidcreations.media/introducing-code-name-potty-chart/", "homepage": "https://lucidcreations.media/introducing-code-name-potty-chart/",
"version": "v0.0.9.11-alpha", "version": "v0.0.10-alpha",
"author": { "author": {
"name": "Lucid Creations Media", "name": "Lucid Creations Media",
"url": "https://lucidcreations.media", "url": "https://lucidcreations.media",
@@ -16,29 +16,32 @@
"pretty": "prettier --write ." "pretty": "prettier --write ."
}, },
"dependencies": { "dependencies": {
"@chakra-ui/react": "^2.1.2", "@chakra-ui/react": "^2.2.1",
"@emotion/react": "^11.9.0", "@emotion/react": "^11.9.3",
"@emotion/styled": "^11.8.1", "@emotion/styled": "^11.9.3",
"@iconify/react": "^3.2.2", "@iconify/react": "^3.2.2",
"@reduxjs/toolkit": "^1.8.2",
"date-fns": "^2.28.0", "date-fns": "^2.28.0",
"formik": "^2.2.9", "formik": "^2.2.9",
"framer-motion": "^6.3.10", "framer-motion": "^6.3.11",
"next": "12.1.6", "next": "12.1.6",
"react": "^18.1.0", "react": "^18.2.0",
"react-dom": "^18.1.0", "react-dom": "^18.2.0",
"react-redux": "^8.0.2",
"sharp": "^0.30.6" "sharp": "^0.30.6"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^17.0.40", "@types/node": "^17.0.42",
"@types/react": "^18.0.12", "@types/react": "^18.0.12",
"@typescript-eslint/eslint-plugin": "^5.27.0", "@types/react-redux": "^7.1.24",
"@typescript-eslint/eslint-plugin": "<5.28.0",
"eslint": "^8.17.0", "eslint": "^8.17.0",
"eslint-config-next": "^12.1.6", "eslint-config-next": "^12.1.6",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-react": "^7.30.0", "eslint-plugin-react": "^7.30.0",
"eslint-plugin-react-hooks": "^4.5.0", "eslint-plugin-react-hooks": "<4.6.0",
"prettier": "^2.6.2", "prettier": "^2.7.0",
"typescript": "^4.7.3" "typescript": "^4.7.3"
}, },
"resolutions": { "resolutions": {

5
src/app/hooks.ts Normal file
View File

@@ -0,0 +1,5 @@
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import { RootState, AppDispatch } from "./store";
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

13
src/app/store.ts Normal file
View File

@@ -0,0 +1,13 @@
import { configureStore } from "@reduxjs/toolkit";
import calenderReducer from "../features/calender/calender";
import stickersReducer from "../features/calender/stickers";
export const store = configureStore({
reducer: {
calender: calenderReducer,
stickers: stickersReducer
}
});
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;

View File

@@ -1,14 +1,19 @@
import React, { useContext } from "react"; import React from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { HStack, IconButton } from "@chakra-ui/react"; import { HStack, IconButton } from "@chakra-ui/react";
import { Icon } from "@iconify/react"; import { Icon } from "@iconify/react";
import { format, isSameMonth, addMonths, subMonths } from "date-fns"; import { format, isSameMonth, addMonths, subMonths } from "date-fns";
import findValidDateRange from "../../../lib/findValidDateRange"; import findValidDateRange from "../../../lib/findValidDateRange";
import DatePicker from "./DatePicker"; import DatePicker from "./DatePicker";
import { CalenderContext } from "../../../contexts/CalenderContext"; import { useAppSelector } from "../../app/hooks";
const CalenderNav = (): JSX.Element => { const CalenderNav = (): JSX.Element => {
const { selectedDate } = useContext(CalenderContext); const selectedDate = useAppSelector(
(state) => state.calender.selectedDateInfo
);
const { date } = selectedDate;
const selectedDateObj = new Date(date);
const validDateRange = findValidDateRange(); const validDateRange = findValidDateRange();
const { start: validStart, end: validEnd } = validDateRange; const { start: validStart, end: validEnd } = validDateRange;
@@ -17,14 +22,14 @@ const CalenderNav = (): JSX.Element => {
const handleNavButtons = (direction: "next" | "prev") => { const handleNavButtons = (direction: "next" | "prev") => {
if (direction === "next") { if (direction === "next") {
const newMonth = addMonths(selectedDate, 1); const newMonth = addMonths(selectedDateObj, 1);
const year = format(newMonth, "y"); const year = format(newMonth, "y");
const month = format(newMonth, "L"); const month = format(newMonth, "L");
router.push(`/calendar/${year}/${month}`); router.push(`/calendar/${year}/${month}`);
} else if (direction === "prev") { } else if (direction === "prev") {
const newMonth = subMonths(selectedDate, 1); const newMonth = subMonths(selectedDateObj, 1);
const year = format(newMonth, "y"); const year = format(newMonth, "y");
const month = format(newMonth, "L"); const month = format(newMonth, "L");
@@ -36,14 +41,14 @@ const CalenderNav = (): JSX.Element => {
return ( return (
<HStack spacing={10} as="nav" w="auto" h="10vh" textAlign="center"> <HStack spacing={10} as="nav" w="auto" h="10vh" textAlign="center">
<IconButton <IconButton
isDisabled={isSameMonth(selectedDate, validStart)} isDisabled={isSameMonth(selectedDateObj, validStart)}
aria-label="Previous Month" aria-label="Previous Month"
icon={<Icon icon="akar-icons:chevron-left" />} icon={<Icon icon="akar-icons:chevron-left" />}
onClick={() => handleNavButtons("prev")} onClick={() => handleNavButtons("prev")}
/> />
<DatePicker /> <DatePicker />
<IconButton <IconButton
isDisabled={isSameMonth(selectedDate, validEnd)} isDisabled={isSameMonth(selectedDateObj, validEnd)}
aria-label="Next Month" aria-label="Next Month"
icon={<Icon icon="akar-icons:chevron-right" />} icon={<Icon icon="akar-icons:chevron-right" />}
onClick={() => handleNavButtons("next")} onClick={() => handleNavButtons("next")}

View File

@@ -1,4 +1,4 @@
import React, { useContext, useRef, useState } from "react"; import React, { useRef, useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { import {
Button, Button,
@@ -27,10 +27,12 @@ import {
import { format } from "date-fns"; import { format } from "date-fns";
import findValidDateRange from "../../../lib/findValidDateRange"; import findValidDateRange from "../../../lib/findValidDateRange";
import FormValidateEmoji from "./FormValidateEmoji"; import FormValidateEmoji from "./FormValidateEmoji";
import { CalenderContext } from "../../../contexts/CalenderContext"; import { useAppSelector } from "../../app/hooks";
const DatePicker = (): JSX.Element => { const DatePicker = (): JSX.Element => {
const { title } = useContext(CalenderContext); const selectedDate = useAppSelector(
(state) => state.calender.selectedDateInfo
);
const router = useRouter(); const router = useRouter();
@@ -129,7 +131,7 @@ const DatePicker = (): JSX.Element => {
<PopoverTrigger> <PopoverTrigger>
<Button border="none" variant="outline"> <Button border="none" variant="outline">
<Heading w="100%" h="auto"> <Heading w="100%" h="auto">
{title} {selectedDate.title}
</Heading> </Heading>
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>

View File

@@ -10,49 +10,54 @@ import {
} from "date-fns"; } from "date-fns";
import router from "next/router"; import router from "next/router";
import React, { Fragment, useState } from "react"; import React, { Fragment, useState } from "react";
import { StickersContextProvider } from "../../../contexts/StickerContext";
import AddUpdateSticker from "./modals/AddUpdateSticker"; import AddUpdateSticker from "./modals/AddUpdateSticker";
import DemoStickers from "./stickers/DemoStickers"; import DemoStickers from "./stickers/DemoStickers";
import { Provider } from "react-redux";
import { store } from "../../app/store";
interface DayProps { interface DayProps {
isOverflow?: boolean; isOverflow?: boolean;
overflowDirection?: "next" | "prev" | null; overflowDirection?: "next" | "prev" | null;
sticker: StickerVal; currSticker: StickerVal;
date: Date; date: string;
selectedDate: Date; selectedDate: string;
currDate: Date; currDate: Date;
isToday: boolean; isToday: boolean;
} }
/** /**
* The individual days in the calender component. * The individual days in the calender component.
* @param props the props for this component. * @param {boolean} isOverflow is the current date being given before or after the current month.
* @param {boolean} props.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 {"next" | "prev" | null} props.overflowDirection the direction the overflow is. This will navigate the calender forward or backwards 1 month. * @param {StickerVal} currSticker the sticker for this date.
* @param {StickerVal} props.sticker the sticker for this date. * @param {date} date the date for this day.
* @param {date} props.date the date for this day. * @param {date} selectedDate the date for the selected month.
* @param {date} props.selectedDate the date for the selected month. * @param {Date} currDate today's date.
* @param {boolean} isToday is the current iteration of this component in today's date.
*/ */
const Day = ({ const Day = ({
isOverflow, isOverflow,
overflowDirection, overflowDirection,
sticker, currSticker,
date, date,
selectedDate, selectedDate,
currDate, currDate,
isToday isToday
}: DayProps): JSX.Element => { }: DayProps): JSX.Element => {
const selectedDateObj = new Date(selectedDate);
const currDateObj = new Date(date);
const handleNav = (direction: "next" | "prev") => { const handleNav = (direction: "next" | "prev") => {
if (direction === "next") { if (direction === "next") {
console.log(overflowDirection); console.log(overflowDirection);
const newMonth = add(selectedDate, { months: 1 }); const newMonth = add(selectedDateObj, { months: 1 });
const year = getYear(newMonth); const year = getYear(newMonth);
const month = getMonth(newMonth) + 1; const month = getMonth(newMonth) + 1;
router.push(`/calendar/${year}/${month}`); router.push(`/calendar/${year}/${month}`);
} else if (direction === "prev") { } else if (direction === "prev") {
const newMonth = sub(selectedDate, { months: 1 }); const newMonth = sub(selectedDateObj, { months: 1 });
const year = getYear(newMonth); const year = getYear(newMonth);
const month = getMonth(newMonth) + 1; const month = getMonth(newMonth) + 1;
@@ -64,10 +69,6 @@ const Day = ({
// This handles the modal for the day. // This handles the modal for the day.
const [isOpen, setIsOpen] = useState<boolean>(false); const [isOpen, setIsOpen] = useState<boolean>(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<StickerVal>(sticker);
// The step the modal is at. // The step the modal is at.
const [step, setStep] = useState<number>(0); const [step, setStep] = useState<number>(0);
@@ -93,7 +94,9 @@ const Day = ({
w="100%" w="100%"
h="100%" h="100%"
_hover={{ _hover={{
cursor: isBefore(date, endOfDay(currDate)) ? "pointer" : "default", cursor: isBefore(currDateObj, endOfDay(currDate))
? "pointer"
: "default",
background: "gray.700", background: "gray.700",
border: "1px solid #FFF", border: "1px solid #FFF",
color: "whiteAlpha.900" color: "whiteAlpha.900"
@@ -105,15 +108,10 @@ const Day = ({
pt={2} pt={2}
> >
<Text w="auto" h="auto"> <Text w="auto" h="auto">
{`${getDate(date)}`} {`${getDate(currDateObj)}`}
</Text> </Text>
<Box <Box key={currSticker} fontSize="1.5rem">
key={stickerState === null ? Math.random() : stickerState} <DemoStickers stickerVal={currSticker} />
fontSize="1.5rem"
>
<DemoStickers
stickerVal={stickerState === null ? null : stickerState}
/>
</Box> </Box>
</VStack> </VStack>
)} )}
@@ -132,7 +130,9 @@ const Day = ({
justifyContent="flex-start" justifyContent="flex-start"
pt={2} pt={2}
_hover={{ _hover={{
cursor: isBefore(date, endOfDay(currDate)) ? "pointer" : "default", cursor: isBefore(currDateObj, endOfDay(currDate))
? "pointer"
: "default",
background: "gray.700", background: "gray.700",
border: "1px solid #FFF" border: "1px solid #FFF"
}} }}
@@ -140,7 +140,7 @@ const Day = ({
<Text <Text
p={ p={
isToday isToday
? getDate(date) > 10 ? getDate(currDateObj) > 10
? "0px 6px 3px 6px" ? "0px 6px 3px 6px"
: "0px 9px 3px 9px" : "0px 9px 3px 9px"
: "auto" : "auto"
@@ -150,24 +150,18 @@ const Day = ({
border={isToday ? "1px solid #0068ff" : "0px"} border={isToday ? "1px solid #0068ff" : "0px"}
borderRadius={isToday ? "100px" : "0px"} borderRadius={isToday ? "100px" : "0px"}
> >
{`${getDate(date)}`} {`${getDate(currDateObj)}`}
</Text> </Text>
<Box <Box key={currSticker} fontSize="1.5rem">
key={stickerState === null ? Math.random() : stickerState} <DemoStickers stickerVal={currSticker} />
fontSize="1.5rem"
>
<DemoStickers
stickerVal={stickerState === null ? null : stickerState}
/>
</Box> </Box>
<StickersContextProvider> <Provider store={store}>
{isBefore(date, endOfDay(currDate)) && ( {isBefore(currDateObj, endOfDay(currDate)) && (
<AddUpdateSticker <AddUpdateSticker
date={date} stickerDate={date}
isOpen={isOpen} isOpen={isOpen}
updateIsOpen={setIsOpen} updateIsOpen={setIsOpen}
updateSticker={setStickerState} currSticker={currSticker}
currSticker={stickerState}
step={step} step={step}
updateStep={setStep} updateStep={setStep}
selectedSticker={selectedSticker} selectedSticker={selectedSticker}
@@ -175,7 +169,7 @@ const Day = ({
currDate={currDate} currDate={currDate}
/> />
)} )}
</StickersContextProvider> </Provider>
</VStack> </VStack>
)} )}
</Fragment> </Fragment>

View File

@@ -1,37 +1,56 @@
import React, { useContext, useEffect } from "react"; import React, { useEffect } from "react";
import { Box, HStack, SimpleGrid, Text, VStack } from "@chakra-ui/react"; import { Box, HStack, SimpleGrid, Text, VStack } from "@chakra-ui/react";
import { isSameDay, format } from "date-fns"; import { isSameDay, format } from "date-fns";
import { CalenderContext } from "../../../contexts/CalenderContext"; import { useAppDispatch, useAppSelector } from "../../app/hooks";
import { StickersContext } from "../../../contexts/StickerContext"; import { updateCurrDate, updateMonth } from "../../features/calender/calender";
import CalenderNav from "./CalenderNav"; import CalenderNav from "./CalenderNav";
import Day from "./Day"; import Day from "./Day";
const Calender = (newDate?: UpdateCalendarProps): JSX.Element => { const Calender = (newDate?: UpdateCalendarProps): JSX.Element => {
const { selectedDate, layout, updateDate, currDate, setCurrDate } = // * Month * //
useContext(CalenderContext); const currDate: string = useAppSelector((state) => state.calender.currDate);
const { stickersMonth } = useContext(StickersContext); const selectedDate: SelectedDateInfo = useAppSelector(
(state) => state.calender.selectedDateInfo
);
const { layout } = selectedDate;
const currDateObj = new Date(currDate);
// * Stickers * //
const stickersMonth: StickerDays = useAppSelector(
(state) => state.stickers.stickersMonth
);
const dispatch = useAppDispatch();
useEffect(() => { useEffect(() => {
if (newDate && newDate.year && newDate.month && newDate.day) { if (newDate && newDate.year && newDate.month && newDate.day) {
const { year, month, day } = newDate; const { year, month, day } = newDate;
if (year > 0 && month > 0 && day > 0) { if (year > 0 && month > 0 && day > 0) {
updateDate(newDate); const generatedDate: Date = new Date(year, month - 1, day);
const dateString: string = generatedDate.toJSON();
dispatch(updateMonth(dateString));
} else { } else {
console.warn("Invalid date format: ", newDate); console.warn("Invalid date format: ", newDate);
} }
} }
}, [newDate, updateDate]); }, [dispatch, newDate]);
useEffect(() => { useEffect(() => {
console.info("Check to update date."); console.info("Check to update date.");
if (!isSameDay(currDate, new Date())) {
console.info("Updated date.");
setCurrDate(new Date());
}
}, [currDate, setCurrDate]);
// Simulated user settings context const currDateObj = new Date(currDate);
if (!isSameDay(currDateObj, new Date())) {
console.info("Updated date.");
dispatch(updateCurrDate());
}
}, [currDate, dispatch]);
// Simulated user settings.
const userSettings = { const userSettings = {
theme: "default", theme: "default",
startOfWeek: "Sunday" startOfWeek: "Sunday"
@@ -81,12 +100,16 @@ const Calender = (newDate?: UpdateCalendarProps): JSX.Element => {
return thisWeek.map((day: MonthDay) => { return thisWeek.map((day: MonthDay) => {
const { date, isOverflow, overflowDirection } = day; const { date, isOverflow, overflowDirection } = day;
const toDateObj: Date = new Date(date);
let sticker = null; let sticker = null;
let id = ""; let id = "";
stickersMonth.map((stickerDay) => { stickersMonth.map((stickerDay) => {
if (isSameDay(stickerDay.date, date)) { const { date: stickerDate } = stickerDay;
if (isSameDay(new Date(stickerDate), toDateObj)) {
sticker = stickerDay.sticker; sticker = stickerDay.sticker;
id = stickerDay.id; id = stickerDay.id;
@@ -97,15 +120,15 @@ const Calender = (newDate?: UpdateCalendarProps): JSX.Element => {
<Day <Day
isOverflow={isOverflow} isOverflow={isOverflow}
overflowDirection={overflowDirection} overflowDirection={overflowDirection}
sticker={sticker} currSticker={sticker}
date={date} date={date}
selectedDate={selectedDate} selectedDate={selectedDate.date}
currDate={currDate} currDate={currDateObj}
isToday={isSameDay(currDate, date)} isToday={isSameDay(currDateObj, toDateObj)}
key={ key={
id.length id.length
? id ? id
: format(date, "yyyyddLL") + : format(toDateObj, "yyyyddLL") +
`/${sticker === null ? 0 : sticker}` `/${sticker === null ? 0 : sticker}`
} }
/> />

View File

@@ -13,18 +13,18 @@ import {
SimpleGrid, SimpleGrid,
Box Box
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import React, { useState, useContext, useRef } from "react"; import React, { useState, useRef } from "react";
import { format, isSameDay } from "date-fns"; import { format, isSameDay } from "date-fns";
import { Icon } from "@iconify/react"; import { Icon } from "@iconify/react";
import { StickersContext } from "../../../../contexts/StickerContext";
import StickerSelector from "./StickerSelector"; import StickerSelector from "./StickerSelector";
import DemoStickers from "../stickers/DemoStickers"; import DemoStickers from "../stickers/DemoStickers";
import { useAppDispatch } from "../../../app/hooks";
import { addEditSticker } from "../../../features/calender/stickers";
interface AddStickerProps { interface AddStickerProps {
isOpen: boolean; isOpen: boolean;
updateIsOpen: React.Dispatch<React.SetStateAction<boolean>>; updateIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
date: Date; stickerDate: string;
updateSticker: React.Dispatch<React.SetStateAction<StickerVal>>;
currSticker: StickerVal; currSticker: StickerVal;
step: number; step: number;
updateStep: React.Dispatch<React.SetStateAction<number>>; updateStep: React.Dispatch<React.SetStateAction<number>>;
@@ -37,18 +37,18 @@ interface AddStickerProps {
* Handles adding and modifying the stickers for the given month. * Handles adding and modifying the stickers for the given month.
* @param {boolean} isOpen Tells the component when the modal should be open. * @param {boolean} isOpen Tells the component when the modal should be open.
* @param {React.Dispatch<React.SetStateAction<boolean>>} updateIsOpen Used to close the modal. * @param {React.Dispatch<React.SetStateAction<boolean>>} updateIsOpen Used to close the modal.
* @param {date} date The date for which the sticker will be added or modified. * @param {date} stickerDate The date for which the sticker will be added or modified.
* @param {React.Dispatch<React.SetStateAction<StickerVal>>} updateSticker The react state function to update the sticker.
* @param {StickerVal} currSticker The current sticker for the date. * @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 {number} step A numerical variable that represents the page the modal should be at.
* @param {React.Dispatch<React.SetStateAction<number>>} updateStep Used to navigate the pages of the modal by updating the step the modal is on. * @param {React.Dispatch<React.SetStateAction<number>>} updateStep Used to navigate the pages of the modal by updating the step the modal is on.
* @param {React.Dispatch<React.SetStateAction<StickerVal>>} updateSticker The react state function to update the selected sticker that will be added or updated. * @param {StickerVal} selectedSticker the value of the selected sticker.
* @param {React.Dispatch<React.SetStateAction<StickerVal>>} updateSelectedSticker The react state function to update the selected sticker that will be added or updated.
* @param {Date} currDate the current date.
*/ */
const AddUpdateSticker = ({ const AddUpdateSticker = ({
isOpen, isOpen,
updateIsOpen, updateIsOpen,
date, stickerDate,
updateSticker,
currSticker, currSticker,
step, step,
updateStep, updateStep,
@@ -56,14 +56,11 @@ const AddUpdateSticker = ({
updateSelectedSticker, updateSelectedSticker,
currDate currDate
}: AddStickerProps): JSX.Element => { }: AddStickerProps): JSX.Element => {
// TODO: Import the stickers array from the calender context. const dispatch = useAppDispatch();
const stickerDateObj = new Date(stickerDate);
const { addEditSticker } = useContext(StickersContext); const [modalVariant] = useState<"add" | "edit">(
isSameDay(stickerDateObj, currDate) ? "add" : "edit"
// ! Update these states to say "add" and "edit" for easier reading.
const [modalVariant] = useState<"currDate" | "notCurrDate">(
isSameDay(date, currDate) ? "currDate" : "notCurrDate"
); );
const handleClose = () => { 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. // TODO: Validate that the provided sticker is not the current sticker. Throw an error if the same sticker is attempted.
const handleSubmit = (sticker) => { const handleSubmit = (sticker: StickerVal) => {
const newSticker: Sticker = addEditSticker(date, sticker); dispatch(addEditSticker({ stickerDate, sticker }));
updateSticker(newSticker.sticker);
handleClose(); handleClose();
}; };
@@ -83,9 +79,12 @@ const AddUpdateSticker = ({
// * Double check that the submit button is disabled if the selected sticker is the same as the current sticker. // * Double check that the submit button is disabled if the selected sticker is the same as the current sticker.
const variants = { const variants = {
currDate: [ add: [
{ {
header: `Which sticker did you earn for ${format(date, "LLL d, y")}?`, header: `Which sticker did you earn for ${format(
stickerDateObj,
"LLL d, y"
)}?`,
body: ( body: (
<VStack <VStack
w="100%" w="100%"
@@ -119,10 +118,10 @@ const AddUpdateSticker = ({
) )
} }
], ],
notCurrDate: [ edit: [
{ {
header: `Which sticker did you want to update for ${format( header: `Which sticker did you want to update for ${format(
date, stickerDateObj,
"LLL d, y" "LLL d, y"
)}?`, )}?`,
body: ( body: (
@@ -164,7 +163,7 @@ const AddUpdateSticker = ({
}, },
{ {
header: `Are you sure you want to change the sticker for ${format( header: `Are you sure you want to change the sticker for ${format(
date, stickerDateObj,
"M/d/y" "M/d/y"
)}?`, )}?`,
body: ( body: (
@@ -235,7 +234,7 @@ const AddUpdateSticker = ({
onClose={() => handleClose()} onClose={() => handleClose()}
motionPreset="slideInBottom" motionPreset="slideInBottom"
scrollBehavior="inside" scrollBehavior="inside"
size={modalVariant === "currDate" ? "xl" : "2xl"} size={modalVariant === "add" ? "xl" : "2xl"}
> >
<ModalOverlay /> <ModalOverlay />
<ModalContent> <ModalContent>

View File

@@ -16,6 +16,7 @@ interface StickerSelectorProps {
* @param {StickerVal} currSticker The current sticker for the date. * @param {StickerVal} currSticker The current sticker for the date.
* @param {StickerVal} selectedSticker The selected sticker for the current. date * @param {StickerVal} selectedSticker The selected sticker for the current. date
* @param {React.Dispatch<React.SetStateAction<StickerVal>>} updateSelectedSticker TThe react state function to update the selected sticker that will be added or updated. * @param {React.Dispatch<React.SetStateAction<StickerVal>>} updateSelectedSticker TThe react state function to update the selected sticker that will be added or updated.
* @param {React.MutableRefObject<undefined>} initialSticker the sticker that should have be in focus when the modal opens.
*/ */
const StickerSelector = ({ const StickerSelector = ({

View File

@@ -1,6 +1,6 @@
import React, { FC } from "react"; import React, { FC } from "react";
// TODO: When themes are made import the theme from user settings context. Refactor to use whatever those SVGs are. // TODO: When themes are made import the theme from user settings store. Refactor to use whatever those SVGs are.
interface DemoStickersProps { interface DemoStickersProps {
stickerVal: StickerVal; stickerVal: StickerVal;
@@ -9,13 +9,19 @@ interface DemoStickersProps {
const DemoStickers: FC<DemoStickersProps> = ({ const DemoStickers: FC<DemoStickersProps> = ({
stickerVal stickerVal
}: DemoStickersProps) => { }: DemoStickersProps) => {
// If sticker is null return an empty space.
if (stickerVal === null) { if (stickerVal === null) {
return <span aria-label="spacer">&nbsp;</span>; return <span aria-label="spacer">&nbsp;</span>;
} }
interface StickerToEmoji { interface StickerToEmoji {
[key: string]: JSX.Element; [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"; let key = "0";
if (stickerVal > 0) { if (stickerVal > 0) {
@@ -24,6 +30,7 @@ const DemoStickers: FC<DemoStickersProps> = ({
key = "-1"; key = "-1";
} }
// Link value to an emoji representing a sticker.
const stickerToEmoji: StickerToEmoji = { const stickerToEmoji: StickerToEmoji = {
"1": ( "1": (
<span role="img" aria-label="Sun"> <span role="img" aria-label="Sun">
@@ -42,6 +49,7 @@ const DemoStickers: FC<DemoStickersProps> = ({
) )
}; };
// Return the appropriate sticker.
return stickerToEmoji[`${key}`]; return stickerToEmoji[`${key}`];
}; };

View File

@@ -0,0 +1,58 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { format } from "date-fns";
import populate from "../../../lib/populateMonth";
interface CalenderSlice {
currDate: string;
selectedDateInfo: SelectedDateInfo;
}
const getCurrDate = (): Date => new Date();
const dateParse = (date: Date) => date.toJSON();
const dateFormatter = (date: Date): string => format(date, "LLLL uuuu");
const initialState: CalenderSlice = {
currDate: dateParse(getCurrDate()),
selectedDateInfo: {
date: dateParse(getCurrDate()),
title: dateFormatter(getCurrDate()),
layout: populate(getCurrDate())
}
};
// TODO: Add a function that validated if a month has at least one sticker in it. Use that within the nav function (when filter is enabled).
// TODO: Add a function that will give the closest date, if available, when the nav func detects an empty month.
// Use the chart creation date to aid with this. (When filter is enabled)
/**
* TODO: Add logic that prevents navigation to the future and too far in the past. (Use chart creation date)
* Update to use a promise and return appropriate errors. Display those errors on the front end.
* Update the use of this function on the front to handle the fails of the promise.
*/
// TODO: (When filter is enabled) Update the calender update function that will take in a direction so that the the navigation buttons will take the user to the next month with stickers. Assuming there was a gap with empty months.
const calenderSlice = createSlice({
name: "Calender",
initialState,
reducers: {
// Update month info
updateMonth(state: CalenderSlice, action: PayloadAction<string>) {
const { payload } = action;
const toDateObj: Date = new Date(payload);
state.selectedDateInfo.date = payload;
state.selectedDateInfo.title = dateFormatter(toDateObj);
state.selectedDateInfo.layout = populate(toDateObj);
},
// Update current date
updateCurrDate(state: CalenderSlice) {
state.currDate = dateParse(new Date());
}
}
});
export const { updateMonth, updateCurrDate } = calenderSlice.actions;
export default calenderSlice.reducer;

View File

@@ -0,0 +1,62 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { format, getDate, isSameDay } from "date-fns";
import stickersSeeder from "../../../data/stickerSeeder";
interface StickersSlice {
stickersMonth: StickerDays;
}
interface UpdateStickerSlicePayload {
stickerDate: string;
sticker: StickerVal;
}
const initialState: StickersSlice = {
stickersMonth: stickersSeeder()
};
const stickersSlice = createSlice({
name: "Stickers",
initialState,
reducers: {
addEditSticker(
state: StickersSlice,
actions: PayloadAction<UpdateStickerSlicePayload>
) {
const { stickerDate, sticker } = actions.payload;
const dateObj = new Date(stickerDate);
// 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];
// 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: stickerDate,
sticker: sticker,
edited: edited,
manual: false
};
state.stickersMonth[index] = newSticker;
}
}
});
export const { addEditSticker } = stickersSlice.actions;
export default stickersSlice.reducer;

View File

@@ -13,8 +13,8 @@ import {
// import findValidDateRange from "../../lib/findValidDateRange"; // import findValidDateRange from "../../lib/findValidDateRange";
import ErrorPage from "next/error"; import ErrorPage from "next/error";
import Calender from "../../components/calender"; import Calender from "../../components/calender";
import { CalenderContextProvider } from "../../../contexts/CalenderContext"; import { Provider } from "react-redux";
import { StickersContextProvider } from "../../../contexts/StickerContext"; import { store } from "../../app/store";
const DateRoute: React.FC<unknown> = () => { const DateRoute: React.FC<unknown> = () => {
const router = useRouter(); const router = useRouter();
@@ -59,8 +59,6 @@ const DateRoute: React.FC<unknown> = () => {
} else if (!dateArr[2]) { } else if (!dateArr[2]) {
date.day = 1; date.day = 1;
} }
} else {
return date;
} }
return date; return date;
@@ -199,11 +197,9 @@ const DateRoute: React.FC<unknown> = () => {
<ErrorPage statusCode={404} /> <ErrorPage statusCode={404} />
) : ( ) : (
<Box textAlign="center" w="100%" h="auto" pt="50px" pb="10vh"> <Box textAlign="center" w="100%" h="auto" pt="50px" pb="10vh">
<CalenderContextProvider> <Provider store={store}>
<StickersContextProvider> <Calender {...date} />
<Calender {...date} /> </Provider>
</StickersContextProvider>
</CalenderContextProvider>
</Box> </Box>
); );
}; };

View File

@@ -1,9 +1,9 @@
import React, { useRef } from "react"; import React, { useRef } from "react";
import { Box } from "@chakra-ui/react"; import { Box } from "@chakra-ui/react";
import Calender from "../components/calender";
import { StickersContextProvider } from "../../contexts/StickerContext";
import { CalenderContextProvider } from "../../contexts/CalenderContext";
import { format } from "date-fns"; import { format } from "date-fns";
import { Provider } from "react-redux";
import { store } from "../app/store";
import Calender from "../components/calender";
const IndexPage = (): JSX.Element => { const IndexPage = (): JSX.Element => {
const date = useRef<UpdateCalendarProps>({ const date = useRef<UpdateCalendarProps>({
@@ -14,11 +14,9 @@ const IndexPage = (): JSX.Element => {
return ( return (
<Box textAlign="center" w="100%" h="auto" pt="50px" pb="10vh"> <Box textAlign="center" w="100%" h="auto" pt="50px" pb="10vh">
<StickersContextProvider> <Provider store={store}>
<CalenderContextProvider> <Calender {...date.current} />
<Calender {...date.current} /> </Provider>
</CalenderContextProvider>
</StickersContextProvider>
</Box> </Box>
); );
}; };

View File

@@ -15,7 +15,7 @@ import appLogo from "../../../public/images/logo.svg";
const Header = (): JSX.Element => { const Header = (): JSX.Element => {
const appName = "LCM Potty Chart"; const appName = "LCM Potty Chart";
const appVersion = "v0.0.9.11-alpha"; const appVersion = "v0.0.10-alpha";
// Add transparency while not at the top of the page. // Add transparency while not at the top of the page.
const [transparentNavbar, setTransparentNavbar] = useState<boolean>(false); const [transparentNavbar, setTransparentNavbar] = useState<boolean>(false);

View File

@@ -15,7 +15,7 @@ interface WeekDays {
} }
interface MonthDay { interface MonthDay {
date: Date; date: string;
isOverflow: boolean; isOverflow: boolean;
overflowDirection: "prev" | "next" | null; overflowDirection: "prev" | "next" | null;
} }
@@ -29,11 +29,6 @@ interface Month {
week6: MonthDay[]; week6: MonthDay[];
} }
interface MonthInfo {
date: Date;
title: string;
}
interface WeekLayout { interface WeekLayout {
weekdays: DaysOfWeek; weekdays: DaysOfWeek;
month: Month; month: Month;
@@ -44,21 +39,14 @@ interface MonthLayout {
monday: WeekLayout; monday: WeekLayout;
} }
interface MonthContext extends MonthInfo {
layout: MonthLayout;
}
interface UpdateCalendarProps { interface UpdateCalendarProps {
year: number; year: number;
month: number; month: number;
day: number; day: number;
} }
interface CalenderContextState { interface SelectedDateInfo {
currDate: Date; date: string;
setCurrDate: React.Dispatch<React.SetStateAction<Date>>;
selectedDate: Date;
title: string; title: string;
layout: MonthLayout; layout: MonthLayout;
updateDate: (input: UpdateCalendarProps) => void;
} }

View File

@@ -1,8 +1,3 @@
interface StickersContextState {
stickersMonth: StickerDays;
addEditSticker: (date: Date, sticker: ValidStickerVal) => Sticker;
}
type StickerVal = -2 | -1 | 0 | 1 | 2 | null; type StickerVal = -2 | -1 | 0 | 1 | 2 | null;
type ValidStickerVal = -2 | -1 | 0 | 1 | 2; type ValidStickerVal = -2 | -1 | 0 | 1 | 2;
@@ -14,7 +9,7 @@ interface AddEditStickerProps {
interface Sticker { interface Sticker {
id: string; id: string;
date: Date; date: string;
sticker: StickerVal; sticker: StickerVal;
edited: boolean; edited: boolean;
manual: boolean; manual: boolean;
@@ -22,7 +17,8 @@ interface Sticker {
type StickerDays = Sticker[]; type StickerDays = Sticker[];
interface MonthSticker { interface StickerModal {
date: Date; isOpen: boolean;
month: Sticker[]; selectedSticker: StickerVal;
step: number;
} }

1594
yarn.lock

File diff suppressed because it is too large Load Diff