Tutorial #62

Merged
LucidKobold merged 32 commits from tutorial into main 2022-06-24 15:51:02 -04:00
14 changed files with 317 additions and 42 deletions
Showing only changes of commit 9506e5b43c - Show all commits

View File

@@ -2,7 +2,7 @@
"private": true,
"name": "lucid-creations-media-potty-chart",
"homepage": "https://lucidcreations.media/introducing-code-name-potty-chart/",
"version": "v0.0.11-alpha",
"version": "0.0.11",
"author": {
"name": "Lucid Creations Media",
"url": "https://lucidcreations.media",

View File

@@ -1,11 +1,13 @@
import { configureStore } from "@reduxjs/toolkit";
import calenderReducer from "../features/calender/calender";
import calenderReducer from "../features/calender";
import stickersReducer from "../features/calender/stickers";
import tutorialReducer from "../features/tutorial";
export const store = configureStore({
reducer: {
calender: calenderReducer,
stickers: stickersReducer
stickers: stickersReducer,
tutorial: tutorialReducer
}
});

View File

@@ -2,7 +2,7 @@ import React, { useEffect } from "react";
import { Box, HStack, SimpleGrid, Text, VStack } from "@chakra-ui/react";
import { isSameDay, format } from "date-fns";
import { useAppDispatch, useAppSelector } from "../../app/hooks";
import { updateCurrDate, updateMonth } from "../../features/calender/calender";
import { updateCurrDate, updateMonth } from "../../features/calender";
import CalenderNav from "./CalenderNav";
import Day from "./Day";
@@ -43,12 +43,12 @@ const Calender = ({
}, [dispatch, newDate]);
useEffect(() => {
console.info("Check to update date.");
// console.info("Check to update date.");
const currDateObj = new Date(currDate);
if (!isSameDay(currDateObj, new Date())) {
console.info("Updated date.");
// console.info("Updated date.");
dispatch(updateCurrDate());
}
}, [currDate, dispatch]);

View File

@@ -1,20 +1,39 @@
import { Box, Button, Heading } from "@chakra-ui/react";
import { Box, Button, Heading, HStack, VStack } from "@chakra-ui/react";
import React from "react";
interface TutorialProps {
setTutorialCookie: (bool: boolean) => void;
setTutorialComplete: () => void;
setTempTutorialComplete: () => void;
}
const Tutorial = ({ setTutorialCookie }: TutorialProps): JSX.Element => {
const handleSetCookieButton = (): void => {
setTutorialCookie(true);
};
const Tutorial = ({
setTutorialComplete,
setTempTutorialComplete
}: TutorialProps): JSX.Element => {
return (
<Box>
<VStack
h="auto"
w="100%"
justifyContent="center"
alignContent="center"
spacing={6}
>
<Heading>{"Tutorial Component"}</Heading>
<Button type="button" onClick={() => handleSetCookieButton()}>
<HStack
h="auto"
w="80%"
justifyContent="space-between"
alignContent="center"
>
<Button type="button" onClick={() => setTutorialComplete()}>
{"Complete Tutorial (remember)"}
</Button>
<Button type="button" onClick={() => setTempTutorialComplete()}>
{"Complete Tutorial"}
</Button>
</HStack>
</VStack>
</Box>
);
};

View File

@@ -0,0 +1,109 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { addMonths } from "date-fns";
interface StorageState {
exp: string;
version: string;
completed: boolean;
}
// * Storage Helpers * //
const setTempStorage = (storageState: StorageState): void => {
sessionStorage.setItem("completedTutorial", JSON.stringify(storageState));
};
const getTempStorage = (): StorageState | null => {
return JSON.parse(sessionStorage.getItem("completedTutorial"));
};
const clearTempStorage = (): void => {
sessionStorage.removeItem("completedTutorial");
};
const setStorage = (storageState: StorageState): void => {
localStorage.setItem("completedTutorial", JSON.stringify(storageState));
};
const getStorage = (): StorageState | null => {
return JSON.parse(localStorage.getItem("completedTutorial"));
};
const clearStorage = (): void => {
localStorage.removeItem("completedTutorial");
};
interface TutorialSlice {
completedTutorial: boolean | null;
storageState: StorageState | null;
}
const initialState: TutorialSlice = {
completedTutorial: null,
storageState: null
};
const tutorialSlice = createSlice({
name: "Tutorial",
initialState,
reducers: {
// Set temp complete
setTempTutorialComplete(state: TutorialSlice) {
const exp: string = addMonths(new Date(), 1).toJSON();
const version: string = process.env.NEXT_PUBLIC_APP_VERSION.split("-")[0];
const storageState: StorageState = {
exp,
version,
completed: true
};
setTempStorage(storageState);
state.storageState = storageState;
state.completedTutorial = true;
},
// Set completed (remember)
setTutorialCompleted(state: TutorialSlice) {
const exp: string = addMonths(new Date(), 1).toJSON();
const version: string = process.env.NEXT_PUBLIC_APP_VERSION.split("-")[0];
const storageState: StorageState = {
exp,
version,
completed: true
};
setStorage(storageState);
state.storageState = storageState;
state.completedTutorial = true;
},
// Clear states and storages
clearTutorialCompleted(state: TutorialSlice) {
clearTempStorage();
clearStorage();
state.storageState = null;
state.completedTutorial = null;
},
// Get and set states
getAndSetTutorial(state: TutorialSlice) {
console.log("get and set tutorial states");
const temp = getTempStorage();
const local = getStorage();
if (temp !== null || local !== null) {
state.storageState = temp !== null ? temp : local;
state.completedTutorial = temp !== null ? temp.completed : local.completed;
}
if (temp === null && local === null) {
state.completedTutorial = false;
}
}
}
});
export const {
setTempTutorialComplete,
setTutorialCompleted,
clearTutorialCompleted,
getAndSetTutorial
} = tutorialSlice.actions;
export default tutorialSlice.reducer;

View File

@@ -20,14 +20,16 @@ const DateRoute: React.FC<unknown> = () => {
const router = useRouter();
const { date: slug } = router.query;
const [date, setDate] = useState<UpdateCalendarProps | null>(null);
const [date, setDate] = useState<UpdateCalenderPropsDateLayout | null>(null);
const [error, setError] = useState<boolean>(false);
// const dateRange = useRef(findValidDateRange());
// const validDateRange = Object.assign({}, dateRange.current);
const validateDateInput = (dateArr: number[]): UpdateCalendarProps => {
const validateDateInput = (
dateArr: number[]
): UpdateCalenderPropsDateLayout => {
if (!(dateArr.length >= 2) && !(dateArr.length <= 3)) {
return {
year: 0,
@@ -198,7 +200,7 @@ const DateRoute: React.FC<unknown> = () => {
) : (
<Box textAlign="center" w="100%" h="auto" pt="50px" pb="10vh">
<Provider store={store}>
<Calender {...date} />
<Calender date={date} isLoading={false} />
</Provider>
</Box>
);

View File

@@ -1,16 +1,27 @@
import React, { Fragment, useEffect, useRef, useState } from "react";
import { Box } from "@chakra-ui/react";
import { addMonths, format } from "date-fns";
import { format } from "date-fns";
import Calender from "../components/calender";
import Tutorial from "../components/tutorial";
import LoadingOverlay from "../components/loading/LoadingOverlay";
import { Provider } from "react-redux";
import { store } from "../app/store";
import { useAppDispatch, useAppSelector } from "../app/hooks";
import { updateLoading } from "../features/calender/calender";
import { updateLoading } from "../features/calender";
import {
getAndSetTutorial,
setTempTutorialComplete,
setTutorialCompleted
} from "../features/tutorial";
const IndexPage = (): JSX.Element => {
const isLoading = useAppSelector((state) => state.calender.isLoading);
const completedTutorial = useAppSelector(
(state) => state.tutorial.completedTutorial
);
const tutorialCompletionInfo = useAppSelector(
(state) => state.tutorial.storageState
);
const dispatch = useAppDispatch();
const currDate = useRef<UpdateCalenderPropsDateLayout>({
@@ -19,25 +30,26 @@ const IndexPage = (): JSX.Element => {
day: parseInt(format(new Date(), "d"))
});
const [completedTutorial, setCompletedTutorial] = useState<boolean | null>(
null
);
const getTutorialCookie = (): boolean => {
return JSON.parse(localStorage.getItem("tutorialCompleted")) || false;
const handleTempTutorialCompleted = (): void => {
dispatch(setTempTutorialComplete());
};
const setTutorialCookie = (bool: boolean): void => {
localStorage.setItem("tutorialCompleted", `${bool}`);
setCompletedTutorial(true);
const handleTutorialCompleted = (): void => {
dispatch(setTutorialCompleted());
};
useEffect(() => {
if (completedTutorial === null || tutorialCompletionInfo === null) {
dispatch(getAndSetTutorial());
dispatch(updateLoading(false));
}
if (completedTutorial !== null) {
dispatch(updateLoading(false));
}
setCompletedTutorial(getTutorialCookie());
}, [completedTutorial, dispatch]);
console.info("use effect", completedTutorial, tutorialCompletionInfo);
}, [completedTutorial, dispatch, tutorialCompletionInfo]);
return (
<Box
@@ -49,7 +61,7 @@ const IndexPage = (): JSX.Element => {
minWidth="min-content"
>
<Provider store={store}>
{completedTutorial === null ? (
{isLoading === true ? (
<Fragment>
<LoadingOverlay />
<Calender date={currDate.current} isLoading={isLoading} />
@@ -57,7 +69,10 @@ const IndexPage = (): JSX.Element => {
) : completedTutorial ? (
<Calender date={currDate.current} isLoading={isLoading} />
) : (
<Tutorial setTutorialCookie={setTutorialCookie} />
<Tutorial
setTutorialComplete={handleTutorialCompleted}
setTempTutorialComplete={handleTempTutorialCompleted}
/>
)}
</Provider>
</Box>

View File

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