Skip to content

Commit 978a9a5

Browse files
looking good
1 parent 01a2e03 commit 978a9a5

17 files changed

+571
-329
lines changed

src/api/classroom.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import Vue from 'vue'
2-
import { ClassroomListRes, ClassroomDetailRes, ClassroomCreateReq, AddStudentReq, RemoveStudentReq, AddReadingExercisesReq, RemoveReadingExercisesReq } from '@/interfaces/api/classroom'
2+
import { ClassroomListRes, ClassroomDetailRes, ClassroomCreateReq, AddStudentReq, RemoveStudentReq, AddReadingExercisesReq, RemoveReadingExercisesReq, ReadingExerciseReportRes } from '@/interfaces/api/classroom'
33
import { Classroom } from '@/interfaces/classroom'
44
import { endpoints, replacePk } from './endpoints'
5+
import { User } from '@/interfaces/user'
56

67
export const classroom = {
78
async list (): Promise<ClassroomListRes> {
@@ -38,5 +39,15 @@ export const classroom = {
3839
async removeReadingExercises (pk: Classroom['pk'], payload: RemoveReadingExercisesReq[]): Promise<void> {
3940
const endpoint = replacePk(endpoints.classroom.removeReadingExercises, pk)
4041
await Vue.axios.post(endpoint, payload)
42+
},
43+
44+
async getStudentReport (classroomPk: Classroom['pk'], studentPk: User['pk']): Promise<ReadingExerciseReportRes[]> {
45+
const endpoint = replacePk(endpoints.classroom.studentReadingReport, classroomPk)
46+
const res = await Vue.axios.get(endpoint, {
47+
params: {
48+
student: studentPk
49+
}
50+
})
51+
return res.data
4152
}
4253
}

src/api/endpoints.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ export const endpoints = {
1616
addStudents: '/classroom/classrooms/<pk>/add-students/',
1717
removeStudents: '/classroom/classrooms/<pk>/remove-students/',
1818
addReadingExercises: '/classroom/classrooms/<pk>/add-reading-exercises/',
19-
removeReadingExercises: '/classroom/classrooms/<pk>/remove-reading-exercises/'
19+
removeReadingExercises: '/classroom/classrooms/<pk>/remove-reading-exercises/',
20+
studentReadingReport: '/classroom/classrooms/<pk>/student-reading-report/'
2021
},
2122
readingExercise: {
2223
list: '/classroom/reading-exercises/',

src/interfaces/api/classroom.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Classroom } from '../classroom'
1+
import { Classroom, ReadingExerciseReport } from '../classroom'
22
import { PaginatedRes } from './common'
33

44
export declare interface ClassroomDetailRes extends Classroom {}
@@ -29,3 +29,5 @@ export declare interface AddReadingExercisesReq {
2929
export declare interface RemoveReadingExercisesReq {
3030
pk: number;
3131
}
32+
33+
export declare interface ReadingExerciseReportRes extends ReadingExerciseReport {}

src/interfaces/classroom.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ClassroomReadingExercise } from './reading-exercise';
12
import { User } from './user'
23

34
export declare interface Classroom {
@@ -7,5 +8,26 @@ export declare interface Classroom {
78
description: string;
89
teacher: User;
910
students: User[];
10-
reading_exercises: number[];
11+
reading_exercises: ClassroomReadingExercise[];
12+
}
13+
14+
15+
export declare interface ReadingSubmissionResult {
16+
question_number: number;
17+
submitted_answer: string;
18+
possible_answers: string[];
19+
is_correct: boolean;
20+
}
21+
22+
export declare interface ReadingExerciseReport {
23+
exercise: string;
24+
passage_1_total: number;
25+
passage_2_total: number;
26+
passage_3_total: number;
27+
total: number;
28+
band_score: number;
29+
submitted: boolean;
30+
passage_1_detail: ReadingSubmissionResult[];
31+
passage_2_detail: ReadingSubmissionResult[];
32+
passage_3_detail: ReadingSubmissionResult[];
1133
}

src/interfaces/reading-exercise.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,8 @@ export declare interface ReadingExercise {
44
identifier: string;
55
content: string;
66
}
7+
8+
export declare interface ClassroomReadingExercise {
9+
pk: number;
10+
identifier: string;
11+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<template>
2+
<LayoutDefault>
3+
<v-container>
4+
<v-progress-circular
5+
v-if="loading"
6+
indeterminate
7+
color="primary"
8+
></v-progress-circular>
9+
10+
<div v-else-if="classroom !== undefined">
11+
<v-breadcrumbs :items="breadcrumbs"></v-breadcrumbs>
12+
13+
<h1 v-text="classroom.name"></h1>
14+
<v-divider></v-divider>
15+
<p v-text="classroom.description"></p> <!-- TODO: multiline -->
16+
17+
<v-tabs>
18+
<v-tab
19+
v-for="tab of tabs"
20+
:key="tab.text"
21+
v-text="tab.text"
22+
link
23+
:to="tab.to"
24+
></v-tab>
25+
</v-tabs>
26+
27+
<router-view v-if="classroomFound" class="mt-5"></router-view>
28+
</div>
29+
</v-container>
30+
</LayoutDefault>
31+
</template>
32+
33+
<script lang="ts">
34+
import { Classroom } from '@/interfaces/classroom'
35+
import { unexpectedExc } from '@/utils'
36+
import { Vue, Component } from 'vue-property-decorator'
37+
import { mapMutations, mapState } from 'vuex'
38+
import LayoutDefault from './LayoutDefault.vue'
39+
40+
@Component({
41+
components: {
42+
LayoutDefault
43+
},
44+
computed: {
45+
...mapState('classroom', {
46+
classroom: 'currentClassroom'
47+
})
48+
},
49+
methods: {
50+
...mapMutations('classroom', {
51+
setCurrentClassroom: 'SET_CURRENT_CLASSROOM'
52+
})
53+
}
54+
})
55+
export default class LayoutClassroomStudent extends Vue {
56+
// eslint-disable-next-line no-undef
57+
[key: string]: unknown
58+
59+
classroom!: Classroom
60+
setCurrentClassroom!: CallableFunction
61+
62+
get breadcrumbs (): unknown[] {
63+
if (this.classroom === undefined) return []
64+
return [
65+
{ text: 'Home', to: { name: 'Home' }, exact: true },
66+
{ text: 'Classrooms', to: { name: 'ClassroomList' }, exact: true },
67+
{ text: this.classroom.name, disabled: true }
68+
]
69+
}
70+
71+
get pk (): string {
72+
return this.$route.params.pk
73+
}
74+
75+
get loading (): boolean {
76+
return this.classroom === undefined
77+
}
78+
79+
created (): void {
80+
this.setClassroom()
81+
}
82+
83+
classroomFound = false
84+
85+
setClassroom (): void {
86+
this.$store.dispatch('classroom/detail', this.pk)
87+
.then(() => {
88+
this.classroomFound = true
89+
})
90+
.catch(unexpectedExc)
91+
}
92+
93+
tabs = [
94+
{ text: 'Reading exercises', to: { name: 'ClassroomExercisesReading' } },
95+
{ text: 'Listening exercises', to: { name: 'ClassroomExercisesListening' } }
96+
]
97+
98+
// @ts-expect-error: don't care
99+
// eslint-disable-next-line
100+
beforeRouteLeave (to, from, next): void {
101+
this.setCurrentClassroom(undefined)
102+
next()
103+
}
104+
}
105+
</script>
106+
107+
<style scoped lang="scss">
108+
109+
</style>

src/router/index.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import VueRouter, { RouteConfig } from 'vue-router'
33

44
import LayoutNoAppbar from '../layouts/LayoutNoAppbar.vue'
55
import LayoutClassroomTeacher from '../layouts/LayoutClassroomTeacher.vue'
6+
import LayoutClassroomStudent from '../layouts/LayoutClassroomStudent.vue'
67

78
import Home from '../views/Home.vue'
89
import Auth from '../views/auth/Auth.vue'
@@ -56,7 +57,8 @@ const routes: Array<RouteConfig> = [
5657
component: ClassroomOverview,
5758
props: castToNumber('pk'),
5859
meta: {
59-
teacherLayout: LayoutClassroomTeacher
60+
teacherLayout: LayoutClassroomTeacher,
61+
studentLayout: LayoutClassroomStudent
6062
}
6163
},
6264
{
@@ -65,7 +67,8 @@ const routes: Array<RouteConfig> = [
6567
component: ClassroomStudents,
6668
props: castToNumber('pk'),
6769
meta: {
68-
teacherLayout: LayoutClassroomTeacher
70+
teacherLayout: LayoutClassroomTeacher,
71+
studentLayout: LayoutClassroomStudent
6972
}
7073
},
7174
{
@@ -74,7 +77,8 @@ const routes: Array<RouteConfig> = [
7477
component: ClassroomExercisesReading,
7578
props: castToNumber('pk'),
7679
meta: {
77-
teacherLayout: LayoutClassroomTeacher
80+
teacherLayout: LayoutClassroomTeacher,
81+
studentLayout: LayoutClassroomStudent
7882
}
7983
},
8084
{
@@ -83,7 +87,8 @@ const routes: Array<RouteConfig> = [
8387
component: ClassroomExercisesListening,
8488
props: castToNumber('pk'),
8589
meta: {
86-
teacherLayout: LayoutClassroomTeacher
90+
teacherLayout: LayoutClassroomTeacher,
91+
studentLayout: LayoutClassroomStudent
8792
}
8893
}
8994
]),

src/store/account.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ export const account: Module<AccountState, RootState> = {
2424
loggedInUser: state => state.loggedInUser,
2525
hasUserInfo: state => state.loggedInUser !== undefined,
2626
accessToken: state => state.accessToken,
27-
refreshToken: state => state.refreshToken
27+
refreshToken: state => state.refreshToken,
28+
isTeacher: state => state.loggedInUser !== undefined && state.loggedInUser.user_type === 'teacher',
29+
isStudent: state => state.loggedInUser !== undefined && state.loggedInUser.user_type === 'student'
2830
},
2931

3032
mutations: {

src/store/classroom.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,23 @@ export const classroom: Module<ClassroomState, RootState> = {
5353
state.currentClassroom.students.splice(index, 1)
5454
},
5555

56-
ADD_READING_EXERCISES_TO_CURRENT_CLASSROOM (state, exercisePk) {
56+
ADD_READING_EXERCISES_TO_CURRENT_CLASSROOM (state, exercise) {
5757
if (state.currentClassroom !== undefined) {
58-
if (!state.currentClassroom.reading_exercises.includes(exercisePk)) {
59-
state.currentClassroom.reading_exercises.push(exercisePk)
58+
const existingPks = state.currentClassroom.reading_exercises.map(exercise => exercise.pk)
59+
if (!existingPks.includes(exercise.pk)) {
60+
state.currentClassroom.reading_exercises.push({
61+
pk: exercise.pk,
62+
identifier: exercise.identifier
63+
})
6064
}
6165
}
6266
},
6367

6468
REMOVE_READING_EXERCISES_FROM_CURRENT_CLASSROOM (state, pkToRemove) {
6569
if (state.currentClassroom === undefined) return
6670
let index = 0
67-
for (const pk of state.currentClassroom.reading_exercises) {
68-
if (pk === pkToRemove) break
71+
for (const exercise of state.currentClassroom.reading_exercises) {
72+
if (exercise.pk === pkToRemove) break
6973
index++
7074
}
7175
state.currentClassroom.reading_exercises.splice(index, 1)
@@ -113,7 +117,7 @@ export const classroom: Module<ClassroomState, RootState> = {
113117
if (state.currentClassroom === undefined) return
114118
await Api.classroom.addReadingExercises(state.currentClassroom.pk, payload)
115119
payload.forEach(exercise => {
116-
commit('ADD_READING_EXERCISES_TO_CURRENT_CLASSROOM', exercise.pk)
120+
commit('ADD_READING_EXERCISES_TO_CURRENT_CLASSROOM', exercise)
117121
})
118122
},
119123

src/views/Home.vue

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,41 @@
1616

1717
<script lang="ts">
1818
import { Vue, Component } from 'vue-property-decorator'
19+
import { mapGetters } from 'vuex'
1920
20-
@Component
21+
@Component({
22+
computed: {
23+
...mapGetters('account', [
24+
'isTeacher',
25+
'isStudent'
26+
])
27+
}
28+
})
2129
export default class Home extends Vue {
2230
breadcrumbs = [
2331
{ text: 'Home', to: { name: 'Home' } }
2432
]
2533
26-
links = [
27-
{ text: 'Classrooms', to: { name: 'ClassroomList' } },
28-
{ text: 'Reading exercises', to: { name: 'ReadingExerciseList' } }
29-
]
34+
isTeacher!: boolean
35+
isStudent!: boolean
36+
37+
created (): void {
38+
if (this.isStudent) {
39+
this.$router.push({ name: 'ClassroomList' })
40+
}
41+
}
42+
43+
// eslint-disable-next-line
44+
get links () {
45+
const links = [
46+
{ text: 'Classrooms', to: { name: 'ClassroomList' } }
47+
]
48+
if (this.isTeacher) {
49+
links.push(
50+
{ text: 'Reading exercises', to: { name: 'ReadingExerciseList' } }
51+
)
52+
}
53+
return links
54+
}
3055
}
3156
</script>

0 commit comments

Comments
 (0)