diff --git a/public/images/logo.png b/public/images/logo.png index 1009fd0..d6ad411 100644 Binary files a/public/images/logo.png and b/public/images/logo.png differ diff --git a/public/images/logo.svg b/public/images/logo.svg index 295413e..84cfb1a 100644 --- a/public/images/logo.svg +++ b/public/images/logo.svg @@ -1 +1,212 @@ - \ No newline at end of file + + + + diff --git a/src/components/buttons/data/links.ts b/src/components/buttons/data/links.ts index 834cea3..9835682 100644 --- a/src/components/buttons/data/links.ts +++ b/src/components/buttons/data/links.ts @@ -8,18 +8,13 @@ type Links = LinkObj[]; const links: Links = [ { - href: "https://docs.google.com/document/d/1hrerGKHTO3iach8A-CabtfIB4lyZWlgO8EGTyOCrI2Y", + href: "https://docs.google.com/document/d/1y1tbTG6TYoLMEde4XHzInByyHQ0T6Aw2RF6Y4Z7Yabs", name: "Roadmap and Progress", type: "secondary" }, - { - href: "https://lucidcreations.media/lcm-potty-chart/", - name: "Official Announcement", - type: "secondary" - }, - { - type: "ko-fi" - }, + // { + // type: "ko-fi" + // }, { href: "https://t.me/LucidCreationsMedia", name: "Dev Updates", diff --git a/src/components/calender/CalenderNav.tsx b/src/components/calender/CalenderNav.tsx deleted file mode 100644 index 94a46e9..0000000 --- a/src/components/calender/CalenderNav.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import React from "react"; -import { useAppSelector } from "../../redux/hooks"; -import { useRouter } from "next/router"; -import { HStack, IconButton } from "@chakra-ui/react"; -import { Icon } from "@iconify/react"; -import { format, isSameMonth, addMonths, subMonths } from "date-fns"; -import findValidDateRange from "../../../lib/findValidDateRange"; -import DatePicker from "./DatePicker"; - -interface CalenderNavProps { - isLoading: boolean; - title: string; -} - -/** - * @param {boolean} isLoading is the component loading? - * @param {string} title the title for the current date. - */ - -const CalenderNav = ({ title, isLoading }: CalenderNavProps): JSX.Element => { - const selectedDate = useAppSelector( - (state) => state.calender.selectedDateInfo - ); - const { date } = selectedDate; - - const selectedDateObj = new Date(date); - - const validDateRange = findValidDateRange(); - const { start: validStart, end: validEnd } = validDateRange; - - const router = useRouter(); - - const handleNavButtons = (direction: "next" | "prev") => { - if (direction === "next") { - const newMonth = addMonths(selectedDateObj, 1); - - const year = format(newMonth, "y"); - const month = format(newMonth, "L"); - - router.push(`/calendar/${year}/${month}`); - } else if (direction === "prev") { - const newMonth = subMonths(selectedDateObj, 1); - - const year = format(newMonth, "y"); - const month = format(newMonth, "L"); - - router.push(`/calendar/${year}/${month}`); - } - }; - - return ( - - } - onClick={() => handleNavButtons("prev")} - /> - - } - onClick={() => handleNavButtons("next")} - /> - - ); -}; - -export default CalenderNav; diff --git a/src/components/calender/DatePicker.tsx b/src/components/calender/DatePicker.tsx deleted file mode 100644 index 459a852..0000000 --- a/src/components/calender/DatePicker.tsx +++ /dev/null @@ -1,284 +0,0 @@ -import React, { useRef, useState } from "react"; -import { useRouter } from "next/router"; -import { - Button, - FormControl, - FormErrorMessage, - FormLabel, - Heading, - HStack, - Input, - Popover, - PopoverBody, - PopoverCloseButton, - PopoverContent, - PopoverHeader, - PopoverTrigger, - Skeleton, - VStack -} from "@chakra-ui/react"; -import { - Formik, - // FormikHelpers, - FormikProps, - Form, - Field, - FieldProps -} from "formik"; -import { format } from "date-fns"; -import findValidDateRange from "../../../lib/findValidDateRange"; -import FormValidateEmoji from "./FormValidateEmoji"; - -interface DatePickerProps { - isLoading: boolean; - title: string; -} - -/** - * @param {boolean} isLoading is the component loading? - * @param {string} title the title for the current date. - */ - -const DatePicker = ({ title, isLoading }: DatePickerProps): JSX.Element => { - const router = useRouter(); - - const [valid, setValid] = useState(false); - - const validDateRange = findValidDateRange(); - - const validateDate = ( - dateString?: string | undefined - ): string | undefined => { - let dateError; - - if (dateString) { - const dateArr = dateString.split("-"); - if (dateArr.length !== 3) { - dateError = "Please select a date."; - setValid(false); - } else if (dateArr.length === 3) { - const date: UpdateCalenderPropsDateLayout = { - year: parseInt(dateArr[0]), - month: parseInt(dateArr[1]), - day: parseInt(dateArr[2]) - }; - - if (!/^(19|20)\d{2}$/.test(`${date.year}`)) { - dateError = "Please use a year between 1900 and 2099"; - setValid(false); - } - - if (date.month < 1 || date.month > 12) { - dateError = "Please use a month between 1 and 12"; - setValid(false); - } - - if (date.day < 1 || date.day > 31) { - dateError = "Please use a day between 1 and 31"; - setValid(false); - } - - setValid(true); - } else { - setValid(true); - } - } else if (dateString.length === 0) { - dateError = "Please select a date."; - setValid(false); - } else { - setValid(true); - } - - return dateError; - }; - - const handleSubmit = (formInput?: { date?: string }): Promise => { - return new Promise((resolve, reject) => { - if (formInput.date) { - if (!validateDate(formInput.date)) { - const dateArr = formInput.date.split("-"); - const date: UpdateCalenderPropsDateLayout = { - year: parseInt(dateArr[0]), - month: parseInt(dateArr[1]), - day: parseInt(dateArr[2]) - }; - - return resolve(router.push(`/calendar/${date.year}/${date.month}`)); - } else { - return reject("Error validating date."); - } - } else { - return reject("Date not provided."); - } - }); - }; - - // Field theme - const fieldTheme = { - width: "auto", - bg: "gray.900", - borderColor: "white", - _placeholder: { - color: "white" - }, - _focus: { - bg: "#000", - color: "#FFF", - borderColor: "#63b3ed", - boxShadow: "0 0 0 1px #63b3ed", - zIndex: "1" - } - }; - - const initRef = useRef(); - - return ( - - - - - - - - {"Choose a Date"} - - - - - { - handleSubmit(data) - .then(() => { - actions.setSubmitting(false); - actions.resetForm({ - values: { - date: "" - } - }); - }) - .catch(() => { - actions.setSubmitting(false); - }); - }} - > - {( - formProps: FormikProps<{ - date: string; - }> - ) => ( -
- - - {"Required fields indicated with"} - - - - {({ field, form }: FieldProps) => ( - - - - - {"Date:"} - - - {!form.touched.date && ( - - )} - {form.errors.name && form.touched.date && ( - - )} - {!form.errors.name && form.touched.date && ( - - )} - - - {typeof form.errors.date === "string" && - form.errors.date} - - - - )} - - - -
- )} -
-
-
-
- ); -}; - -export default DatePicker; diff --git a/src/components/calender/Day.tsx b/src/components/calender/Day.tsx deleted file mode 100644 index b5e5245..0000000 --- a/src/components/calender/Day.tsx +++ /dev/null @@ -1,262 +0,0 @@ -import React, { useState } from "react"; -import { Provider } from "react-redux"; -import { store } from "../../redux/store"; -import { Box, Skeleton, VStack } from "@chakra-ui/react"; -import { - add, - getYear, - getMonth, - sub, - getDate, - isBefore, - endOfDay, - isToday as isTodayFun -} from "date-fns"; -import router from "next/router"; -import AddUpdateSticker from "./modals/AddUpdateSticker"; -import DemoStickers from "./stickers/DemoStickers"; - -interface DayProps { - isLoading: boolean; - isOverflow?: boolean; - overflowDirection?: "next" | "prev" | null; - currSticker: StickerVal; - date: string; - selectedDate: string; - currDate: Date; - tutorial?: "add" | "edit"; -} - -/** - * The individual days in the calender component. - * @param {boolean} isLoading is the component loading? - * @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} currSticker the sticker for this date. - * @param {date} date the date for this day. - * @param {date} selectedDate the date for the selected month. - * @param {Date} currDate today's date. - */ -const Day = ({ - isLoading, - isOverflow, - overflowDirection, - currSticker, - date, - selectedDate, - currDate, - tutorial -}: DayProps): JSX.Element => { - const selectedDateObj = new Date(selectedDate); - const currDateObj = new Date(date); - const isToday = isTodayFun(currDateObj); - - const handleNav = (direction: "next" | "prev") => { - if (direction === "next") { - console.log(overflowDirection); - const newMonth = add(selectedDateObj, { months: 1 }); - - const year = getYear(newMonth); - const month = getMonth(newMonth) + 1; - - router.push(`/calendar/${year}/${month}`); - } else if (direction === "prev") { - const newMonth = sub(selectedDateObj, { months: 1 }); - - const year = getYear(newMonth); - const month = getMonth(newMonth) + 1; - - router.push(`/calendar/${year}/${month}`); - } - }; - - // This handles the modal for the day. - const [isOpen, setIsOpen] = useState(false); - - // The step the modal is at. - const [step, setStep] = useState(0); - - // The current selected sticker. (To be added or updated) - const [selectedSticker, setSelectedSticker] = useState(null); - - /** - * TODO: Add logic to remove the onClick within overflow dates. - * Do not give dates for the next month an onClick. - * Do not give dates in the past an onClick there is nothing before that month. - * (Creation date of a chart) - */ - - // TODO: When the valid date range is created, disallow pointer cursor outside of the date range. - - return isOverflow ? ( - - selectedSticker !== null ? handleNav(overflowDirection) : "" - } - spacing="0.5rem" - alignContent="center" - justifyContent="flex-start" - > - - {`${getDate(currDateObj)}`} - - {isLoading ? ( - - - - - - ) : ( - - - - )} - - ) : ( - { - setStep(0); - setSelectedSticker(null); - setIsOpen(true); - }} - alignContent="center" - justifyContent="flex-start" - pt={2} - _hover={{ - cursor: isBefore(currDateObj, endOfDay(currDate)) - ? "pointer" - : "default", - bg: tutorial - ? tutorial === "add" && isToday - ? "gray.600" - : tutorial === "edit" && - !isToday && - isBefore(currDateObj, endOfDay(currDate)) - ? "gray.600" - : "transparent" - : "transparent", - border: "1px solid #FFF" - }} - > - {isToday ? ( - - {`${getDate(currDateObj)}`} - - ) : ( - - {`${getDate(currDateObj)}`} - - )} - {isLoading ? ( - - - - - - ) : ( - - - - )} - {tutorial ? ( - - {tutorial.toLowerCase() === "add" && isToday && !isLoading && ( - - )} - {tutorial.toLowerCase() === "edit" && - !isToday && - isBefore(currDateObj, endOfDay(currDate)) && - !isLoading && ( - - )} - - ) : ( - - {isBefore(currDateObj, endOfDay(currDate)) && !isLoading && ( - - )} - - )} - - ); -}; - -export default Day; diff --git a/src/components/calender/FormValidateEmoji.tsx b/src/components/calender/FormValidateEmoji.tsx deleted file mode 100644 index a231114..0000000 --- a/src/components/calender/FormValidateEmoji.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { FC } from "react"; - -interface FormValidateEmojiProps { - type: string; -} - -const FormValidateEmoji: FC = ({ - type -}: FormValidateEmojiProps) => { - interface Validations { - [key: string]: JSX.Element; - } - - const validations: Validations = { - Required: ( - - ❗ - - ), - Error: ( - - ❌ - - ), - Valid: ( - - ✔ - - ) - }; - - return validations[`${type}`]; -}; - -export default FormValidateEmoji; diff --git a/src/components/calender/index.tsx b/src/components/calender/index.tsx deleted file mode 100644 index 01f9dda..0000000 --- a/src/components/calender/index.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import React, { useEffect } from "react"; -import { useAppDispatch, useAppSelector } from "../../redux/hooks"; -import { updateCurrDate, updateMonth } from "../../features/calender"; -import { Box, HStack, SimpleGrid, Text, VStack } from "@chakra-ui/react"; -import { isSameDay, format } from "date-fns"; -import CalenderNav from "./CalenderNav"; -import Day from "./Day"; - -const Calender = ({ - date: newDate, - isLoading -}: UpdateCalendarProps): JSX.Element => { - const dispatch = useAppDispatch(); - - // * Month * // - const currDate: string = useAppSelector((state) => state.calender.currDate); - const selectedDate: SelectedDateInfo = useAppSelector( - (state) => state.calender.selectedDateInfo - ); - const { layout, title, date: currentSelectedDateStr } = selectedDate; - - const currDateObj = new Date(currDate); - - // * Stickers * // - - const stickersMonth: StickerDays = useAppSelector( - (state) => state.stickers.stickersMonth - ); - - useEffect(() => { - if (newDate && newDate.year && newDate.month && newDate.day) { - const { year, month, day } = newDate; - - if (year > 0 && month > 0 && day > 0) { - const generatedDate: Date = new Date(year, month - 1, day); - const currSelectedDateObj = new Date(currentSelectedDateStr); - const dateString: string = generatedDate.toJSON(); - - if (!isSameDay(currSelectedDateObj, generatedDate)) { - dispatch(updateMonth(dateString)); - } - } else { - console.warn("Invalid date format: ", newDate); - } - } - }, [currentSelectedDateStr, dispatch, newDate]); - - useEffect(() => { - // console.info("Check to update date."); - - const currDateObj = new Date(currDate); - - if (!isSameDay(currDateObj, new Date())) { - // console.info("Updated date."); - dispatch(updateCurrDate()); - } - }, [currDate, dispatch]); - - // Simulated user settings. - const userSettings = { - theme: "default", - startOfWeek: "Sunday" - }; - - const currMonth: WeekLayout = - layout[`${userSettings.startOfWeek.toLowerCase()}`]; - const { month, weekdays } = currMonth; - - // TODO: Move the weekdays into it's own component for responsiveness. - - return ( - - - - - {weekdays.map((weekDay) => { - return ( - - - {weekDay} - - - {weekDay.substring(0, 3)} - - - {weekDay.substring(0, 2)} - - - ); - })} - - - {Object.keys(month).map((week) => { - const thisWeek = month[week]; - - return thisWeek.map((day: MonthDay) => { - const { date, isOverflow, overflowDirection } = day; - - const toDateObj: Date = new Date(date); - - let sticker = null; - - let id = ""; - - stickersMonth.map((stickerDay) => { - const { date: stickerDate } = stickerDay; - - if (isSameDay(new Date(stickerDate), toDateObj)) { - sticker = stickerDay.sticker; - - id = stickerDay.id; - } - }); - - return ( - - ); - }); - })} - - - - ); -}; - -export default Calender; diff --git a/src/components/calender/modals/AddUpdateSticker.tsx b/src/components/calender/modals/AddUpdateSticker.tsx deleted file mode 100644 index 60f2146..0000000 --- a/src/components/calender/modals/AddUpdateSticker.tsx +++ /dev/null @@ -1,271 +0,0 @@ -import React, { useState, useRef } from "react"; -import { useAppDispatch } from "../../../redux/hooks"; -import { addEditSticker } from "../../../features/calender/stickers"; -import { - Button, - Modal, - ModalOverlay, - ModalContent, - ModalHeader, - ModalBody, - ModalFooter, - Heading, - HStack, - Text, - VStack, - SimpleGrid, - Box -} from "@chakra-ui/react"; -import { format, isSameDay } from "date-fns"; -import { Icon } from "@iconify/react"; -import StickerSelector from "./StickerSelector"; -import DemoStickers from "../stickers/DemoStickers"; - -interface AddStickerProps { - isOpen: boolean; - updateIsOpen: React.Dispatch>; - stickerDate: string; - currSticker: StickerVal; - step: number; - updateStep: React.Dispatch>; - selectedSticker: StickerVal; - updateSelectedSticker: React.Dispatch>; - currDate: Date; -} - -/** - * 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} stickerDate 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. - * @param {StickerVal} selectedSticker the value of the selected sticker. - * @param {React.Dispatch>} updateSelectedSticker The react state function to update the selected sticker that will be added or updated. - * @param {Date} currDate the current date. - */ -const AddUpdateSticker = ({ - isOpen, - updateIsOpen, - stickerDate, - currSticker, - step, - updateStep, - selectedSticker, - updateSelectedSticker, - currDate -}: AddStickerProps): JSX.Element => { - const dispatch = useAppDispatch(); - const stickerDateObj = new Date(stickerDate); - - const [modalVariant] = useState<"add" | "edit">( - isSameDay(stickerDateObj, currDate) ? "add" : "edit" - ); - - const handleClose = () => { - updateIsOpen(false); - }; - - // TODO: Validate that the provided sticker is not the current sticker. Throw an error if the same sticker is attempted. - const handleSubmit = (sticker: StickerVal) => { - dispatch(addEditSticker({ stickerDate, sticker })); - handleClose(); - }; - - // The first sticker to have focus when the modal opens. - const initialRef = useRef(); - - // * Double check that the submit button is disabled if the selected sticker is the same as the current sticker. - - const variants = { - add: [ - { - header: `Which sticker did you earn for ${format( - stickerDateObj, - "LLL d, y" - )}?`, - body: ( - - - {"Select a sticker"} - - - - ), - footer: ( - - ) - } - ], - edit: [ - { - header: `Which sticker did you want to update for ${format( - stickerDateObj, - "LLL d, y" - )}?`, - body: ( - - - {"Current Sticker"} - - - - - - {"Select your new sticker"} - - - - ), - footer: ( - - ) - }, - { - header: `Are you sure you want to change the sticker for ${format( - stickerDateObj, - "M/d/y" - )}?`, - body: ( - - - {"Previous Sticker"} - - - - {"New Sticker"} - - - - - - - - - - - - ), - footer: ( - - - - - - - - ) - } - ] - }; - - return ( - handleClose()} - motionPreset="slideInBottom" - scrollBehavior="inside" - size={modalVariant === "add" ? "xl" : "2xl"} - > - - - - - - {modalVariant && variants[modalVariant][step].header} - - - - - - {modalVariant && variants[modalVariant][step].body} - - - {modalVariant && variants[modalVariant][step].footer} - - - - ); -}; - -export default AddUpdateSticker; diff --git a/src/components/calender/modals/StickerSelector.tsx b/src/components/calender/modals/StickerSelector.tsx deleted file mode 100644 index 63b5199..0000000 --- a/src/components/calender/modals/StickerSelector.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { HStack, Button } from "@chakra-ui/react"; -import React from "react"; -import DemoStickers from "../stickers/DemoStickers"; - -interface StickerSelectorProps { - stickerSet: "Demo"; - currSticker: StickerVal; - selectedSticker: StickerVal; - updateSelectedSticker: React.Dispatch>; - initialSticker: React.MutableRefObject; -} - -/** - * Handles displaying a list of dynamic stickers to be selected. - * @param {string} stickerSet The name of the stickers that should be displayed. - * @param {StickerVal} currSticker The current sticker for the date. - * @param {StickerVal} selectedSticker The selected sticker for the current. date - * @param {React.Dispatch>} updateSelectedSticker TThe react state function to update the selected sticker that will be added or updated. - * @param {React.MutableRefObject} initialSticker the sticker that should have be in focus when the modal opens. - */ - -const StickerSelector = ({ - stickerSet, - currSticker, - selectedSticker, - updateSelectedSticker, - initialSticker -}: StickerSelectorProps): JSX.Element => { - const stickers = { - Demo: ( - - - - - - ) - }; - - return stickers[stickerSet]; -}; - -export default StickerSelector; diff --git a/src/components/calender/stickers/DemoStickers.tsx b/src/components/calender/stickers/DemoStickers.tsx deleted file mode 100644 index e7d60f3..0000000 --- a/src/components/calender/stickers/DemoStickers.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import React, { FC } from "react"; - -// TODO: When themes are made import the theme from user settings store. Refactor to use whatever those SVGs are. - -interface DemoStickersProps { - stickerVal: StickerVal; -} - -const DemoStickers: FC = ({ - 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) { - key = "1"; - } else if (stickerVal < 0) { - key = "-1"; - } - - // Link value to an emoji representing a sticker. - const stickerToEmoji: StickerToEmoji = { - "1": ( - - ☀️ - - ), - "0": ( - - ☁️ - - ), - "-1": ( - - 🌧️ - - ) - }; - - // Return the appropriate sticker. - return stickerToEmoji[`${key}`]; -}; - -export default DemoStickers; diff --git a/src/components/tutorial/CalenderExample.tsx b/src/components/tutorial/CalenderExample.tsx deleted file mode 100644 index 3c8531d..0000000 --- a/src/components/tutorial/CalenderExample.tsx +++ /dev/null @@ -1,210 +0,0 @@ -import React, { useEffect } from "react"; -import { useAppDispatch, useAppSelector } from "../../redux/hooks"; -import { updateMonth } from "../../features/calender"; -import { Box, HStack, SimpleGrid, Text, VStack } from "@chakra-ui/react"; -import { format, isSameDay, isToday } from "date-fns"; -import Day from "../calender/Day"; -import { setCurrentWeek } from "../../features/tutorial"; - -interface CalenderExampleProps { - type: "add" | "edit"; - isLoading: boolean; -} - -const CalenderExample = ({ - type, - isLoading -}: CalenderExampleProps): JSX.Element => { - // TODO: Check if the current date is the start of the user's preferred start of the week and use the previous week for the edit example. - - const currDateStr: string = useAppSelector( - (state) => state.calender.currDate - ); - const currDateObj: Date = new Date(currDateStr); - - const dispatch = useAppDispatch(); - - // * Current Month * // - const selectedDate: SelectedDateInfo = useAppSelector( - (state) => state.calender.selectedDateInfo - ); - const { layout, date: currSelectedDateStr } = selectedDate; - - // * Stickers * // - const stickersMonth: StickerDays = useAppSelector( - (state) => state.stickers.stickersMonth - ); - - // Simulated user settings. - const userSettings = { - theme: "default", - startOfWeek: "Sunday" - }; - - // * Week Names * // - const currMonth: WeekLayout = - layout[`${userSettings.startOfWeek.toLowerCase()}`]; - const { month, weekdays } = currMonth; - - useEffect(() => { - const currDateObj: Date = new Date(currDateStr); - const currSelectedDateOj: Date = new Date(currSelectedDateStr); - - if (!isSameDay(currDateObj, currSelectedDateOj)) { - dispatch(updateMonth(currDateObj.toJSON())); - } - }, [currDateStr, currSelectedDateStr, dispatch]); - - // * The current week * // - const currWeek = useAppSelector((state) => state.tutorial.currWeek); - - useEffect(() => { - const getCurrentWeek = (): MonthDay[] => { - let foundWeek: MonthDay[]; - - for (const week in month) { - const currWeek = month[week]; - - currWeek.forEach((day: MonthDay) => { - const { date } = day; - - if (isToday(new Date(date))) { - foundWeek = currWeek; - } - }); - } - - return foundWeek || ([] as MonthDay[]); - }; - - if (currWeek === null) { - dispatch(setCurrentWeek(getCurrentWeek())); - } - }, [currWeek, dispatch, month]); - - return ( - - - - {weekdays.map((weekDay) => { - return ( - - - {weekDay} - - - {weekDay.substring(0, 3)} - - - {weekDay.substring(0, 2)} - - - ); - })} - - - {currWeek && - currWeek.map((day: MonthDay) => { - const { date, isOverflow, overflowDirection } = day; - - const toDateObj: Date = new Date(date); - - let sticker = null; - - let id = ""; - - stickersMonth.map((stickerDay) => { - const { date: stickerDate } = stickerDay; - - if (isSameDay(new Date(stickerDate), toDateObj)) { - sticker = stickerDay.sticker; - - id = stickerDay.id; - } - }); - - return ( - - ); - })} - - - {type === "edit" && ( - - - { - "Not being able to edit within this tutorial when the current date is the start of the week or month is a known bug." - } - - - {"This bug will be fixed in beta v2."} - - - {"You can skip the tutorial and try again tomorrow."} - - - )} - - ); -}; - -export default CalenderExample; diff --git a/src/components/tutorial/data/aboutApp.ts b/src/components/tutorial/data/aboutApp.ts deleted file mode 100644 index e6fcd35..0000000 --- a/src/components/tutorial/data/aboutApp.ts +++ /dev/null @@ -1,10 +0,0 @@ -type AboutApp = string[]; - -const aboutApp: AboutApp = [ - "The Potty Chart is an app that mimics a potty/star chart commonly used while potty training toddler or child.", - "The app can be used to track behavior, habits, diaper training, potty training (good luck), daily chores/tasks, or anything else you might want to track in a fun and visual way with colorful themes, stickers, and even receive encouraging messaged from your big/dom, followers, and friends.", - "The final app will have settings to disable any mentions and references of ABDL to allow a more general audience to use, such as for a master and pet relationship.", - "This is a beta build of the app. Some functionality may not work as intended, is not fully functional, and may be missing entirely." -]; - -export default aboutApp; diff --git a/src/components/tutorial/data/appFunctionality.ts b/src/components/tutorial/data/appFunctionality.ts deleted file mode 100644 index 9c62325..0000000 --- a/src/components/tutorial/data/appFunctionality.ts +++ /dev/null @@ -1,9 +0,0 @@ -type AppFunctionality = string[]; - -const appFunctionality: AppFunctionality = [ - "The app will generate stickers to display from the 1st of the month to the day before today. This is to simulate previous and continued use.", - "Ability to add a sticker to the current date.", - "Ability to add edit a sticker from a previous date with a confirmation prompt." -]; - -export default appFunctionality; diff --git a/src/components/tutorial/index.tsx b/src/components/tutorial/index.tsx deleted file mode 100644 index 3ad41b0..0000000 --- a/src/components/tutorial/index.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from "react"; -import { VStack } from "@chakra-ui/react"; -import TutorialCalender from "./sections/TutorialCalender"; -import TutorialLinks from "./sections/TutorialLinks"; -import TutorialHeading from "./sections/TutorialHeading"; -import TutorialAboutApp from "./sections/TutorialAboutApp"; -import TutorialSubmitButtons from "./sections/TutorialSubmitButtons"; -import TutorialAppFunctionality from "./sections/TutorialAppFunctionality"; - -interface TutorialProps { - isLoading: boolean; -} - -const Tutorial = ({ isLoading }: TutorialProps): JSX.Element => { - return ( - - - - - - - - - ); -}; - -export default Tutorial; diff --git a/src/components/tutorial/sections/TutorialAboutApp.tsx b/src/components/tutorial/sections/TutorialAboutApp.tsx deleted file mode 100644 index 5017de0..0000000 --- a/src/components/tutorial/sections/TutorialAboutApp.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from "react"; -import { VStack, Heading, Divider, Text } from "@chakra-ui/react"; -import aboutApp from "../data/aboutApp"; - -const TutorialAboutApp = (): JSX.Element => { - return ( - - - {"About the App"} - - - {aboutApp.map((string: string) => { - return {string}; - })} - - - - ); -}; - -export default TutorialAboutApp; diff --git a/src/components/tutorial/sections/TutorialAppFunctionality.tsx b/src/components/tutorial/sections/TutorialAppFunctionality.tsx deleted file mode 100644 index c4f5b1c..0000000 --- a/src/components/tutorial/sections/TutorialAppFunctionality.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from "react"; -import { VStack, Heading, Divider, Text } from "@chakra-ui/react"; -import appFunctionality from "../data/appFunctionality"; - -const TutorialAppFunctionality = (): JSX.Element => { - return ( - - - {"App Functionality"} - - - {appFunctionality.map((string: string) => { - return {string}; - })} - - - - ); -}; - -export default TutorialAppFunctionality; diff --git a/src/components/tutorial/sections/TutorialCalender.tsx b/src/components/tutorial/sections/TutorialCalender.tsx deleted file mode 100644 index 4a110e7..0000000 --- a/src/components/tutorial/sections/TutorialCalender.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import React from "react"; -import { Divider, Heading, HStack, Text, VStack } from "@chakra-ui/react"; -import CalenderExample from "../CalenderExample"; - -interface CalenderExampleProps { - isLoading: boolean; -} - -const TutorialCalender = ({ isLoading }: CalenderExampleProps): JSX.Element => { - return ( - - - {"How to Use The Calender"} - - - - {"Add a Sticker to Today's Date"} - - - {"Select the date with the"} - {" green "} - {"border."} - - - - - - {"Add a Sticker to Previous Dates"} - - - {"Select a date with a"} - {" green "} - {"border."} - - - - - - ); -}; - -export default TutorialCalender; diff --git a/src/components/tutorial/sections/TutorialHeading.tsx b/src/components/tutorial/sections/TutorialHeading.tsx deleted file mode 100644 index 852f065..0000000 --- a/src/components/tutorial/sections/TutorialHeading.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from "react"; -import { VStack, Heading, Divider } from "@chakra-ui/react"; - -const TutorialHeading = (): JSX.Element => { - return ( - - {"Welcome to Code Name: LCM Potty Chart"} - - {"A Lucid Creations Media Project"} - - - - ); -}; - -export default TutorialHeading; diff --git a/src/components/tutorial/sections/TutorialLinks.tsx b/src/components/tutorial/sections/TutorialLinks.tsx deleted file mode 100644 index a0cb1a0..0000000 --- a/src/components/tutorial/sections/TutorialLinks.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; -import { Divider, Heading, VStack } from "@chakra-ui/react"; -import Buttons from "../../buttons"; - -const TutorialLinks = (): JSX.Element => { - return ( - - - {"More Info"} - - - - - ); -}; - -export default TutorialLinks; diff --git a/src/components/tutorial/sections/TutorialSubmitButtons.tsx b/src/components/tutorial/sections/TutorialSubmitButtons.tsx deleted file mode 100644 index 4c619d4..0000000 --- a/src/components/tutorial/sections/TutorialSubmitButtons.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { HStack, Button, VStack, Checkbox } from "@chakra-ui/react"; -import React from "react"; -import { useAppDispatch, useAppSelector } from "../../../redux/hooks"; -import { - setTutorialCompleted, - setTempTutorialComplete, - toggleRememberCompleted -} from "../../../features/tutorial"; - -interface TutorialSubmitButtonsProps { - isLoading: boolean; -} - -const TutorialSubmitButtons = ({ - isLoading -}: TutorialSubmitButtonsProps): JSX.Element => { - const rememberComplete: boolean = useAppSelector( - (state) => state.tutorial.rememberCompleted - ); - const dispatch = useAppDispatch(); - - const handleComplete = (): void => { - if (rememberComplete) { - dispatch(setTutorialCompleted()); - } - - if (!rememberComplete) { - dispatch(setTempTutorialComplete()); - } - }; - - const handleSkip = (): void => { - dispatch(setTempTutorialComplete()); - }; - - const handleUpdateCheck = (): void => { - dispatch(toggleRememberCompleted()); - }; - - return ( - - - - - handleUpdateCheck()} - > - {"Remember completed?"} - - - - ); -}; - -export default TutorialSubmitButtons; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 2eed775..e4eb060 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -13,7 +13,7 @@ function LCMPottyChart({ Component, pageProps }: AppProps): JSX.Element { - {"LCM Potty Chart"} + {"LCM Website"} - + - + - + - + - + - + - + - - - + + diff --git a/src/pages/calendar/[...date].tsx b/src/pages/calendar/[...date].tsx deleted file mode 100644 index a174e88..0000000 --- a/src/pages/calendar/[...date].tsx +++ /dev/null @@ -1,209 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { Provider } from "react-redux"; -import { store } from "../../redux/store"; -import { Box } from "@chakra-ui/react"; -import { useRouter } from "next/router"; -import { - endOfMonth, - getDate - // getMonth, - // getYear, - // isAfter, - // isBefore, - // isSameMonth -} from "date-fns"; -// import findValidDateRange from "../../lib/findValidDateRange"; -import ErrorPage from "next/error"; -import Calender from "../../components/calender"; - -const DateRoute: React.FC = () => { - const router = useRouter(); - const { date: slug } = router.query; - - const [date, setDate] = useState(null); - - const [error, setError] = useState(false); - - // const dateRange = useRef(findValidDateRange()); - // const validDateRange = Object.assign({}, dateRange.current); - - const validateDateInput = ( - dateArr: number[] - ): UpdateCalenderPropsDateLayout => { - if (!(dateArr.length >= 2) && !(dateArr.length <= 3)) { - return { - year: 0, - month: 0, - day: 0 - }; - } - - const date = { - year: 0, - month: 0, - day: 0 - }; - - if (/^(19|20)\d{2}$/.test(`${dateArr[0]}`)) { - date.year = dateArr[0]; - } - - if (dateArr[1] > 0 && dateArr[1] <= 12) { - date.month = dateArr[1]; - } - - if (date.month && date.year) { - const lastDay = getDate( - endOfMonth(new Date(date.year, date.month - 1, 1)) - ); - if (dateArr[2] && dateArr[2] > 0 && dateArr[2] <= lastDay) { - date.day = dateArr[2]; - } else if (!dateArr[2]) { - date.day = 1; - } - } - - return date; - }; - - /** - * ! This function does not work as is. It is causing infinite loops whe used within the useEffect. - */ - // const validateDateRange = ( - // slugDate: Date - // ): [Date, "after" | "before" | "valid"] => { - // const { start: validStart, end: validEnd } = validDateRange; - - // // Check if the slug date is beyond the valid end date. - // if (isAfter(slugDate, validEnd)) { - // // router.push("/calender/now"); - // console.warn( - // "Slug date is after the valid date range for this calendar!!!" - // ); - // return [validEnd, "after"]; - // // Check if the slug is before the valid start date. - // } else if (isBefore(slugDate, validStart)) { - // console.warn( - // "Slug date is before the valid date range for this calendar!!!" - // ); - // return [validStart, "before"]; - // // router.push(`/${getYear(validStart)}/${getMonth(validStart) + 1}`); - // } else { - // console.info( - // "Slug date is within the valid date range for this calendar." - // ); - // return [slugDate, "valid"]; - // } - // }; - - useEffect(() => { - // Checking if the slug exists and is an array. - if (slug && Array.isArray(slug)) { - console.log(slug); - // Grabbing the slug length - const length = slug.length; - - // Parsing the slug to convert it from strings to numbers. - const parsedSlug = slug.map((e) => { - return parseInt(e); - }); - - // Checking if the slug has 2 to 3 numbers within the array. year/month/day. - if (length >= 2 && length <= 3) { - // Validate that the date is valid. - const newDate = validateDateInput(parsedSlug); - - // If anything is invalid the year/day/month would be set to 0. This checks for the invalid condition. - if (newDate.year === 0 || newDate.month === 0 || newDate.day === 0) { - setError(true); - // Set the date to the valid date. - } else { - // TODO: Make sure the date is within the valid range using the validateDateRange function. - // const validDate = new Date( - // newDate.year, - // newDate.month - 1, - // newDate.day - // ); - - // const validDateWithinRange = validateDateRange(validDate)[0]; - - // setDate({ - // ...{ - // year: getYear(validDateWithinRange), - // month: getMonth(validDateWithinRange) + 1, - // day: getDate(validDateWithinRange) - // } - // }); - - setDate({ - ...newDate - }); - } - } else if (length === 1) { - // Checking if the slug is not "now". - // ! Update this to include a check for "today". - if (slug[0] !== "now") { - setError(true); - return console.warn("improper date input:", slug); - } - } - } - }, [slug]); - - /** - * ? Pushing into the router within the use effect does not create the infinite loop. - * ? The way the validate date range or the way it is being used within a useEffect is what is creating the infinite loop. - */ - - // useEffect(() => { - // // Check is slug and date are valid. - // if (slug && date && date !== null) { - // // Check if the slug is an array and has a length of 2. - // if (Array.isArray(slug) && slug.length === 2) { - // const dateState = new Date(date.year, date.month - 1, date.day); - - // const parsedSlug = slug.map((e) => { - // return parseInt(e); - // }); - // const slugDate = new Date(parsedSlug[0], parsedSlug[1] - 1, 1); - - // if (!isSameMonth(dateState, slugDate)) { - // const validDateWithinRange = validateDateRange(dateState); - - // if (validDateRange[1] === "after") { - // router.push("/now"); - // } else { - // router.push( - // `/${getYear(validDateWithinRange[0])}/${getMonth( - // validDateWithinRange[0] - // )}` - // ); - // } - // } - // } - // } - // }, [date]); - - if (router.isFallback) { - return ; - } - - /** - * TODO: Update to disallow navigation in the future and too far in the past. - * Update so that a date given in the future take the user to /now to today's date. - * Update so that a date given beyond the last valid date will bring the user to the - * last month that has stickers within it (When filter is enabled) or to the creation date of the chart.. - */ - - return error ? ( - - ) : ( - - - - - - ); -}; - -export default DateRoute; diff --git a/src/pages/calendar/index.tsx b/src/pages/calendar/index.tsx deleted file mode 100644 index ad0dc52..0000000 --- a/src/pages/calendar/index.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React, { useEffect } from "react"; -import { useRouter } from "next/router"; -import { Box, Heading } from "@chakra-ui/react"; - -const DateIndex = () => { - const router = useRouter(); - - useEffect(() => { - if (router) { - router.push("calendar/now"); - } - }, [router]); - - return ( - - - Loading - - - ); -}; - -export default DateIndex; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 4c5825e..9b2d53b 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,130 +1,15 @@ -import React, { Fragment, useEffect, useRef } from "react"; +import React from "react"; import { Provider } from "react-redux"; import { store } from "../redux/store"; -import { useAppDispatch, useAppSelector } from "../redux/hooks"; -import { updateLoading } from "../features/calender"; -import { - clearTutorialCompleted, - getAndSetTutorial, - StorageState -} from "../features/tutorial"; import { Box } from "@chakra-ui/react"; -import { format, isAfter, isBefore, startOfDay } from "date-fns"; -import Calender from "../components/calender"; -import Tutorial from "../components/tutorial"; -import LoadingOverlay from "../components/loading/LoadingOverlay"; -import versionStringToNumber from "../../lib/versionStringToNumber"; + const IndexPage = (): JSX.Element => { - const currDateStr: string = useAppSelector( - (state) => state.calender.currDate - ); - const isLoading: boolean = useAppSelector( - (state) => state.calender.isLoading - ); - - const currDateObj: Date = new Date(currDateStr); - - // * Tutorial * // - const completedTutorial: boolean = useAppSelector( - (state) => state.tutorial.completedTutorial - ); - const tutorialCompletionInfo: StorageState = useAppSelector( - (state) => state.tutorial.storageState - ); - const dispatch = useAppDispatch(); - - // Get the completed tutorial cookie or have it set to false. - useEffect(() => { - if (completedTutorial === null && tutorialCompletionInfo === null) { - dispatch(getAndSetTutorial()); - } - - if (completedTutorial !== null) { - dispatch(updateLoading(false)); - } - }, [completedTutorial, dispatch, tutorialCompletionInfo]); - - // Checking the exp date of completed tutorial cookie and if the version completed is out of date. - useEffect(() => { - if (tutorialCompletionInfo !== null) { - const { exp, version } = tutorialCompletionInfo; - const currDateObj: Date = new Date(currDateStr); - - /** - * Checks if the completed tutorial cookie is expired. - * @param {Date} expDate the date when the completed tutorital cookie expires. - * @returns {boolean} true if the cookie is expired, false is otherwise. - */ - const expDateValidator = (expDate: Date): boolean => { - let flag = false; - - const startOfToday = startOfDay(currDateObj); - - if (isAfter(startOfToday, expDate)) { - flag = true; - } - - return flag; - }; - - /** - * Checks if the last time the completed tutorial is before an update to the tutorial. - * @param {number} lastVersionCompleted the version number the tutorial was last completed. - * @returns {boolean} true if the version given is before the changes to the tutorial, false otherwise. - */ - const versionValidator = (lastVersionCompleted: number): boolean => { - const lastVersionWithChangeStr: string = - process.env.NEXT_PUBLIC_NEW_TUTORIAL_VERSION; - const lastVersionWithChange: number = versionStringToNumber( - lastVersionWithChangeStr - ); - - const lastUpdatedDateStr: string = - process.env.NEXT_PUBLIC_LAST_UPDATE_DATE; - const lastUpdatedDate: Date = new Date(lastUpdatedDateStr); - - let flag = false; - - if ( - lastVersionCompleted < lastVersionWithChange || - (lastVersionCompleted === lastVersionWithChange && - isBefore(currDateObj, lastUpdatedDate)) - ) { - flag = true; - console.error("Completed cookie version is out of date."); - } - - return flag; - }; - - if (expDateValidator(new Date(exp)) || versionValidator(version)) { - console.warn("Version outdated or cookie expired."); - dispatch(clearTutorialCompleted()); - } - } - }, [currDateStr, dispatch, tutorialCompletionInfo]); - - // Current date - const currDate = useRef({ - year: parseInt(format(currDateObj, "y")), - month: parseInt(format(currDateObj, "M")), - day: parseInt(format(currDateObj, "d")) - }); return ( - {isLoading === true ? ( - - - - - ) : completedTutorial ? ( - - ) : ( - - )} + ); diff --git a/src/theme/AppTheme.ts b/src/theme/AppTheme.ts index 2d2321f..140f5b8 100644 --- a/src/theme/AppTheme.ts +++ b/src/theme/AppTheme.ts @@ -29,8 +29,7 @@ const AppTheme = extendTheme({ footer: "#0097a7", footerText: "black", content: "#2d3748", - kofi: "#FF5E5B", - twitter: "#1da1f2" + kofi: "#FF5E5B" }, loading: { overlayBg: "#171923cb", diff --git a/src/theme/layout/Header.tsx b/src/theme/layout/Header.tsx index a204165..2cb4bbb 100644 --- a/src/theme/layout/Header.tsx +++ b/src/theme/layout/Header.tsx @@ -14,7 +14,7 @@ import MobileNav from "./MobileNav"; import appLogo from "../../../public/images/logo.svg"; const Header = (): JSX.Element => { - const appName = "LCM Potty Chart"; + const appName = "Lucid Creations Media"; const appVersion = process.env.NEXT_PUBLIC_APP_VERSION_HEADER || ""; // Add transparency while not at the top of the page.