Merge pull request #13 from LucidKobold/context

Calender Navigation
This commit is contained in:
Lucid Kobold
2021-12-01 14:34:58 -06:00
committed by GitHub
9 changed files with 200 additions and 71 deletions

View File

@@ -65,7 +65,7 @@ I cannot guarantee functionality or stability if used on other OSs Ubuntu versio
After cloning the app you will need to install the dependencies and packages. The app uses Yarn v2. Run this command to install using Yarn v2: After cloning the app you will need to install the dependencies and packages. The app uses Yarn v2. Run this command to install using Yarn v2:
``` ```
Yarn install yarn install
``` ```
### Upgrading Packages ### Upgrading Packages

View File

@@ -1,42 +1,12 @@
import React from "react"; import React, { useContext } from "react";
import { Box, HStack, SimpleGrid, Text, VStack } from "@chakra-ui/react"; import { Box, HStack, SimpleGrid, Text, VStack } from "@chakra-ui/react";
import { endOfMonth, getDate } from "date-fns";
import CalenderNav from "./CalenderNav"; import CalenderNav from "./CalenderNav";
import { CalenderContext } from "../../contexts/CalenderContext";
const Calender = (): JSX.Element => { const Calender = (): JSX.Element => {
const today = new Date(); const { daysOfMonth, daysOfWeek } = useContext(CalenderContext);
const endOfCurrMonth = endOfMonth(today);
const lastDay = getDate(endOfCurrMonth);
// console.info(`This month has ${lastDay} days.`);
const daysOfMonth = [];
for (let i = daysOfMonth.length; i < lastDay; i++) {
daysOfMonth.push(daysOfMonth.length + 1);
}
const daysOfWeek = {
Sunday: [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
],
Monday: [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday",
],
};
// Simulated user settings context
const userSettings = { const userSettings = {
theme: "default", theme: "default",
startOfWeek: "Sunday", startOfWeek: "Sunday",
@@ -54,7 +24,7 @@ const Calender = (): JSX.Element => {
alignContent="center" alignContent="center"
alignItems="center" alignItems="center"
> >
{daysOfWeek[userSettings.startOfWeek].map((weekDay) => { {daysOfWeek.startOfWeek[userSettings.startOfWeek].map((weekDay) => {
return ( return (
<Box <Box
d="flex" d="flex"

View File

@@ -1,25 +1,34 @@
import React from "react"; import React, { useContext } from "react";
import { Heading, HStack, IconButton } from "@chakra-ui/react"; import { Heading, HStack, IconButton } from "@chakra-ui/react";
import { Icon } from "@iconify/react"; import { Icon } from "@iconify/react";
import { format } from "date-fns"; import { format } from "date-fns";
import { CalenderContext } from "../../contexts/CalenderContext";
const CalenderNav = (): JSX.Element => { const CalenderNav = (): JSX.Element => {
const today = new Date(); const { selectedMonth, prevMonth, nextMonth } = useContext(CalenderContext);
const currentMonth = format(today, "LLLL uuuu"); const currentMonth = format(selectedMonth, "LLLL uuuu");
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
aria-label="Previous Month" aria-label="Previous Month"
icon={<Icon icon="akar-icons:chevron-left" />} icon={<Icon icon="akar-icons:chevron-left" />}
onClick={() => prevMonth()}
/> />
<Heading w="100%" h="auto"> <Heading
w="100%"
h="auto"
_hover={{
cursor: "default",
}}
>
{currentMonth} {currentMonth}
</Heading> </Heading>
<IconButton <IconButton
aria-label="Next Month" aria-label="Next Month"
icon={<Icon icon="akar-icons:chevron-right" />} icon={<Icon icon="akar-icons:chevron-right" />}
onClick={() => nextMonth()}
/> />
</HStack> </HStack>
); );

View File

@@ -0,0 +1,144 @@
import React, { createContext, useState, ReactNode, useEffect } from "react";
import { endOfMonth, getDate, sub, add } from "date-fns";
// TODO: import types
type days =
| "Sunday"
| "Monday"
| "Tuesday"
| "Wednesday"
| "Thursday"
| "Friday"
| "Saturday";
interface DaysOfWeek {
startOfWeek: {
Sunday: days[];
Monday: days[];
};
}
interface CalenderContextState {
selectedMonth: Date;
daysOfMonth: [number];
daysOfWeek: DaysOfWeek;
prevMonth: () => void;
nextMonth: () => void;
}
const CalenderContext = createContext({} as CalenderContextState);
const CalenderContextProvider = ({
children,
}: {
children: ReactNode;
}): JSX.Element => {
// Today's date
const [today] = useState<Date>(new Date());
// Selected month & year
const [selectedMonth, setSelectedMonth] = useState<Date>(today);
const [endOfSelectedMonth, SetEndOfSelectedDMonth] = useState<number>(
getDate(endOfMonth(selectedMonth))
);
const [daysOfMonth, setDaysOfMonth] = useState<[number]>([0]);
// Update or populate the days of the month.
const populateDays = (): void => {
let newDaysOfMonth: [number] = [...daysOfMonth];
if (newDaysOfMonth.length > 1) {
newDaysOfMonth = [0];
}
for (let i = 1; i < endOfSelectedMonth; i++) {
if (newDaysOfMonth[i - 1] === 0) {
newDaysOfMonth[i - 1] = i;
} else {
newDaysOfMonth.push(i + 1);
}
}
setDaysOfMonth(newDaysOfMonth);
};
// Update selected month sates when the selected month is updated.
// Update days of month.
useEffect(() => {
if (daysOfMonth === null) {
populateDays();
} else {
if (daysOfMonth[daysOfMonth.length - 1] !== endOfSelectedMonth) {
populateDays();
}
}
}, [selectedMonth, endOfSelectedMonth]);
// Update end of month.
useEffect(() => {
if (endOfSelectedMonth !== getDate(endOfMonth(selectedMonth))) {
SetEndOfSelectedDMonth(getDate(endOfMonth(selectedMonth)));
}
}, [selectedMonth]);
// Calender Layout
const daysOfWeek: DaysOfWeek = {
startOfWeek: {
Sunday: [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
],
Monday: [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday",
],
},
};
//TODO: Create an object of arrays that will align with the days on the week. Make two sets for each start of the week setting.
// Navigation
const prevMonth = (): void => {
const newMonth = sub(selectedMonth, {
months: 1,
});
setSelectedMonth(newMonth);
};
const nextMonth = (): void => {
const newMonth = add(selectedMonth, {
months: 1,
});
setSelectedMonth(newMonth);
};
const calenderContextValues = {
selectedMonth,
daysOfMonth,
daysOfWeek,
prevMonth,
nextMonth,
};
return (
<CalenderContext.Provider value={calenderContextValues}>
{children}
</CalenderContext.Provider>
);
};
export { CalenderContextProvider, CalenderContext };

View File

@@ -17,10 +17,10 @@
}, },
"dependencies": { "dependencies": {
"@chakra-ui/react": "^1.7.2", "@chakra-ui/react": "^1.7.2",
"@emotion/react": "^11.6.0", "@emotion/react": "^11.7.0",
"@emotion/styled": "^11.6.0", "@emotion/styled": "^11.6.0",
"@types/react": "^17.0.37", "@types/react": "^17.0.37",
"date-fns": "^2.26.0", "date-fns": "^2.27.0",
"framer-motion": "^5.3.3", "framer-motion": "^5.3.3",
"next": "12.0.4", "next": "12.0.4",
"react": "17.0.2", "react": "17.0.2",

View File

@@ -1,11 +1,14 @@
import React from "react"; import React from "react";
import { Box } from "@chakra-ui/react"; import { Box } from "@chakra-ui/react";
import Calender from "../components/calender/Calender"; import Calender from "../components/calender/Calender";
import { CalenderContextProvider } from "../contexts/CalenderContext";
const IndexPage = (): JSX.Element => { 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">
<Calender /> <CalenderContextProvider>
<Calender />
</CalenderContextProvider>
</Box> </Box>
); );
}; };

View File

@@ -1,4 +1,4 @@
import React/*, { useEffect, useRef, useState }*/ from "react"; import React /*, { useEffect, useRef, useState }*/ from "react";
import { import {
Box, Box,
Text, Text,
@@ -74,10 +74,7 @@ const Footer = (): JSX.Element => {
target="_blank" target="_blank"
rel="noopener" rel="noopener"
> >
<Button <Button color="whiteAlpha" variant="credits">
color="whiteAlpha"
variant="credits"
>
More About This App More About This App
</Button> </Button>
</Link> </Link>
@@ -101,8 +98,7 @@ const Footer = (): JSX.Element => {
<Text color="brand.footerText" fontSize="xs"> <Text color="brand.footerText" fontSize="xs">
&copy; &copy;
{" 2021 - "} {" 2021 - "}
{new Date().getFullYear()} {new Date().getFullYear()}{" "}
{" "}
<Link <Link
href="https://lucidcreations.media" href="https://lucidcreations.media"
rel="noopener" rel="noopener"

View File

@@ -4,19 +4,16 @@ import {
HStack, HStack,
Box, Box,
IconButton, IconButton,
Flex,
Menu, Menu,
MenuButton, MenuButton,
VStack,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { Icon } from "@iconify/react"; import { Icon } from "@iconify/react";
import DesktopNav from "./DesktopNav"; import DesktopNav from "./DesktopNav";
import MobileNav from "./MobileNav"; import MobileNav from "./MobileNav";
const Header = (): JSX.Element => { const Header = (): JSX.Element => {
const appName = "LCM Potty Chart" const appName = "LCM Potty Chart";
const appVersion = "v0.0.2.5-pre-alpha" const appVersion = "v0.0.3.0-pre-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);
@@ -85,8 +82,8 @@ const Header = (): JSX.Element => {
open open
? "brand.main" ? "brand.main"
: transparentNavbar : transparentNavbar
? "rgba(49, 56, 220, 0.9)" ? "rgba(49, 56, 220, 0.9)"
: "brand.main" : "brand.main"
} }
transition=".5s ease" transition=".5s ease"
borderRadius="0px 0px 10px 10px" borderRadius="0px 0px 10px 10px"
@@ -109,6 +106,9 @@ const Header = (): JSX.Element => {
ml={4} ml={4}
d={{ base: "flex", lg: "none" }} d={{ base: "flex", lg: "none" }}
spacing="5px" spacing="5px"
_hover={{
cursor: "default",
}}
> >
<Heading as="h1" size="md"> <Heading as="h1" size="md">
{appName} {appName}
@@ -119,7 +119,13 @@ const Header = (): JSX.Element => {
</HStack> </HStack>
{/* Desktop Nav Items and Mobile Menu Button */} {/* Desktop Nav Items and Mobile Menu Button */}
<HStack w="100%" px={4} h={12} alignItems="center" justifyContent="space-between" > <HStack
w="100%"
px={4}
h={12}
alignItems="center"
justifyContent="space-between"
>
<HStack <HStack
w="100%" w="100%"
h="auto" h="auto"
@@ -133,6 +139,9 @@ const Header = (): JSX.Element => {
alignItems="center" alignItems="center"
height="auto" height="auto"
spacing="5px" spacing="5px"
_hover={{
cursor: "default",
}}
> >
<Heading as="h1" size="md"> <Heading as="h1" size="md">
{appName} {appName}
@@ -154,9 +163,7 @@ const Header = (): JSX.Element => {
onMouseLeave={() => setHover(false)} onMouseLeave={() => setHover(false)}
d={{ base: "inline-flex", lg: "none" }} d={{ base: "inline-flex", lg: "none" }}
variant="mobileNav" variant="mobileNav"
bg={ bg={transparentNavbar ? "transparent" : "rgba(255, 255, 255, .15)"}
transparentNavbar ? "transparent" : "rgba(255, 255, 255, .15)"
}
type="button" type="button"
border={transparentNavbar ? "1px solid #0068ff" : "none"} border={transparentNavbar ? "1px solid #0068ff" : "none"}
id="mobile-menu-button" id="mobile-menu-button"

View File

@@ -1031,9 +1031,9 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@emotion/react@npm:^11.6.0": "@emotion/react@npm:^11.7.0":
version: 11.6.0 version: 11.7.0
resolution: "@emotion/react@npm:11.6.0" resolution: "@emotion/react@npm:11.7.0"
dependencies: dependencies:
"@babel/runtime": ^7.13.10 "@babel/runtime": ^7.13.10
"@emotion/cache": ^11.6.0 "@emotion/cache": ^11.6.0
@@ -1050,7 +1050,7 @@ __metadata:
optional: true optional: true
"@types/react": "@types/react":
optional: true optional: true
checksum: 4fb2d108dc32716d1f162026ac5fdbd0662e3b435a34fb324629d72bb6bff61b18ac8975b51457c16ffa41543bade5d07558566ab76420b3926fbb9159441232 checksum: 8b50d61caabe04ae413ae23b98c170da643754ec89f25eb001464095685686585d0f88988bc36432f231e6de6abdbee73308c42ba427de9eaaf5a54d7f2f6ae5
languageName: node languageName: node
linkType: hard linkType: hard
@@ -2637,10 +2637,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"date-fns@npm:^2.26.0": "date-fns@npm:^2.27.0":
version: 2.26.0 version: 2.27.0
resolution: "date-fns@npm:2.26.0" resolution: "date-fns@npm:2.27.0"
checksum: 49ad59bc788134a6552ef4e4af0d18792001c1ca0070d543de4f36aba5761058b6e6a57b8ca51dd3b0f07f3bd55376b8bc69602bd7940648ba3869c5253c6ae8 checksum: db62036b3816eb0322c9532b353beac7f660a91e1a55dbd21c14893c621ebb8509f21c66ba287844dabd34dee0207edd54a9537bce6bb7cab9383dedc6b8bc90
languageName: node languageName: node
linkType: hard linkType: hard
@@ -4402,12 +4402,12 @@ __metadata:
resolution: "lucid-creations-media-potty-chart@workspace:." resolution: "lucid-creations-media-potty-chart@workspace:."
dependencies: dependencies:
"@chakra-ui/react": ^1.7.2 "@chakra-ui/react": ^1.7.2
"@emotion/react": ^11.6.0 "@emotion/react": ^11.7.0
"@emotion/styled": ^11.6.0 "@emotion/styled": ^11.6.0
"@iconify/react": ^3.1.0 "@iconify/react": ^3.1.0
"@types/react": ^17.0.37 "@types/react": ^17.0.37
"@typescript-eslint/eslint-plugin": ^5.4.0 "@typescript-eslint/eslint-plugin": ^5.4.0
date-fns: ^2.26.0 date-fns: ^2.27.0
eslint: <8.0.0 eslint: <8.0.0
eslint-config-next: 12.0.3 eslint-config-next: 12.0.3
eslint-config-prettier: ^8.3.0 eslint-config-prettier: ^8.3.0