Skip to content

Commit

Permalink
Merge pull request #18 from TeaByte/NewTestingWay
Browse files Browse the repository at this point in the history
ADD Deno Kv
  • Loading branch information
m7medVision authored Jan 16, 2024
2 parents fe2d160 + 0c8733c commit 89f61e2
Show file tree
Hide file tree
Showing 17 changed files with 189 additions and 49 deletions.
4 changes: 2 additions & 2 deletions components/Collapse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Course } from "../utils/types.ts";
import CourseCard from "./CourseCard.tsx";

export default function Collapse(
{ title, courses }: { title: string; courses: Course[] },
{ title, courses, completed }: { title: string; courses: Course[]; completed: string[] },
) {
return (
<div class="collapse collapse-arrow bg-base-300">
Expand All @@ -12,7 +12,7 @@ export default function Collapse(
</div>
<div class="collapse-content flex flex-col">
{courses.map((course) => (
<CourseCard key={course.slug} course={course} />
<CourseCard isDone={completed ? completed.includes(course.slug) : false} key={course.slug} course={course} />
))}
</div>
</div>
Expand Down
6 changes: 3 additions & 3 deletions components/CourseCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Course } from "../utils/types.ts";

import ProgressCheck from "../islands/ProgressCheck.tsx";
import ProgressCheck from "./ProgressCheck.tsx";

export default function CourseCard(props: { course: Course }) {
export default function CourseCard(props: { course: Course; isDone: boolean }) {
const { course } = props;
return (
<a
Expand All @@ -12,7 +12,7 @@ export default function CourseCard(props: { course: Course }) {
style={{ order: course.order }}
>
<h3 class="text-gray-500 font-bold flex gap-1 items-center">
<ProgressCheck slug={course.slug} />
<ProgressCheck isDone={props.isDone} />
{course.title}
</h3>
</a>
Expand Down
6 changes: 4 additions & 2 deletions components/Courses.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import Collapse from "./Collapse.tsx";
import CourseCard from "./CourseCard.tsx";

export default function Courses(
{ courses }: { courses: (Course | CourseGroup)[] },
{ courses, completed }: { courses: (Course | CourseGroup)[], completed: string[] },
) {

return (
<>
<h1 class="text-5xl font-bold z-10 mb-2">الاساسيات</h1>
Expand All @@ -16,6 +17,7 @@ export default function Courses(
return (
<div key={index} class="mt-1">
<Collapse
completed={completed}
title={course.label}
courses={course.courses}
/>
Expand All @@ -25,7 +27,7 @@ export default function Courses(
// Single course
return (
<div key={course.slug}>
<CourseCard course={course} />
<CourseCard course={course} isDone={completed ? completed.includes(course.slug) : false} />
</div>
);
}
Expand Down
8 changes: 8 additions & 0 deletions components/ProgressCheck.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import IconCircleCheckFilled from "https://deno.land/x/tabler_icons_tsx@0.0.5/tsx/circle-check-filled.tsx";
import IconCircle from "https://deno.land/x/tabler_icons_tsx@0.0.5/tsx/circle.tsx";

export default function ProgressCheck(props: {isDone : boolean}) {
return props.isDone
? <IconCircleCheckFilled aria-hidden="true" class="h-4 w-4" />
: <IconCircle aria-hidden="true" class="h-4 w-4" />;
}
37 changes: 20 additions & 17 deletions components/ProgressPageSplit.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import Progress from "../islands/Progress.tsx";
import Icon from "./Icon.tsx";
import ProgressBar from "./ProgressBar.tsx";

export default function ProgressPageSplit() {
return (
<>
<div className="flex gap-2">
<h1 className="text-2xl font-bold">مرحباً بك في</h1>
<Icon />
</div>
<p className="text-lg">
وجهتك الأمثل لاكتساب مهارات جافاسكربت بسهولة وفعالية. رحلة تعليمية شيقة
تمتد من الأساسيات إلى المستويات المتقدمة
</p>
<h2 className="text-xl font-bold">تقدمك في إنجاز الدروس:</h2>
{/* TODO: Make this a component */}
<Progress />
</>
);
}
export default function ProgressPageSplit(props: { completed: number, total: number }) {
return (
<>
<div className="flex gap-2">
<h1 className="text-2xl font-bold">مرحباً بك في</h1>
<Icon />
</div>
<p className="text-lg">
وجهتك الأمثل لاكتساب مهارات جافاسكربت بسهولة وفعالية. رحلة تعليمية شيقة
تمتد من الأساسيات إلى المستويات المتقدمة
</p>
<h2 className="text-xl font-bold">تقدمك في إنجاز الدروس:</h2>
<div className="flex flex-col gap-2">
<h1 className="text-sm">لقد تعلمت {props.completed} من أصل {props.total} درس</h1>
<ProgressBar progress={Math.floor((props.completed / props.total) * 100)} />
</div>
</>
);
}
5 changes: 3 additions & 2 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"check": "deno fmt --check && deno lint && deno check **/*.ts && deno check **/*.tsx",
"cli": "echo \"import '\\$fresh/src/dev/cli.ts'\" | deno run --unstable -A -",
"manifest": "deno task cli manifest $(pwd)",
"start": "deno run -A --watch=static/,routes/ dev.ts",
"start": "deno run -A --watch=static/,routes/ --unstable dev.ts",
"build": "deno run -A dev.ts build",
"preview": "deno run -A main.ts",
"update": "deno run -A -r https://fresh.deno.dev/update ."
Expand All @@ -31,7 +31,8 @@
"tailwindcss/plugin": "npm:/tailwindcss@3.3.5/plugin.js",
"$std/": "https://deno.land/std@0.208.0/",
"$gfm": "https://deno.land/x/gfm@0.1.26/mod.ts",
"daisyui": "npm:daisyui@latest"
"daisyui": "npm:daisyui@latest",
"zod": "https://esm.sh/zod@3.22.4"
},
"compilerOptions": {
"jsx": "react-jsx",
Expand Down
6 changes: 4 additions & 2 deletions fresh.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import * as $_slug_ from "./routes/[...slug].tsx";
import * as $_404 from "./routes/_404.tsx";
import * as $_app from "./routes/_app.tsx";
import * as $_middleware from "./routes/_middleware.ts";
import * as $about from "./routes/about.tsx";
import * as $api_test from "./routes/api/test.ts";
import * as $api_test_finsh from "./routes/api/test/finsh.ts";
import * as $group_slug_ from "./routes/group/[slug].tsx";
import * as $index from "./routes/index.tsx";
import * as $Editor from "./islands/Editor.tsx";
Expand All @@ -24,8 +25,9 @@ const manifest = {
"./routes/[...slug].tsx": $_slug_,
"./routes/_404.tsx": $_404,
"./routes/_app.tsx": $_app,
"./routes/_middleware.ts": $_middleware,
"./routes/about.tsx": $about,
"./routes/api/test.ts": $api_test,
"./routes/api/test/finsh.ts": $api_test_finsh,
"./routes/group/[slug].tsx": $group_slug_,
"./routes/index.tsx": $index,
},
Expand Down
16 changes: 12 additions & 4 deletions islands/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ export default function Editor(props: EditorProps) {
{
msg: "لا يوجد اختبارات لهذا السؤال",
type: "info",
}
)
},
);
setTesting(false);
return;
}

// deno-lint-ignore prefer-const
let isPass = false;
// deno-lint-ignore prefer-const
Expand All @@ -61,7 +61,15 @@ export default function Editor(props: EditorProps) {
msg: "تم تجاوز الاختبارات بنجاح",
type: "success",
});
localStorage.setItem(props.slug, "done");
fetch("/api/test/finsh", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
courseslug: props.slug,
}),
});
setTesting(false);
return;
} else {
Expand Down
3 changes: 1 addition & 2 deletions routes/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { type PageProps } from "$fresh/server.ts";
import { Handlers, type PageProps, FreshContext } from "$fresh/server.ts";
import NavBar from "../components/Nav.tsx";
import Toast from "../islands/Toast.tsx";
import { populateCache } from "../utils/course-cache.ts";

populateCache();

export default function App({ Component }: PageProps) {
return (
<html dir="rtl" lang="ar">
Expand Down
24 changes: 24 additions & 0 deletions routes/_middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { FreshContext } from "$fresh/server.ts";
import {getCookies, Cookie, setCookie} from "$std/http/mod.ts";
import { createStudent } from "../utils/KV.ts";
export async function handler(
req: Request,
ctx: FreshContext,
) {
const resp = await ctx.next();
const cookies = getCookies(req.headers);
const sessionId = cookies["sessionId"] || "";
if (!sessionId) {
try {
const student = await createStudent();
const cookie: Cookie = {
name: "sessionId",
value: student.sessionId,
}
setCookie(resp.headers, cookie);
} catch {
return ctx.renderNotFound();
}
}
return resp;
}
5 changes: 0 additions & 5 deletions routes/api/test.ts

This file was deleted.

19 changes: 19 additions & 0 deletions routes/api/test/finsh.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Handlers } from "$fresh/server.ts";
import { getCookies } from "$std/http/mod.ts";
import { addCompletedCourse } from "../../../utils/KV.ts";
interface FinshTest {
courseslug: string;
}
export const handler: Handlers<FinshTest> = {
async POST(req, _ctx) {
try {
const FinshTest = (await req.json() as FinshTest)
const courseslug = FinshTest.courseslug
const sessionId = getCookies(req.headers)?.sessionId;
addCompletedCourse(sessionId, courseslug)
} catch (error) {
return new Response(error.message, { status: 500 });
}
return new Response("ok");
},
};
33 changes: 23 additions & 10 deletions routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,39 @@ import { Head } from "$fresh/runtime.ts";
import { Handlers } from "$fresh/server.ts";
import { PageProps } from "$fresh/server.ts";

import { getCourses } from "../utils/course.ts";
import { getCourses, getNumberOfCourses } from "../utils/course.ts";
import { Course, CourseGroup } from "../utils/types.ts";
import { cache } from "../utils/course-cache.ts";

import Footer from "../components/Footer.tsx";
import Courses from "../components/Courses.tsx";
import ProgressPageSplit from "../components/ProgressPageSplit.tsx";
import { getCookies } from "$std/http/mod.ts";
import { getStudent } from "../utils/KV.ts";


export const handler: Handlers<{ courses: (Course | CourseGroup)[] }> = {
interface Props {
courses: (Course | CourseGroup)[];
completed: string[];
total: number;
}
export const handler: Handlers<Props> = {
async GET(_req, ctx) {
const courses = await getCourses(cache);
return ctx.render(courses);
const session = getCookies(_req.headers)["sessionId"];
const completed = (await getStudent(session)).completedCourses;
const total = getNumberOfCourses(courses.courses);
return ctx.render({
completed,
total,
courses: courses.courses,
});
},
};

export default function BlogIndexPage(
props: PageProps<{ courses: (Course | CourseGroup)[] }>,
) {
const { courses } = props.data;
props: PageProps<Props>,
) {
const { courses, completed, total } = props.data;
return (
<>
<Head>
Expand All @@ -39,12 +52,12 @@ export default function BlogIndexPage(
content="وجهتك الأمثل لاكتساب مهارات جافاسكربت بسهولة وفعالية. رحلة تعليمية شيقة تمتد من الأساسيات إلى المستويات المتقدمة"
/>
</Head>
<main className="flex min-w-screen-md px-4 pt-12 mx-auto mb-6 max-sm:flex-col-reverse">
<main className="flex min-w-screen-md w-[75%] pt-12 mx-auto mb-6 max-sm:flex-col-reverse">
<div className="max-sm:w-full w-1/2 p-4">
<Courses courses={courses} />
<Courses completed={completed} courses={courses} />
</div>
<div className="max-sm:w-full w-1/2 p-4 flex flex-col gap-2">
<ProgressPageSplit />
<ProgressPageSplit completed={completed.length} total={total} />
</div>
</main>
<Footer />
Expand Down
1 change: 1 addition & 0 deletions tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default {
],
plugins: [daisyui],
daisyui: {
log: false,
themes: ["dracula", "nord"],
},
} satisfies Config;
46 changes: 46 additions & 0 deletions utils/KV.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { student, Result } from "./types.ts";

const kv = await Deno.openKv();
export const createStudent = async (): Promise<student> => {
const student: student = {
sessionId: crypto.randomUUID(),
completedCourses: [],
}
const res = await kv.set(["student", student.sessionId], student)
if (res.ok) {
return student
} else {
throw new Error("Failed to create student")
}
}
export const getStudent = async (sessionId: string): Promise<student> => {
const student = await kv.get(["student", sessionId])
if (student) {
return student.value as student
} else {
throw new Error("Failed to get student")
}
}
export const updateStudent = async (sessionId: string, student: student): Promise<Result> => {
const res = await kv.set(["student", sessionId], student)
if (res.ok) {
return res
} else {
throw new Error("Failed to update student")
}
}
export const addCompletedCourse = async (sessionId: string, course: string) : Promise<Result> => {
const student = await getStudent(sessionId)
if (student.completedCourses.includes(course)) {
throw new Error("Course already completed")
}
const completedCourses = student.completedCourses
completedCourses.push(course)
student.completedCourses = completedCourses
try {
const res = await updateStudent(sessionId, student)
return res
} catch {
throw new Error("Failed to add completed course")
}
}
12 changes: 12 additions & 0 deletions utils/course.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,15 @@ export async function getCourses(
console.log(`Caching data took ${(endTime - startTime) / 1000} seconds`);
return cache;
}

export function getNumberOfCourses(courses: (Course | CourseGroup)[]) {
let count = 0;
for (const course of courses) {
if ("courses" in course) {
count += course.courses.length;
} else {
count++;
}
}
return count;
}
Loading

0 comments on commit 89f61e2

Please sign in to comment.