Skip to content

Commit dadc2d4

Browse files
classroom update
1 parent 3b39e35 commit dadc2d4

File tree

7 files changed

+221
-3
lines changed

7 files changed

+221
-3
lines changed

src/api/classroom.ts

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

@@ -20,6 +20,12 @@ export const classroom = {
2020
return res.data
2121
},
2222

23+
async update (pk: Classroom['pk'], payload: ClassroomUpdateReq): Promise<ClassroomDetailRes> {
24+
const endpoint = replacePk(endpoints.classroom.classroomUpdate, pk)
25+
const res = await Vue.axios.patch(endpoint, payload)
26+
return res.data
27+
},
28+
2329
async addStudents (pk: Classroom['pk'], payload: AddStudentReq[]): Promise<void> {
2430
const endpoint = replacePk(endpoints.classroom.addStudents, pk)
2531
await Vue.axios.post(endpoint, payload)

src/api/endpoints.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const endpoints = {
1414
classroomList: '/classroom/classrooms/',
1515
classroomDetail: '/classroom/classrooms/<pk>/',
1616
classroomCreate: '/classroom/classrooms/',
17+
classroomUpdate: '/classroom/classrooms/<pk>/',
1718
addStudents: '/classroom/classrooms/<pk>/add-students/',
1819
removeStudents: '/classroom/classrooms/<pk>/remove-students/',
1920
addReadingExercises: '/classroom/classrooms/<pk>/add-reading-exercises/',

src/interfaces/api/classroom.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ export declare interface ClassroomCreateReq {
1212
description?: string;
1313
}
1414

15+
export declare interface ClassroomUpdateReq extends ClassroomCreateReq {}
16+
1517
export declare interface AddStudentReq {
1618
name: string;
1719
email: string;

src/layouts/LayoutClassroomTeacher.vue

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,54 @@
1010
<div v-else-if="classroom !== undefined">
1111
<v-breadcrumbs :items="breadcrumbs"></v-breadcrumbs>
1212

13-
<h1 v-text="classroom.name"></h1>
13+
<v-row
14+
justify="space-between"
15+
align="center"
16+
>
17+
<v-col cols="auto">
18+
<h1 v-text="classroom.name"></h1>
19+
</v-col>
20+
<v-col cols="auto">
21+
<v-menu
22+
offset-x
23+
left
24+
nudge-left="12"
25+
>
26+
<template #activator="{ on, attrs }">
27+
<v-icon
28+
v-on="on"
29+
v-bind="attrs"
30+
>
31+
mdi-dots-vertical
32+
</v-icon>
33+
</template>
34+
<v-list>
35+
<v-list-item
36+
link
37+
:to="{
38+
name: 'ClassroomUpdate',
39+
params: { pk: classroom.pk }
40+
}"
41+
>
42+
<v-list-item-icon>
43+
<v-icon>mdi-pencil-outline</v-icon>
44+
</v-list-item-icon>
45+
<v-list-item-content>
46+
<v-list-item-title>Edit</v-list-item-title>
47+
</v-list-item-content>
48+
</v-list-item>
49+
<v-list-item>
50+
<v-list-item-icon>
51+
<v-icon>mdi-delete-outline</v-icon>
52+
</v-list-item-icon>
53+
<v-list-item-content>
54+
<v-list-item-title>Delete</v-list-item-title>
55+
</v-list-item-content>
56+
</v-list-item>
57+
</v-list>
58+
</v-menu>
59+
</v-col>
60+
</v-row>
1461
<v-divider></v-divider>
1562
<p
1663
class="mt-5 description"

src/router/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Http404 from '../views/http/Http404.vue'
1111

1212
import ClassroomList from '../views/classroom/ClassroomList.vue'
1313
import ClassroomCreate from '../views/classroom/ClassroomCreate.vue'
14+
import ClassroomUpdate from '../views/classroom/ClassroomUpdate.vue'
1415
import ClassroomOverview from '../views/classroom/ClassroomOverview.vue'
1516
import ClassroomOverviewStudentReport from '../views/classroom/ClassroomOverviewStudentReport.vue'
1617
import ClassroomStudents from '../views/classroom/ClassroomStudents.vue'
@@ -54,6 +55,12 @@ const routes: Array<RouteConfig> = [
5455
name: 'ClassroomCreate',
5556
component: ClassroomCreate
5657
},
58+
{
59+
path: '/:pk/edit',
60+
name: 'ClassroomUpdate',
61+
component: ClassroomUpdate,
62+
props: castToNumber(['pk'])
63+
},
5764
{
5865
path: '/:pk/overview',
5966
name: 'ClassroomOverview',

src/store/classroom.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Api } from '@/api'
2-
import { AddReadingExercisesReq, AddStudentReq, ClassroomCreateReq, RemoveReadingExercisesReq, RemoveStudentReq } from '@/interfaces/api/classroom'
2+
import { AddReadingExercisesReq, AddStudentReq, ClassroomCreateReq, ClassroomUpdateReq, RemoveReadingExercisesReq, RemoveStudentReq } from '@/interfaces/api/classroom'
33
import { PaginatedRes } from '@/interfaces/api/common'
44
import { Classroom } from '@/interfaces/classroom'
55
import { Module } from 'vuex'
@@ -37,6 +37,15 @@ export const classroom: Module<ClassroomState, RootState> = {
3737
state.classrooms.splice(0, 0, classroom)
3838
},
3939

40+
EDIT_CLASSROOM (state, classroom) {
41+
let index = 0
42+
for (const c of state.classrooms) {
43+
if (c.pk === classroom.pk) break
44+
index++
45+
}
46+
state.classrooms.splice(index, 1, classroom)
47+
},
48+
4049
ADD_STUDENT_TO_CURRENT_CLASSROOM (state, student) {
4150
if (state.currentClassroom !== undefined) {
4251
state.currentClassroom.students.push(student)
@@ -97,6 +106,14 @@ export const classroom: Module<ClassroomState, RootState> = {
97106
return data.pk
98107
},
99108

109+
async update (
110+
{ commit },
111+
{ pk, payload }: { pk: Classroom['pk'], payload: ClassroomUpdateReq }
112+
): Promise<void> {
113+
const data = await Api.classroom.update(pk, payload)
114+
commit('EDIT_CLASSROOM', data)
115+
},
116+
100117
async addStudents ({ state, commit }, payload: AddStudentReq[]): Promise<void> {
101118
if (state.currentClassroom === undefined) return
102119
await Api.classroom.addStudents(state.currentClassroom.pk, payload)
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<template>
2+
<v-container class="container-sm">
3+
<v-breadcrumbs :items="breadcrumbs"></v-breadcrumbs>
4+
5+
<v-progress-circular
6+
v-if="loading"
7+
indeterminate
8+
color="primary"
9+
></v-progress-circular>
10+
11+
<v-card v-else>
12+
<v-card-title>
13+
Edit classroom
14+
</v-card-title>
15+
16+
<v-card-text>
17+
<v-form>
18+
<v-text-field
19+
v-model="name"
20+
label="Name *"
21+
autofocus
22+
:error-messages="nameErrs"
23+
:error-count="nameErrs.length"
24+
></v-text-field>
25+
<v-textarea
26+
v-model="description"
27+
label="Description"
28+
></v-textarea>
29+
</v-form>
30+
</v-card-text>
31+
32+
<v-card-actions>
33+
<v-btn
34+
color="primary"
35+
@click="save"
36+
:loading="loading"
37+
min-width="110"
38+
>
39+
Save
40+
</v-btn>
41+
</v-card-actions>
42+
</v-card>
43+
</v-container>
44+
</template>
45+
46+
<script lang="ts">
47+
import { ClassroomCreateReq } from '@/interfaces/api/classroom'
48+
import { Classroom } from '@/interfaces/classroom'
49+
import { unexpectedExc } from '@/utils'
50+
import { assertErrCode, status } from '@/utils/status-codes'
51+
import { Vue, Component, Prop } from 'vue-property-decorator'
52+
import { mapState } from 'vuex'
53+
54+
@Component({
55+
computed: {
56+
...mapState('classroom', {
57+
classroom: 'currentClassroom'
58+
})
59+
}
60+
})
61+
export default class ClassroomUpdate extends Vue {
62+
@Prop(Number) readonly pk!: number
63+
64+
// eslint-disable-next-line no-undef
65+
[key: string]: unknown
66+
67+
breadcrumbs = [
68+
{ text: 'Home', to: { name: 'Home' }, exact: true },
69+
{ text: 'Classrooms', to: { name: 'ClassroomList' }, exact: true },
70+
{ text: 'Edit', disabled: true }
71+
]
72+
73+
/**
74+
* Init
75+
*/
76+
classroom!: Classroom
77+
loading = false
78+
name = ''
79+
description = ''
80+
nameErrs = []
81+
82+
created (): void {
83+
this.setUp()
84+
}
85+
86+
setUp (): void {
87+
this.$store.dispatch('classroom/detail', this.pk)
88+
.then(() => {
89+
this.name = this.classroom.name
90+
this.description = this.classroom.description
91+
})
92+
}
93+
94+
/**
95+
* Save
96+
*/
97+
saving = false
98+
99+
save (): void {
100+
if (this.saving) return
101+
this.saving = true
102+
103+
const payload: ClassroomCreateReq = {
104+
name: this.name,
105+
description: this.description
106+
}
107+
108+
this.$store.dispatch('classroom/update', {
109+
pk: this.classroom.pk,
110+
payload
111+
})
112+
.then(() => {
113+
this.$router.push({
114+
name: 'ClassroomOverview',
115+
params: { pk: this.classroom.pk.toString() }
116+
})
117+
})
118+
.catch(err => {
119+
if (assertErrCode(err, status.HTTP_400_BAD_REQUEST)) {
120+
const data = err.response.data
121+
Object.entries(data).forEach(([field, errMsgs]) => {
122+
const attr = `${field}Errs`
123+
this[attr] = errMsgs
124+
})
125+
} else {
126+
unexpectedExc(err)
127+
}
128+
})
129+
.finally(() => {
130+
this.saving = false
131+
})
132+
}
133+
}
134+
</script>
135+
136+
<style scoped lang="scss">
137+
138+
</style>

0 commit comments

Comments
 (0)