From 571176016f39316638f3ea74734c9aec8099e210 Mon Sep 17 00:00:00 2001 From: JunGu Kang <chr0m3.kr@gmail.com> Date: Tue, 10 Dec 2019 01:16:46 +0900 Subject: [PATCH] #21 Add Schedule Detail View --- src/router/index.js | 5 + src/views/ScheduleDetail.vue | 293 +++++++++++++++++++++++++++++++++++ 2 files changed, 298 insertions(+) create mode 100644 src/views/ScheduleDetail.vue diff --git a/src/router/index.js b/src/router/index.js index 4285289..752f888 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -43,6 +43,11 @@ const routes = [ name: 'ScheduleCreate', component: () => import('../views/ScheduleCreate.vue'), }, + { + path: '/schedule/:id', + name: 'ScheduleDetail', + component: () => import('@/views/ScheduleDetail.vue'), + }, { path: '/trainee', name: 'TraineeList', diff --git a/src/views/ScheduleDetail.vue b/src/views/ScheduleDetail.vue new file mode 100644 index 0000000..d3ff6e9 --- /dev/null +++ b/src/views/ScheduleDetail.vue @@ -0,0 +1,293 @@ +<template> + <div class="schedule-detail"> + <v-row> + <v-col + cols="12" + > + <v-card + :loading="isProcessing" + > + <v-card-title>일정 정보</v-card-title> + <v-card-text> + <v-alert + v-if="error.isError" + dense + text + type="error" + > + {{ error.message }} + </v-alert> + <v-text-field + label="등록번호" + readonly + v-model="id" + ></v-text-field> + <program-field + :program.sync="schedule.program" + ></program-field> + <trainer-field + :trainer.sync="schedule.trainer" + ></trainer-field> + <v-text-field + label="최대 예약 가능 인원" + v-model="schedule.maxTrainee" + ></v-text-field> + <date-time-field + :datetime.sync="schedule.startAt" + ></date-time-field> + <v-text-field + label="등록 시각" + readonly + v-model="schedule.createdAt" + ></v-text-field> + <v-text-field + label="최종 수정 시각" + readonly + v-model="schedule.updatedAt" + ></v-text-field> + </v-card-text> + <v-card-actions> + <v-spacer></v-spacer> + <v-btn + color="error" + outlined + @click="deleteSchedule(id)" + > + <v-icon + left + > + mdi-delete + </v-icon> + 삭제 + </v-btn> + <v-btn + color="primary" + outlined + @click="updateSchedule(id)" + > + <v-icon + left + > + mdi-content-save + </v-icon> + 저장 + </v-btn> + </v-card-actions> + </v-card> + </v-col> + </v-row> + <v-row> + <v-col + cols="12" + > + <v-card + :loading="isProcessing" + > + <v-card-title>예약자</v-card-title> + <v-card-text> + <v-row + justify="end" + > + <v-col + cols="12" + sm="4" + md="3" + lg="3" + xl="2" + > + <v-text-field + append-icon="mdi-magnify" + clearable + label="회원 검색" + v-model="traineeList.searchKeyword" + ></v-text-field> + </v-col> + </v-row> + <v-data-table + :headers="traineeList.headers" + item-key="id" + :items="schedule.trainees" + :loading="isProcessing" + loading-text="데이터를 불러오는 중입니다." + :search="traineeList.searchKeyword" + no-results-text="일치하는 회원을 찾지 못했습니다." + > + <template v-slot:item.action="{ item }"> + <v-icon + small + class="mr-2" + @click="editTrainee(item.id)" + > + mdi-pencil + </v-icon> + <v-icon + small + @click="deleteTrainee(item.id)" + > + mdi-delete + </v-icon> + </template> + </v-data-table> + </v-card-text> + </v-card> + </v-col> + </v-row> + </div> +</template> + +<script> +import APISetting from '@/settings/api'; +import DateTimeField from '@/components/DateTimeField.vue'; +import ProgramField from '@/components/ProgramField.vue'; +import TrainerField from '@/components/TrainerField.vue'; + +export default { + name: 'ScheduleDetail', + + components: { + DateTimeField, + ProgramField, + TrainerField, + }, + + data: () => ({ + isProcessing: false, + error: { + isError: false, + message: '', + }, + traineeList: { + headers: [ + { + text: '#', + value: 'id', + }, + { + text: '이름', + value: 'name', + }, + { + text: '이메일', + value: 'email', + }, + { + text: '연락처', + value: 'phone', + }, + { + text: '', + value: 'action', + sortable: false, + }, + ], + data: [], + searchKeyword: '', + }, + schedule: { + program: { + title: '', + }, + trainer: { + name: '', + }, + maxTrainee: '', + startAt: '', + createdAt: '', + updatedAt: '', + }, + }), + + computed: { + id() { + if ('id' in this.$route.params) return this.$route.params.id; + return null; + }, + }, + + methods: { + getSchedule(id) { + this.error.isError = false; + this.error.message = ''; + this.isProcessing = true; + + fetch(APISetting.endpoints.schedule.detail(id), APISetting.settings.get) + .then((res) => { + if (res.status === 404) return Promise.all([null, res]); + if ([200, 400, 500].includes(res.status)) return Promise.all([res.json(), res]); + throw new Error('알 수 없는 응답입니다.'); + }) + .then((values) => { + const [json, res] = values; + if (res.status === 404) throw new Error('존재하지 않는 데이터입니다.'); + if (res.status !== 200) throw new Error(json.message); + this.schedule = json.schedule; + }) + .catch((e) => { + this.error.message = e.message; + this.error.isError = true; + }) + .finally(() => { + this.isProcessing = false; + }); + }, + updateSchedule(id) { + this.error.isError = false; + this.error.message = ''; + this.isProcessing = true; + + fetch(APISetting.endpoints.schedule.detail(id), APISetting.settings.put(this.schedule)) + .then((res) => { + if (res.status === 404) return Promise.all([null, res]); + if ([200, 400, 404, 500].includes(res.status)) return Promise.all([res.json(), res]); + throw new Error('알 수 없는 응답입니다.'); + }) + .then((values) => { + const [json, res] = values; + if (res.status === 404) throw new Error('존재하지 않는 데이터입니다.'); + if (res.status !== 200) throw new Error(json.message); + this.schedule = json.schedule; + }) + .catch((e) => { + this.error.message = e.message; + this.error.isError = true; + }) + .finally(() => { + this.isProcessing = false; + }); + }, + deleteSchedule(id) { + this.error.isError = false; + this.error.message = ''; + this.isProcessing = true; + + fetch(APISetting.endpoints.schedule.detail(id), APISetting.settings.delete) + .then((res) => { + if ([204, 404].includes(res.status)) return Promise.all([null, res]); + if ([204, 400, 404, 500].includes(res.status)) return Promise.all([res.json(), res]); + // If response status is not equal to 204, 400, 404, or 500, go to catch. + throw new Error('알 수 없는 응답입니다.'); + }) + .then((values) => { + const [json, res] = values; + if (res.status === 404) throw new Error('존재하지 않는 데이터입니다.'); + if (res.status !== 204) throw new Error(json.message); + return this.$router.push('/schedule'); + }) + .catch((e) => { + this.error.message = e.message; + this.error.isError = true; + }) + .finally(() => { + this.isProcessing = false; + }); + }, + editTrainee(id) { + this.$router.push(`/trainee/${id}`); + }, + }, + + created() { + this.getSchedule(this.id); + }, +}; +</script> -- GitLab