From 1f727d2e1748dc4b885c76ca5ab351f3d133eb24 Mon Sep 17 00:00:00 2001
From: Gleison <126490844+gvieira-dutra@users.noreply.github.com>
Date: Mon, 17 Mar 2025 11:57:14 -0400
Subject: [PATCH 1/6] feat: add content for StyleCop (#8337)

* Added content for StyleCop section

* Update src/data/roadmaps/aspnet-core/content/stylecop-rules@R7Qk5hsEIl9dspQXdaJAJ.md

* Update src/data/roadmaps/aspnet-core/content/stylecop-rules@R7Qk5hsEIl9dspQXdaJAJ.md

---------

Co-authored-by: Arik Chakma <arikchangma@gmail.com>
---
 .../content/stylecop-rules@R7Qk5hsEIl9dspQXdaJAJ.md   | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/data/roadmaps/aspnet-core/content/stylecop-rules@R7Qk5hsEIl9dspQXdaJAJ.md b/src/data/roadmaps/aspnet-core/content/stylecop-rules@R7Qk5hsEIl9dspQXdaJAJ.md
index 90022a147..9bb092720 100644
--- a/src/data/roadmaps/aspnet-core/content/stylecop-rules@R7Qk5hsEIl9dspQXdaJAJ.md
+++ b/src/data/roadmaps/aspnet-core/content/stylecop-rules@R7Qk5hsEIl9dspQXdaJAJ.md
@@ -1 +1,10 @@
-# StyleCop Rules
\ No newline at end of file
+# StyleCop Rules
+
+StyleCop is a tool used for developers to standardize their code and ensure they all follow the same syntax principles. With StyleCop, one standard can be defined in a `stylecop.json` file and shared across your team so that each member has the same guidelines when formatting your code. Beyond a single project, StyleCop can also be added as an extension, so all of the projects on your IDE follow the same formatting rules, this is especially useful if your organization follows the same rule standards for all projects.
+
+Visit the following resources to learn more:
+
+- [@opensource@StyleCop GitHub official page](https://github.com/StyleCop/StyleCop)
+- [@opensource@StyeleCop Analyzers, a more modern version of StyleCop](https://github.com/DotNetAnalyzers/StyleCopAnalyzers)
+- [@video@The StyleCop setup and Advantages](https://www.youtube.com/watch?v=dmpOKmz3lPw)
+- [@article@StyleCop: A Detailed Guide to Starting and Using It](https://blog.submain.com/stylecop-detailed-guide/)

From 16db649baf4b88b7c6a24ed5cd54d329470b887a Mon Sep 17 00:00:00 2001
From: Jawher Kl <kalleljawher4@gmail.com>
Date: Mon, 17 Mar 2025 20:22:18 +0100
Subject: [PATCH 2/6] fix: broken link (#8334)

---
 .../qa/content/regression-testing@XCeXiKvBblmDArfbWjDvw.md    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/data/roadmaps/qa/content/regression-testing@XCeXiKvBblmDArfbWjDvw.md b/src/data/roadmaps/qa/content/regression-testing@XCeXiKvBblmDArfbWjDvw.md
index 935a4c199..9ab5bda98 100644
--- a/src/data/roadmaps/qa/content/regression-testing@XCeXiKvBblmDArfbWjDvw.md
+++ b/src/data/roadmaps/qa/content/regression-testing@XCeXiKvBblmDArfbWjDvw.md
@@ -4,6 +4,6 @@ Regression Testing is a type of software testing to confirm that a recent progra
 
 Visit the following resources to learn more:
 
-- [@article@Regression Testing](https://www.javatpoint.com/regression-testing)
+- [@article@Regression Testing](https://www.tpointtech.com/regression-testing)
 - [@article@What is Regression Testing with Test Cases](https://www.guru99.com/regression-testing.html)
-- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)
\ No newline at end of file
+- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)

From 98d8510b6007147e21f0f2f76340c62cb240740d Mon Sep 17 00:00:00 2001
From: Kamran Ahmed <kamranahmed.se@gmail.com>
Date: Mon, 17 Mar 2025 17:15:35 +0000
Subject: [PATCH 3/6] Add UI

---
 src/components/GenerateCourse/AICourse.tsx    |  3 +
 .../GenerateCourse/FineTuneCourse.tsx         | 83 +++++++++++++++++++
 2 files changed, 86 insertions(+)
 create mode 100644 src/components/GenerateCourse/FineTuneCourse.tsx

diff --git a/src/components/GenerateCourse/AICourse.tsx b/src/components/GenerateCourse/AICourse.tsx
index 7d4ea4326..8a92cf99f 100644
--- a/src/components/GenerateCourse/AICourse.tsx
+++ b/src/components/GenerateCourse/AICourse.tsx
@@ -4,6 +4,7 @@ import { cn } from '../../lib/classname';
 import { isLoggedIn } from '../../lib/jwt';
 import { showLoginPopup } from '../../lib/popup';
 import { UserCoursesList } from './UserCoursesList';
+import { FineTuneCourse } from './FineTuneCourse';
 
 export const difficultyLevels = [
   'beginner',
@@ -98,6 +99,8 @@ export function AICourse(props: AICourseProps) {
               </div>
             </div>
 
+            <FineTuneCourse />
+
             <button
               type="submit"
               disabled={!keyword.trim()}
diff --git a/src/components/GenerateCourse/FineTuneCourse.tsx b/src/components/GenerateCourse/FineTuneCourse.tsx
new file mode 100644
index 000000000..6cf09361a
--- /dev/null
+++ b/src/components/GenerateCourse/FineTuneCourse.tsx
@@ -0,0 +1,83 @@
+import { useState } from 'react';
+import { cn } from '../../lib/classname';
+
+type QuestionProps = {
+  label: string;
+  placeholder: string;
+  autoFocus?: boolean;
+  value: string;
+  onChange: (value: string) => void;
+};
+
+function Question(props: QuestionProps) {
+  const { label, placeholder, value, onChange, autoFocus = false } = props;
+
+  return (
+    <div className="flex flex-col">
+      <label className="bg-gray-100 border-y px-4 py-2.5 text-sm font-medium text-gray-700">
+        {label}
+      </label>
+      <textarea
+        placeholder={placeholder}
+        className="min-h-[80px] w-full resize-none px-4 py-3 text-gray-700 placeholder:text-gray-400 focus:outline-none"
+        value={value}
+        onChange={(e) => onChange(e.target.value)}
+        autoFocus={autoFocus}
+      />
+    </div>
+  );
+}
+
+export function FineTuneCourse() {
+  const [isFineTuning, setIsFineTuning] = useState(false);
+
+  const [about, setAbout] = useState('');
+  const [goal, setGoal] = useState('');
+  const [customInstructions, setCustomInstructions] = useState('');
+
+  return (
+    <div className="flex flex-col overflow-hidden rounded-lg border border-gray-200 transition-all">
+      <label
+        className={cn(
+          'group flex cursor-pointer select-none flex-row items-center gap-2.5 px-4 py-3 text-left text-gray-500 transition-colors hover:bg-gray-100 focus:outline-none',
+          isFineTuning && 'bg-gray-100',
+        )}
+      >
+        <input
+          id="fine-tune-checkbox"
+          type="checkbox"
+          className="h-4 w-4 group-hover:fill-current"
+          onChange={() => setIsFineTuning(!isFineTuning)}
+        />
+        Tell us more to tailor the course (optional){' '}
+        <span className="ml-auto rounded-md bg-gray-400 px-2 py-0.5 text-xs text-white">
+          recommended
+        </span>
+      </label>
+
+      {isFineTuning && (
+        <div className="mt-0 flex flex-col">
+          <Question
+            label="Tell us about your self"
+            placeholder="e.g. I have a background in marketing and I already have some basic knowledge of coding."
+            value={about}
+            onChange={setAbout}
+            autoFocus={true}
+          />
+          <Question
+            label="What is your goal with this course?"
+            placeholder="e.g. I want to learn about advanced topics with focus on practical examples."
+            value={goal}
+            onChange={setGoal}
+          />
+          <Question
+            label="Custom Instructions (Optional)"
+            placeholder="Give instructions to the AI as if you were giving them to a friend."
+            value={customInstructions}
+            onChange={setCustomInstructions}
+          />
+        </div>
+      )}
+    </div>
+  );
+}

From 340ae002ca2c80e83c5b1c00ce0d4bf12ed0b401 Mon Sep 17 00:00:00 2001
From: Kamran Ahmed <kamranahmed.se@gmail.com>
Date: Mon, 17 Mar 2025 23:53:21 +0000
Subject: [PATCH 4/6] Improve fine-tuning

---
 src/components/GenerateCourse/AICourse.tsx    | 49 +++++++++++++++++--
 .../GenerateCourse/FineTuneCourse.tsx         | 44 ++++++++++++-----
 .../GenerateCourse/GenerateAICourse.tsx       | 44 +++++++++++++++--
 src/helper/generate-ai-course.ts              |  9 ++++
 src/lib/ai.ts                                 | 39 +++++++++++++++
 5 files changed, 167 insertions(+), 18 deletions(-)

diff --git a/src/components/GenerateCourse/AICourse.tsx b/src/components/GenerateCourse/AICourse.tsx
index 8a92cf99f..5fce355b4 100644
--- a/src/components/GenerateCourse/AICourse.tsx
+++ b/src/components/GenerateCourse/AICourse.tsx
@@ -1,10 +1,15 @@
 import { SearchIcon, WandIcon } from 'lucide-react';
-import { useState } from 'react';
+import { useEffect, useState } from 'react';
 import { cn } from '../../lib/classname';
 import { isLoggedIn } from '../../lib/jwt';
 import { showLoginPopup } from '../../lib/popup';
 import { UserCoursesList } from './UserCoursesList';
 import { FineTuneCourse } from './FineTuneCourse';
+import {
+  getCourseFineTuneData,
+  getLastSessionId,
+  storeFineTuneData,
+} from '../../lib/ai';
 
 export const difficultyLevels = [
   'beginner',
@@ -19,6 +24,27 @@ export function AICourse(props: AICourseProps) {
   const [keyword, setKeyword] = useState('');
   const [difficulty, setDifficulty] = useState<DifficultyLevel>('beginner');
 
+  const [hasFineTuneData, setHasFineTuneData] = useState(false);
+  const [about, setAbout] = useState('');
+  const [goal, setGoal] = useState('');
+  const [customInstructions, setCustomInstructions] = useState('');
+
+  useEffect(() => {
+    const lastSessionId = getLastSessionId();
+    if (!lastSessionId) {
+      return;
+    }
+
+    const fineTuneData = getCourseFineTuneData(lastSessionId);
+    if (!fineTuneData) {
+      return;
+    }
+
+    // setAbout(fineTuneData.about);
+    // setGoal(fineTuneData.goal);
+    // setCustomInstructions(fineTuneData.customInstructions);
+  }, []);
+
   const handleKeyDown = (e: React.KeyboardEvent) => {
     if (e.key === 'Enter' && keyword.trim()) {
       onSubmit();
@@ -31,7 +57,15 @@ export function AICourse(props: AICourseProps) {
       return;
     }
 
-    window.location.href = `/ai-tutor/search?term=${encodeURIComponent(keyword)}&difficulty=${difficulty}`;
+    const sessionId = hasFineTuneData
+      ? storeFineTuneData({
+          about,
+          goal,
+          customInstructions,
+        })
+      : '';
+
+    window.location.href = `/ai-tutor/search?term=${encodeURIComponent(keyword)}&difficulty=${difficulty}&id=${sessionId}`;
   }
 
   return (
@@ -99,7 +133,16 @@ export function AICourse(props: AICourseProps) {
               </div>
             </div>
 
-            <FineTuneCourse />
+            <FineTuneCourse
+              hasFineTuneData={hasFineTuneData}
+              setHasFineTuneData={setHasFineTuneData}
+              about={about}
+              goal={goal}
+              customInstructions={customInstructions}
+              setAbout={setAbout}
+              setGoal={setGoal}
+              setCustomInstructions={setCustomInstructions}
+            />
 
             <button
               type="submit"
diff --git a/src/components/GenerateCourse/FineTuneCourse.tsx b/src/components/GenerateCourse/FineTuneCourse.tsx
index 6cf09361a..bc023ec14 100644
--- a/src/components/GenerateCourse/FineTuneCourse.tsx
+++ b/src/components/GenerateCourse/FineTuneCourse.tsx
@@ -14,7 +14,7 @@ function Question(props: QuestionProps) {
 
   return (
     <div className="flex flex-col">
-      <label className="bg-gray-100 border-y px-4 py-2.5 text-sm font-medium text-gray-700">
+      <label className="border-y bg-gray-100 px-4 py-2.5 text-sm font-medium text-gray-700">
         {label}
       </label>
       <textarea
@@ -28,26 +28,46 @@ function Question(props: QuestionProps) {
   );
 }
 
-export function FineTuneCourse() {
-  const [isFineTuning, setIsFineTuning] = useState(false);
+type FineTuneCourseProps = {
+  hasFineTuneData: boolean;
+  about: string;
+  goal: string;
+  customInstructions: string;
 
-  const [about, setAbout] = useState('');
-  const [goal, setGoal] = useState('');
-  const [customInstructions, setCustomInstructions] = useState('');
+  setHasFineTuneData: (hasMetadata: boolean) => void;
+  setAbout: (about: string) => void;
+  setGoal: (goal: string) => void;
+  setCustomInstructions: (customInstructions: string) => void;
+};
+
+export function FineTuneCourse(props: FineTuneCourseProps) {
+  const {
+    about,
+    goal,
+    customInstructions,
+    hasFineTuneData,
+    setAbout,
+    setGoal,
+    setCustomInstructions,
+    setHasFineTuneData,
+  } = props;
 
   return (
     <div className="flex flex-col overflow-hidden rounded-lg border border-gray-200 transition-all">
       <label
         className={cn(
           'group flex cursor-pointer select-none flex-row items-center gap-2.5 px-4 py-3 text-left text-gray-500 transition-colors hover:bg-gray-100 focus:outline-none',
-          isFineTuning && 'bg-gray-100',
+          hasFineTuneData && 'bg-gray-100',
         )}
       >
         <input
           id="fine-tune-checkbox"
           type="checkbox"
           className="h-4 w-4 group-hover:fill-current"
-          onChange={() => setIsFineTuning(!isFineTuning)}
+          checked={hasFineTuneData}
+          onChange={() => {
+            setHasFineTuneData(!hasFineTuneData);
+          }}
         />
         Tell us more to tailor the course (optional){' '}
         <span className="ml-auto rounded-md bg-gray-400 px-2 py-0.5 text-xs text-white">
@@ -55,24 +75,24 @@ export function FineTuneCourse() {
         </span>
       </label>
 
-      {isFineTuning && (
+      {hasFineTuneData && (
         <div className="mt-0 flex flex-col">
           <Question
             label="Tell us about your self"
-            placeholder="e.g. I have a background in marketing and I already have some basic knowledge of coding."
+            placeholder="e.g. I am a frontend developer and have good knowledge of HTML, CSS, and JavaScript."
             value={about}
             onChange={setAbout}
             autoFocus={true}
           />
           <Question
             label="What is your goal with this course?"
-            placeholder="e.g. I want to learn about advanced topics with focus on practical examples."
+            placeholder="e.g. I want to be able to build Node.js APIs with Express.js and MongoDB."
             value={goal}
             onChange={setGoal}
           />
           <Question
             label="Custom Instructions (Optional)"
-            placeholder="Give instructions to the AI as if you were giving them to a friend."
+            placeholder="Give additional instructions to the AI as if you were giving them to a friend."
             value={customInstructions}
             onChange={setCustomInstructions}
           />
diff --git a/src/components/GenerateCourse/GenerateAICourse.tsx b/src/components/GenerateCourse/GenerateAICourse.tsx
index 8687d7944..95ea38935 100644
--- a/src/components/GenerateCourse/GenerateAICourse.tsx
+++ b/src/components/GenerateCourse/GenerateAICourse.tsx
@@ -1,7 +1,7 @@
 import { useEffect, useState } from 'react';
 import { getUrlParams } from '../../lib/browser';
 import { isLoggedIn } from '../../lib/jwt';
-import { type AiCourse } from '../../lib/ai';
+import { getCourseFineTuneData, type AiCourse } from '../../lib/ai';
 import { AICourseContent } from './AICourseContent';
 import { generateCourse } from '../../helper/generate-ai-course';
 import { useQuery } from '@tanstack/react-query';
@@ -13,6 +13,10 @@ type GenerateAICourseProps = {};
 export function GenerateAICourse(props: GenerateAICourseProps) {
   const [term, setTerm] = useState('');
   const [difficulty, setDifficulty] = useState('');
+  const [sessionId, setSessionId] = useState('');
+  const [goal, setGoal] = useState('');
+  const [about, setAbout] = useState('');
+  const [customInstructions, setCustomInstructions] = useState('');
 
   const [isLoading, setIsLoading] = useState(true);
   const [error, setError] = useState('');
@@ -54,16 +58,47 @@ export function GenerateAICourse(props: GenerateAICourseProps) {
 
     setTerm(paramsTerm);
     setDifficulty(paramsDifficulty);
-    handleGenerateCourse({ term: paramsTerm, difficulty: paramsDifficulty });
+
+    const sessionId = params?.id;
+    setSessionId(sessionId);
+
+    let paramsGoal = '';
+    let paramsAbout = '';
+    let paramsCustomInstructions = '';
+
+    if (sessionId) {
+      const fineTuneData = getCourseFineTuneData(sessionId);
+      if (fineTuneData) {
+        paramsGoal = fineTuneData.goal;
+        paramsAbout = fineTuneData.about;
+        paramsCustomInstructions = fineTuneData.customInstructions;
+
+        setGoal(paramsGoal);
+        setAbout(paramsAbout);
+        setCustomInstructions(paramsCustomInstructions);
+      }
+    }
+
+    handleGenerateCourse({
+      term: paramsTerm,
+      difficulty: paramsDifficulty,
+      instructions: paramsCustomInstructions,
+      goal: paramsGoal,
+      about: paramsAbout,
+    });
   }, [term, difficulty]);
 
   const handleGenerateCourse = async (options: {
     term: string;
     difficulty: string;
+    instructions?: string;
+    goal?: string;
+    about?: string;
     isForce?: boolean;
     prompt?: string;
   }) => {
-    const { term, difficulty, isForce, prompt } = options;
+    const { term, difficulty, isForce, prompt, instructions, goal, about } =
+      options;
 
     if (!isLoggedIn()) {
       window.location.href = '/ai-tutor';
@@ -79,6 +114,9 @@ export function GenerateAICourse(props: GenerateAICourseProps) {
       onCourseChange: setCourse,
       onLoadingChange: setIsLoading,
       onError: setError,
+      instructions,
+      goal,
+      about,
       isForce,
       prompt,
     });
diff --git a/src/helper/generate-ai-course.ts b/src/helper/generate-ai-course.ts
index 6adab7e9c..6ae70b431 100644
--- a/src/helper/generate-ai-course.ts
+++ b/src/helper/generate-ai-course.ts
@@ -12,6 +12,9 @@ type GenerateCourseOptions = {
   slug?: string;
   isForce?: boolean;
   prompt?: string;
+  instructions?: string;
+  goal?: string;
+  about?: string;
   onCourseIdChange?: (courseId: string) => void;
   onCourseSlugChange?: (courseSlug: string) => void;
   onCourseChange?: (course: AiCourse, rawData: string) => void;
@@ -31,6 +34,9 @@ export async function generateCourse(options: GenerateCourseOptions) {
     onError,
     isForce = false,
     prompt,
+    instructions,
+    goal,
+    about,
   } = options;
 
   onLoadingChange?.(true);
@@ -76,6 +82,9 @@ export async function generateCourse(options: GenerateCourseOptions) {
             difficulty,
             isForce,
             customPrompt: prompt,
+            instructions,
+            goal,
+            about,
           }),
           credentials: 'include',
         },
diff --git a/src/lib/ai.ts b/src/lib/ai.ts
index f4f895d73..a76337636 100644
--- a/src/lib/ai.ts
+++ b/src/lib/ai.ts
@@ -55,6 +55,45 @@ export function generateAiCourseStructure(
   };
 }
 
+type CourseFineTuneData = {
+  about: string;
+  goal: string;
+  customInstructions: string;
+};
+
+export function storeFineTuneData(meta: CourseFineTuneData) {
+  const sessionId = Date.now().toString();
+
+  sessionStorage.setItem(sessionId, JSON.stringify(meta));
+  sessionStorage.setItem('lastSessionId', sessionId);
+
+  return sessionId;
+}
+
+export function getCourseFineTuneData(
+  sessionId: string,
+): CourseFineTuneData | null {
+  const meta = sessionStorage.getItem(sessionId);
+  if (!meta) {
+    return null;
+  }
+
+  return JSON.parse(meta);
+}
+
+export function getLastSessionId(): string | null {
+  return sessionStorage.getItem('lastSessionId');
+}
+
+export function clearFineTuneData() {
+  const sessionId = getLastSessionId();
+  if (sessionId) {
+    sessionStorage.removeItem(sessionId);
+  }
+
+  sessionStorage.removeItem('lastSessionId');
+}
+
 const NEW_LINE = '\n'.charCodeAt(0);
 
 export async function readAIRoadmapStream(

From 3bc00b5b1a025e111832424f5f29d2b0bf5d794d Mon Sep 17 00:00:00 2001
From: Kamran Ahmed <kamranahmed.se@gmail.com>
Date: Tue, 18 Mar 2025 00:07:23 +0000
Subject: [PATCH 5/6] Storing fine-tune data

---
 src/components/GenerateCourse/AICourse.tsx | 23 ++++++++++++----------
 src/lib/ai.ts                              | 12 +++++------
 2 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/src/components/GenerateCourse/AICourse.tsx b/src/components/GenerateCourse/AICourse.tsx
index 5fce355b4..3443d7da6 100644
--- a/src/components/GenerateCourse/AICourse.tsx
+++ b/src/components/GenerateCourse/AICourse.tsx
@@ -6,6 +6,7 @@ import { showLoginPopup } from '../../lib/popup';
 import { UserCoursesList } from './UserCoursesList';
 import { FineTuneCourse } from './FineTuneCourse';
 import {
+  clearFineTuneData,
   getCourseFineTuneData,
   getLastSessionId,
   storeFineTuneData,
@@ -40,9 +41,9 @@ export function AICourse(props: AICourseProps) {
       return;
     }
 
-    // setAbout(fineTuneData.about);
-    // setGoal(fineTuneData.goal);
-    // setCustomInstructions(fineTuneData.customInstructions);
+    setAbout(fineTuneData.about);
+    setGoal(fineTuneData.goal);
+    setCustomInstructions(fineTuneData.customInstructions);
   }, []);
 
   const handleKeyDown = (e: React.KeyboardEvent) => {
@@ -57,13 +58,15 @@ export function AICourse(props: AICourseProps) {
       return;
     }
 
-    const sessionId = hasFineTuneData
-      ? storeFineTuneData({
-          about,
-          goal,
-          customInstructions,
-        })
-      : '';
+    let sessionId = '';
+    if (hasFineTuneData) {
+      clearFineTuneData();
+      sessionId = storeFineTuneData({
+        about,
+        goal,
+        customInstructions,
+      });
+    }
 
     window.location.href = `/ai-tutor/search?term=${encodeURIComponent(keyword)}&difficulty=${difficulty}&id=${sessionId}`;
   }
diff --git a/src/lib/ai.ts b/src/lib/ai.ts
index a76337636..ac9bf1d9e 100644
--- a/src/lib/ai.ts
+++ b/src/lib/ai.ts
@@ -64,8 +64,8 @@ type CourseFineTuneData = {
 export function storeFineTuneData(meta: CourseFineTuneData) {
   const sessionId = Date.now().toString();
 
-  sessionStorage.setItem(sessionId, JSON.stringify(meta));
-  sessionStorage.setItem('lastSessionId', sessionId);
+  localStorage.setItem(sessionId, JSON.stringify(meta));
+  localStorage.setItem('lastSessionId', sessionId);
 
   return sessionId;
 }
@@ -73,7 +73,7 @@ export function storeFineTuneData(meta: CourseFineTuneData) {
 export function getCourseFineTuneData(
   sessionId: string,
 ): CourseFineTuneData | null {
-  const meta = sessionStorage.getItem(sessionId);
+  const meta = localStorage.getItem(sessionId);
   if (!meta) {
     return null;
   }
@@ -82,16 +82,16 @@ export function getCourseFineTuneData(
 }
 
 export function getLastSessionId(): string | null {
-  return sessionStorage.getItem('lastSessionId');
+  return localStorage.getItem('lastSessionId');
 }
 
 export function clearFineTuneData() {
   const sessionId = getLastSessionId();
   if (sessionId) {
-    sessionStorage.removeItem(sessionId);
+    localStorage.removeItem(sessionId);
   }
 
-  sessionStorage.removeItem('lastSessionId');
+  localStorage.removeItem('lastSessionId');
 }
 
 const NEW_LINE = '\n'.charCodeAt(0);

From fbd39e9079b018b1ea19fdb9f132ecde0281063e Mon Sep 17 00:00:00 2001
From: Kamran Ahmed <kamranahmed.se@gmail.com>
Date: Tue, 18 Mar 2025 00:30:46 +0000
Subject: [PATCH 6/6] Moving next should be mark it as done

---
 .../GenerateCourse/AICourseLesson.tsx         | 51 ++++++++++++++-----
 1 file changed, 38 insertions(+), 13 deletions(-)

diff --git a/src/components/GenerateCourse/AICourseLesson.tsx b/src/components/GenerateCourse/AICourseLesson.tsx
index c64966d16..4ab35c429 100644
--- a/src/components/GenerateCourse/AICourseLesson.tsx
+++ b/src/components/GenerateCourse/AICourseLesson.tsx
@@ -334,19 +334,44 @@ export function AICourseLesson(props: AICourseLessonProps) {
             Previous <span className="hidden lg:inline">&nbsp;Lesson</span>
           </button>
 
-          <button
-            onClick={onGoToNextLesson}
-            disabled={cantGoForward}
-            className={cn(
-              'flex items-center rounded-full px-4 py-2 disabled:opacity-50 max-lg:px-3 max-lg:py-1.5 max-lg:text-sm',
-              cantGoForward
-                ? 'cursor-not-allowed text-gray-400'
-                : 'bg-gray-800 text-white hover:bg-gray-700',
-            )}
-          >
-            Next <span className="hidden lg:inline">&nbsp;Lesson</span>
-            <ChevronRight size={16} className="ml-2" />
-          </button>
+          <div>
+            <button
+              onClick={() => {
+                if (!isLessonDone) {
+                  toggleDone(undefined, {
+                    onSuccess: () => {
+                      onGoToNextLesson();
+                    },
+                  });
+                } else {
+                  onGoToNextLesson();
+                }
+              }}
+              disabled={cantGoForward || isTogglingDone}
+              className={cn(
+                'flex items-center rounded-full px-4 py-2 disabled:opacity-50 max-lg:px-3 max-lg:py-1.5 max-lg:text-sm',
+                cantGoForward
+                  ? 'cursor-not-allowed text-gray-400'
+                  : 'bg-gray-800 text-white hover:bg-gray-700',
+              )}
+            >
+              {isTogglingDone ? (
+                <>
+                  <Loader2Icon
+                    size={16}
+                    strokeWidth={3}
+                    className="animate-spin text-white"
+                  />
+                  Please wait ...
+                </>
+              ) : (
+                <>
+                  Next <span className="hidden lg:inline">&nbsp;Lesson</span>
+                  <ChevronRight size={16} className="ml-2" />
+                </>
+              )}
+            </button>
+          </div>
         </div>
       </div>