Skip to content

Commit a8eb510

Browse files
committed
feat: fetch course data from api
1 parent 5a0b72c commit a8eb510

File tree

9 files changed

+101
-36
lines changed

9 files changed

+101
-36
lines changed

apps/api/src/app.module.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import { AppService } from './app.service';
44
import { GlobalModule } from './global/global.mudule';
55
import { UserModule } from './user/user.module';
66
import { AuthModule } from './auth/auth.module';
7+
import { CourseModule } from './course/course.module';
78

89
@Module({
9-
imports: [GlobalModule, UserModule, AuthModule],
10+
imports: [GlobalModule, UserModule, AuthModule, CourseModule],
1011
controllers: [AppController],
1112
providers: [AppService],
1213
})

apps/api/src/app.service.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { Inject, Injectable } from '@nestjs/common';
22
import { DB, DbType } from './global/providers/db.provider';
3-
import {course} from '@earthwrom/shared'
3+
import { course } from '@earthwrom/shared';
44

55
@Injectable()
66
export class AppService {
7-
constructor(@Inject(DB) private db: DbType) {}
7+
constructor(@Inject(DB) private db: DbType) {}
88
async getHello() {
9-
return await this.db.select().from(course)
9+
return await this.db.select().from(course);
1010
}
1111
}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Controller, Get, Param } from '@nestjs/common';
2+
import { CourseService } from './course.service';
3+
4+
@Controller('courses')
5+
export class CourseController {
6+
constructor(private courseService: CourseService) {}
7+
8+
@Get(':courseId')
9+
getStatements(@Param('courseId') courseId: number) {
10+
return this.courseService.find(courseId);
11+
}
12+
}

apps/api/src/course/course.module.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Module } from '@nestjs/common';
2+
import { CourseService } from './course.service';
3+
import { CourseController } from './course.controller';
4+
import { GlobalModule } from '../global/global.mudule';
5+
6+
@Module({
7+
imports: [GlobalModule],
8+
providers: [CourseService],
9+
controllers: [CourseController],
10+
})
11+
export class CourseModule {}

apps/api/src/course/course.service.ts

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { DB, DbType } from '../global/providers/db.provider';
2+
import { eq, asc } from 'drizzle-orm';
3+
import { statement, course } from '@earthwrom/shared';
4+
import { Injectable, Inject } from '@nestjs/common';
5+
6+
@Injectable()
7+
export class CourseService {
8+
constructor(@Inject(DB) private db: DbType) {}
9+
10+
async find(courseId: number) {
11+
const courseResult = await this.db
12+
.select({
13+
id: course.id,
14+
title: course.title,
15+
})
16+
.from(course)
17+
.where(eq(course.id, courseId));
18+
19+
const statementsResult = await this.db
20+
.select({
21+
id: statement.id,
22+
chinese: statement.chinese,
23+
english: statement.english,
24+
soundmark: statement.soundmark,
25+
})
26+
.from(statement)
27+
.where(eq(statement.courseId, courseId))
28+
.orderBy(asc(statement.order));
29+
30+
const finalResult = {
31+
id: courseResult[0].id,
32+
title: courseResult[0].title,
33+
statements: statementsResult,
34+
};
35+
36+
return finalResult;
37+
}
38+
}

apps/client/api/courses.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { useFetchPlus } from "~/composables/useFetch";
2+
3+
interface Course {
4+
title: string;
5+
id: number;
6+
}
7+
8+
export async function fetchCourse(courseId: number) {
9+
const { data: courses } = await useFetchPlus<Course[]>(
10+
`/courses/${courseId}`
11+
);
12+
13+
return courses;
14+
}

apps/client/components/main/Question.vue

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<div class="text-5xl text-center mb-20 mt-10">
33
<div class="text-fuchsia-500 dark:text-gray-50">
4-
{{ currentStatement?.chinese }}
4+
{{ coursesStore.currentStatement?.chinese }}
55
</div>
66
<div class="code-box">
77
<template v-for="i in lineNum" :key="i">
@@ -36,7 +36,7 @@ import { useCoursesStore } from "~/store/courses";
3636
3737
const emit = defineEmits(["bingo"]);
3838
39-
const { currentStatement, checkCorrect } = useCoursesStore();
39+
const coursesStore = useCoursesStore();
4040
4141
const lineNum = ref(1);
4242
const focusing = ref(true);
@@ -47,8 +47,9 @@ const activeInputIndex = computed(() => {
4747
return Math.min(words.value.length - 1, lineNum.value - 1);
4848
});
4949
50+
5051
watchEffect(() => {
51-
lineNum.value = currentStatement?.english.split(" ").length || 1;
52+
lineNum.value = coursesStore.currentStatement?.english.split(" ").length || 1;
5253
});
5354
5455
watchEffect(() => {
@@ -57,7 +58,7 @@ watchEffect(() => {
5758
5859
function handleKeyDown(e: KeyboardEvent) {
5960
if (e.code === "Enter") {
60-
if (checkCorrect(inputValue.value.trim())) {
61+
if (coursesStore.checkCorrect(inputValue.value.trim())) {
6162
emit("bingo");
6263
}
6364
inputValue.value = "";

apps/client/pages/Main/[id].vue

+3-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ import { useCoursesStore } from "~/store/courses";
1515
const route = useRoute();
1616
const coursesStore = useCoursesStore();
1717
18-
await coursesStore.fetchCourseData(route.params.id as string);
18+
onMounted(async () => {
19+
await coursesStore.setup(+route.params.id);
20+
});
1921
</script>
2022

2123
<style scoped></style>

apps/client/store/courses.ts

+13-27
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { defineStore } from "pinia";
2+
import { fetchCourse } from "~/api/courses";
23

34
interface Statement {
45
id: number;
@@ -7,14 +8,17 @@ interface Statement {
78
soundmark: string;
89
}
910

10-
type Course = { statements: Statement[] };
11+
type Course = { id: number; title: string; statements: Statement[] };
1112

1213
export const useCoursesStore = defineStore("courses", () => {
1314
const currentCourse = ref<Course>();
1415
const statementIndex = ref(0);
15-
const currentStatement = computed(() => {
16-
return currentCourse.value?.statements[statementIndex.value];
17-
})
16+
const currentStatement = ref<Statement>();
17+
18+
watchEffect(() => {
19+
currentStatement.value =
20+
currentCourse.value?.statements[statementIndex.value];
21+
});
1822

1923
function toNextStatement() {
2024
statementIndex.value = statementIndex.value + 1;
@@ -29,35 +33,17 @@ export const useCoursesStore = defineStore("courses", () => {
2933
);
3034
}
3135

32-
async function fetchCourseData(courseId: string) {
33-
const courseData = {
34-
"1": {
35-
title: "第一课",
36-
statements: [
37-
{
38-
id: 1,
39-
chinese: "我",
40-
english: "I",
41-
soundmark: "/aɪ/",
42-
},
43-
{
44-
id: 2,
45-
chinese: "不",
46-
english: "don't",
47-
soundmark: "/dont/",
48-
},
49-
],
50-
},
51-
};
52-
53-
currentCourse.value = courseData[courseId];
36+
async function setup(courseId: number) {
37+
const course = await fetchCourse(courseId);
38+
currentCourse.value = course.value;
5439
}
5540

41+
5642
return {
5743
statementIndex,
5844
currentCourse,
5945
currentStatement,
60-
fetchCourseData,
46+
setup,
6147
checkCorrect,
6248
toNextStatement,
6349
};

0 commit comments

Comments
 (0)