Skip to content

Commit 535d3b2

Browse files
Save the code and add checkpoint so the users can start from where they left off (#102)
* Save the code and a checkpoint so the users can start from where they left off * fixed required changes. * fix: format code * refactor: Add Nullish coalescing operator * refactor: added global state management * refactor: changed variable names * refactor: fixed minor bug * added continue button * refactor * rename class * fix rename * minor change * format files --------- Co-authored-by: JeelRajodiya <[email protected]>
1 parent 14a864e commit 535d3b2

File tree

11 files changed

+178
-10
lines changed

11 files changed

+178
-10
lines changed

app/components/CodeEditor/CodeEditor.tsx

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { OutputReducerAction } from "@/lib/reducers";
1212
import { validateCode } from "@/lib/client-functions";
1313
import FiChevronRight from "@/app/styles/icons/HiChevronRightGreen";
1414
import { useRouter } from "next/navigation";
15-
import { useEditorStore } from "@/lib/stores";
15+
import { useUserSolutionStore, useEditorStore } from "@/lib/stores";
1616
import { sendGAEvent } from "@next/third-parties/google";
1717

1818
export default function CodeEditor({
@@ -38,6 +38,7 @@ export default function CodeEditor({
3838
const [monaco, setMonaco] = useState<any>(null);
3939
const router = useRouter();
4040
const editorStore = useEditorStore();
41+
const userSolutionStore = useUserSolutionStore();
4142

4243
useEffect(() => {
4344
if (monaco) {
@@ -76,6 +77,31 @@ export default function CodeEditor({
7677
document.removeEventListener("keydown", handleKeyDown);
7778
};
7879
}, [codeString]);
80+
81+
useEffect(() => {
82+
const savedCode = userSolutionStore.getSavedUserSolutionByLesson(
83+
chapterIndex,
84+
stepIndex,
85+
);
86+
if (savedCode && savedCode !== codeString) {
87+
setCodeString(savedCode);
88+
}
89+
}, [chapterIndex, stepIndex]);
90+
91+
useEffect(() => {
92+
userSolutionStore.saveUserSolutionForLesson(
93+
chapterIndex,
94+
stepIndex,
95+
codeString,
96+
);
97+
}, [codeString, chapterIndex, stepIndex]);
98+
99+
useEffect(() => {
100+
if (Object.keys(userSolutionStore.userSolutionsByLesson).length == 0) {
101+
setCodeString(JSON.stringify(codeFile.code, null, 2));
102+
}
103+
}, [userSolutionStore]);
104+
79105
return (
80106
<>
81107
<div className={ctx(styles.codeEditor, GeistMono.className)}>
@@ -85,7 +111,7 @@ export default function CodeEditor({
85111
theme={colorMode === "light" ? "light" : "my-theme"}
86112
value={codeString}
87113
height={"100%"}
88-
onChange={(codeString) => setCodeString(codeString ? codeString : "")}
114+
onChange={(codeString) => setCodeString(codeString ?? "")}
89115
options={{ minimap: { enabled: false }, fontSize: 14 }}
90116
onMount={(editor, monaco) => {
91117
setMonaco(monaco);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.continueBtn {
2+
display: flex;
3+
gap: 5px;
4+
}
5+
6+
.rightIcon {
7+
display: flex;
8+
justify-content: center;
9+
align-items: center;
10+
width: 10px;
11+
height: 10px;
12+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"use client";
2+
3+
import { useRouter } from "next/navigation";
4+
import { getCheckPoint } from "@/lib/progressSaving";
5+
import styles from "./ContinueBtn.module.css";
6+
import RightArrow from "@/app/styles/icons/RightArrow";
7+
import { Button } from "@chakra-ui/react";
8+
9+
export default function ContinueBtn() {
10+
const router = useRouter();
11+
const checkpoint = getCheckPoint();
12+
13+
const handleClick = () => {
14+
const checkpoint = getCheckPoint();
15+
if (checkpoint) {
16+
router.push(`/${checkpoint}`);
17+
}
18+
};
19+
20+
return (
21+
<>
22+
{checkpoint && (
23+
<Button
24+
variant={"default"}
25+
onClick={handleClick}
26+
size={"sm"}
27+
className={styles.continueBtn}
28+
>
29+
Continue
30+
<div className={styles.rightIcon}>
31+
<RightArrow />
32+
</div>
33+
</Button>
34+
)}
35+
</>
36+
);
37+
38+
return null;
39+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as default } from "./ContinueBtn";

app/components/NavBarMenus/NavBarMenus.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
import React, { useState } from "react";
2222
import navBarStyles from "../NavBar/NavBar.module.css";
2323
import { sendGAEvent } from "@next/third-parties/google";
24+
import { useUserSolutionStore } from "@/lib/stores";
2425

2526
export default function NavBarMenu() {
2627
const { colorMode } = useColorMode();
@@ -29,6 +30,8 @@ export default function NavBarMenu() {
2930

3031
const toast = useToast();
3132

33+
const userSolutionStore = useUserSolutionStore();
34+
3235
return (
3336
<Menu closeOnSelect={false} gutter={4}>
3437
<MenuButton
@@ -75,6 +78,7 @@ export default function NavBarMenu() {
7578
mt={2}
7679
onClick={() => {
7780
localStorage.removeItem("progress");
81+
userSolutionStore.clearAllCode();
7882
setIsOpen(false);
7983
toast({
8084
title: "Progress Cleared",

app/content/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
import React from "react";
33
import styles from "./layout.module.css";
44
import NavBar from "@/app/components/NavBar";
5-
import { contentManager } from "@/lib/contentManager";
65
import { usePathname } from "next/navigation";
6+
import { setCheckpoint } from "@/lib/progressSaving";
77

88
export default function PageLayout({
99
children,
@@ -12,7 +12,7 @@ export default function PageLayout({
1212
params: { markdownPath: string[] };
1313
}) {
1414
const urlPath = usePathname().replace("/content", "").substring(1);
15-
15+
setCheckpoint(`content/${urlPath}`);
1616
return (
1717
<div className={styles.wrapper}>
1818
<NavBar urlPath={urlPath} />

app/page.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import styles from "./styles/page.module.css";
22
import cx from "classnames";
33
import { interFont, outfitFont } from "./styles/fonts";
4-
import CompanyLogos from "./components/CommunityLinks/CommunityLinks";
5-
import HomePageLinks from "./components/HomePageLinks/HomePageLinks";
6-
import { Flex } from "@chakra-ui/react";
7-
4+
import CompanyLogos from "./components/CommunityLinks";
5+
import HomePageLinks from "./components/HomePageLinks";
6+
import dynamic from "next/dynamic";
7+
const ContinueBtn = dynamic(() => import("./components/ContinueBtn"), {
8+
ssr: false,
9+
});
810
export default function Home() {
911
return (
1012
<div className={cx(styles.main, outfitFont.className)}>
@@ -25,7 +27,12 @@ export default function Home() {
2527
</div>
2628
</div>
2729
</div>
28-
<HomePageLinks />
30+
<div className={styles.homePageLinksWrapper}>
31+
<HomePageLinks />
32+
<div className={styles.continueBtnWrapper}>
33+
<ContinueBtn />
34+
</div>
35+
</div>
2936
</div>
3037
<div className={styles.footer}>
3138
<div className={cx(styles.footerText, interFont.className)}>

app/styles/page.module.css

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,14 @@
6666
gap: 0px;
6767
justify-content: center;
6868
}
69-
69+
.homePageLinksWrapper {
70+
display: flex;
71+
align-items: center;
72+
}
73+
.continueBtnWrapper {
74+
position: absolute;
75+
margin-left: 500px;
76+
}
7077
.footer {
7178
display: flex;
7279
flex-direction: column;

lib/contentVariables.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// variables to generate the outline.json and iterate through the content
22

33
export const contentFolderPath: string = "./content";
4+
45
export const contentFolderName: string = contentFolderPath.replace("./", "");
56
export const indexFileName = "index.mdx";
67
export const instructionsFileName = "instructions.mdx";

lib/progressSaving.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export function setCheckpoint(path: string) {
2+
if (typeof window === "undefined") return false;
3+
const checkpoint = path;
4+
5+
localStorage.setItem("checkPoint", JSON.stringify(checkpoint));
6+
}
7+
8+
export function getCheckPoint() {
9+
if (typeof window === "undefined") return false;
10+
11+
const checkpoint = localStorage.getItem("checkPoint");
12+
13+
if (checkpoint) {
14+
return JSON.parse(checkpoint);
15+
}
16+
return null;
17+
}

0 commit comments

Comments
 (0)