Skip to content
Snippets Groups Projects
Commit 1471e2a9 authored by JunGu Kang's avatar JunGu Kang
Browse files

#20 Add Schedule List View

parent 2651862f
No related branches found
No related tags found
2 merge requests!37Deploy,!24#20 Add Schedule List View
Pipeline #4325 passed
...@@ -48,6 +48,22 @@ ...@@ -48,6 +48,22 @@
</v-list-item-content> </v-list-item-content>
</v-list-item> </v-list-item>
</v-list-item-group> </v-list-item-group>
<v-subheader>일정 관리</v-subheader>
<v-list-item-group
color="primary"
>
<v-list-item
link
:to="{ name: 'ScheduleList' }"
>
<v-list-item-icon>
<v-icon>mdi-shape</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>일정 목록</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list-item-group>
<v-subheader>매장 관리</v-subheader> <v-subheader>매장 관리</v-subheader>
<v-list-item-group <v-list-item-group
color="primary" color="primary"
......
...@@ -33,6 +33,11 @@ const routes = [ ...@@ -33,6 +33,11 @@ const routes = [
name: 'ProgramDetail', name: 'ProgramDetail',
component: () => import('@/views/ProgramDetail.vue'), component: () => import('@/views/ProgramDetail.vue'),
}, },
{
path: '/schedule',
name: 'ScheduleList',
component: () => import('@/views/ScheduleList.vue'),
},
{ {
path: '/trainee', path: '/trainee',
name: 'TraineeList', name: 'TraineeList',
......
...@@ -14,6 +14,10 @@ export default { ...@@ -14,6 +14,10 @@ export default {
list: `${host}/program`, list: `${host}/program`,
detail: id => (`${host}/program/${id}`), detail: id => (`${host}/program/${id}`),
}, },
schedule: {
list: `${host}/schedule`,
detail: id => (`${host}/schedule/${id}`),
},
trainee: { trainee: {
list: `${host}/trainee`, list: `${host}/trainee`,
detail: id => (`${host}/trainee/${id}`), detail: id => (`${host}/trainee/${id}`),
......
<template>
<div class="schedule-list">
<v-card>
<v-card-title>일정 목록</v-card-title>
<v-card-text>
<v-row
justify="end"
>
<v-col
align-self="center"
cols="12"
sm="8"
md="9"
lg="9"
xl="10"
>
<v-btn
color="success"
outlined
@click="createSchedule"
>
<v-icon
left
>
mdi-plus
</v-icon>
새 일정 등록
</v-btn>
</v-col>
<v-col
cols="12"
sm="4"
md="3"
lg="3"
xl="2"
>
<v-text-field
append-icon="mdi-magnify"
clearable
label="일정 검색"
v-model="scheduleList.searchKeyword"
></v-text-field>
</v-col>
</v-row>
<v-data-table
:headers="scheduleList.headers"
item-key="id"
:items="scheduleList.data"
:loading="isProcessing"
loading-text="데이터를 불러오는 중입니다."
:search="scheduleList.searchKeyword"
no-results-text="일치하는 일정을 찾지 못했습니다."
>
<template v-slot:item.action="{ item }">
<v-icon
small
class="mr-2"
@click="editSchedule(item.id)"
>
mdi-pencil
</v-icon>
<v-icon
small
@click="deleteSchedule(item.id)"
>
mdi-delete
</v-icon>
</template>
</v-data-table>
</v-card-text>
</v-card>
</div>
</template>
<script>
import moment from 'moment';
import APISetting from '@/settings/api';
export default {
name: 'ScheduleList',
data: () => ({
isProcessing: false,
error: {
isError: false,
message: '',
},
scheduleList: {
headers: [
{
text: '#',
value: 'id',
},
{
text: '프로그램',
value: 'program.title',
},
{
text: '트레이너',
value: 'trainer.name',
},
{
text: '시작 시각',
value: 'startAt',
},
{
text: '소요시간(분)',
value: 'program.durationTime',
},
{
text: '최대 예약 가능 인원',
value: 'maxTrainee',
},
{
text: '현재 예약 인원',
value: 'trainees.length',
},
{
text: '현재 예약 가능 인원',
value: 'remainTrainee',
},
{
text: '',
value: 'action',
sortable: false,
},
],
data: [],
searchKeyword: '',
},
}),
methods: {
getScheduleList() {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.schedule.list, APISetting.settings.get)
.then((res) => {
if (res.status === 200) return res.json();
throw new Error('알 수 없는 응답입니다.');
})
.then((json) => {
const { schedules } = json;
schedules.forEach((schedule) => {
// eslint-disable-next-line no-param-reassign
schedule.startAt = moment(schedule.startAt).format('YYYY-MM-DD HH:mm');
// eslint-disable-next-line no-param-reassign
schedule.remainTrainee = schedule.maxTrainee - schedule.trainees.length;
});
this.scheduleList.data = schedules;
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
});
},
createSchedule() {
this.$router.push('/schedule/create');
},
editSchedule(id) {
this.$router.push(`/schedule/${id}`);
},
deleteSchedule(id) {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.schedule.detail(id), APISetting.settings.delete)
.then((res) => {
if (res.status === 204) return Promise.all([null, res]);
if ([400, 404, 500].includes(res.status)) return Promise.all([res.json(), res]);
throw new Error('알 수 없는 응답입니다.');
})
.then((values) => {
const [json, res] = values;
if (res.status === 204) return this.getScheduleList();
throw new Error(json.message);
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
});
},
},
created() {
this.getScheduleList();
},
};
</script>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment