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

#35 Refactor Trainer Views

Trainer Create View
Trainer Detail View
Trainer List View
parent 2707b3da
Branches #35
No related tags found
2 merge requests!37Deploy,!31#35 Refactor Trainer Views
Pipeline #4348 passed
<template>
<div class="trainer-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="이메일"
v-model="trainer.email"
></v-text-field>
<v-text-field
label="비밀번호"
type="password"
v-model="trainer.password"
></v-text-field>
<v-text-field
label="이름"
v-model="trainer.name"
></v-text-field>
<v-text-field
label="닉네임"
v-model="trainer.nickname"
></v-text-field>
<v-text-field
label="연락처"
v-model="trainer.phone"
></v-text-field>
<v-menu
:close-on-content-click="false"
min-width="290px"
offset-y
v-model="showDatePicker"
>
<template v-slot:activator="{ on }">
<v-text-field
label="생년월일"
readonly
v-model="trainer.birthDate"
v-on="on"
></v-text-field>
</template>
<v-date-picker
v-model="trainer.birthDate"
@input="showDatePicker = false"
></v-date-picker>
</v-menu>
<v-textarea
auto-grow
label="소개"
v-model="trainer.bio"
></v-textarea>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="error"
outlined
@click="cancel"
>
<v-icon left>mdi-delete</v-icon>
취소
</v-btn>
<v-btn
color="primary"
outlined
@click="createTrainer"
>
<v-icon left>mdi-content-save</v-icon>
저장
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import APISetting from '@/settings/api';
export default {
name: 'TrainerCreate',
data: () => ({
isProcessing: false,
error: {
isError: false,
message: '',
},
showDatePicker: false,
trainer: {
email: '',
password: '',
name: '',
nickname: '',
phone: '',
birthDate: '',
bio: '',
},
}),
methods: {
createTrainer() {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.trainer.list, APISetting.settings.post(this.trainer))
.then((res) => {
if ([201, 400, 500].includes(res.status)) return Promise.all([res.json(), res]);
throw new Error('알 수 없는 응답입니다.');
})
.then((values) => {
const [json, res] = values;
if (res.status !== 201) throw new Error(json.message);
this.$router.push('/trainer');
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
});
},
cancel() {
this.$router.push('/trainer');
},
},
};
</script>
<template> <template>
<div class="trainer-detail"> <div class="trainer-detail">
<v-card <v-row>
:loading="isProcessing" <v-col cols="12">
> <v-card :loading="isProcessing">
<v-card-title>트레이너 정보</v-card-title> <v-card-title>트레이너 정보</v-card-title>
<v-card-text> <v-card-text>
<v-alert <v-alert
...@@ -18,13 +18,17 @@ ...@@ -18,13 +18,17 @@
readonly readonly
v-model="id" v-model="id"
></v-text-field> ></v-text-field>
<v-text-field
label="이메일"
v-model="trainer.email"
></v-text-field>
<v-text-field <v-text-field
label="이름" label="이름"
v-model="trainer.name" v-model="trainer.name"
></v-text-field> ></v-text-field>
<v-text-field <v-text-field
label="이메일" label="닉네임"
v-model="trainer.email" v-model="trainer.nickname"
></v-text-field> ></v-text-field>
<v-text-field <v-text-field
label="연락처" label="연락처"
...@@ -36,9 +40,7 @@ ...@@ -36,9 +40,7 @@
offset-y offset-y
v-model="showDatePicker" v-model="showDatePicker"
> >
<template <template v-slot:activator="{ on }">
v-slot:activator="{ on }"
>
<v-text-field <v-text-field
label="생년월일" label="생년월일"
readonly readonly
...@@ -51,6 +53,11 @@ ...@@ -51,6 +53,11 @@
@input="showDatePicker = false" @input="showDatePicker = false"
></v-date-picker> ></v-date-picker>
</v-menu> </v-menu>
<v-textarea
auto-grow
label="소개"
v-model="trainer.bio"
></v-textarea>
<v-text-field <v-text-field
label="등록 시각" label="등록 시각"
readonly readonly
...@@ -63,11 +70,13 @@ ...@@ -63,11 +70,13 @@
></v-text-field> ></v-text-field>
</v-card-text> </v-card-text>
<v-card-actions> <v-card-actions>
<v-spacer></v-spacer>
<v-btn <v-btn
color="error" color="error"
outlined outlined
@click="deleteTrainer(id)" @click="deleteTrainer(id)"
> >
<v-icon left>mdi-delete</v-icon>
삭제 삭제
</v-btn> </v-btn>
<v-btn <v-btn
...@@ -75,14 +84,19 @@ ...@@ -75,14 +84,19 @@
outlined outlined
@click="updateTrainer(id)" @click="updateTrainer(id)"
> >
<v-icon left>mdi-content-save</v-icon>
저장 저장
</v-btn> </v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</v-col>
</v-row>
</div> </div>
</template> </template>
<script> <script>
import moment from 'moment';
import APISetting from '@/settings/api'; import APISetting from '@/settings/api';
export default { export default {
...@@ -102,8 +116,8 @@ export default { ...@@ -102,8 +116,8 @@ export default {
phone: '', phone: '',
birthDate: '', birthDate: '',
bio: '', bio: '',
updatedAt: '',
createdAt: '', createdAt: '',
updatedAt: '',
}, },
}), }),
...@@ -130,6 +144,9 @@ export default { ...@@ -130,6 +144,9 @@ export default {
const [json, res] = values; const [json, res] = values;
if (res.status === 404) throw new Error('존재하지 않는 데이터입니다.'); if (res.status === 404) throw new Error('존재하지 않는 데이터입니다.');
if (res.status !== 200) throw new Error(json.message); if (res.status !== 200) throw new Error(json.message);
const { trainer } = json;
trainer.createdAt = moment(trainer.createdAt).format('YYYY-MM-DD HH:mm:ss');
trainer.updatedAt = moment(trainer.updatedAt).format('YYYY-MM-DD HH:mm:ss');
this.trainer = json.trainer; this.trainer = json.trainer;
}) })
.catch((e) => { .catch((e) => {
...@@ -148,13 +165,16 @@ export default { ...@@ -148,13 +165,16 @@ export default {
fetch(APISetting.endpoints.trainer.detail(id), APISetting.settings.put(this.trainer)) fetch(APISetting.endpoints.trainer.detail(id), APISetting.settings.put(this.trainer))
.then((res) => { .then((res) => {
if (res.status === 404) return Promise.all([null, res]); if (res.status === 404) return Promise.all([null, res]);
if ([200, 400, 404, 500].includes(res.status)) return Promise.all([res.json(), res]); if ([200, 400, 500].includes(res.status)) return Promise.all([res.json(), res]);
throw new Error('알 수 없는 응답입니다.'); throw new Error('알 수 없는 응답입니다.');
}) })
.then((values) => { .then((values) => {
const [json, res] = values; const [json, res] = values;
if (res.status === 404) throw new Error('존재하지 않는 데이터입니다.'); if (res.status === 404) throw new Error('존재하지 않는 데이터입니다.');
if (res.status !== 200) throw new Error(json.message); if (res.status !== 200) throw new Error(json.message);
const { trainer } = json;
trainer.createdAt = moment(trainer.createdAt).format('YYYY-MM-DD HH:mm:ss');
trainer.updatedAt = moment(trainer.updatedAt).format('YYYY-MM-DD HH:mm:ss');
this.trainer = json.trainer; this.trainer = json.trainer;
}) })
.catch((e) => { .catch((e) => {
...@@ -173,8 +193,7 @@ export default { ...@@ -173,8 +193,7 @@ export default {
fetch(APISetting.endpoints.trainer.detail(id), APISetting.settings.delete) fetch(APISetting.endpoints.trainer.detail(id), APISetting.settings.delete)
.then((res) => { .then((res) => {
if ([204, 404].includes(res.status)) return Promise.all([null, 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 ([400, 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('알 수 없는 응답입니다.'); throw new Error('알 수 없는 응답입니다.');
}) })
.then((values) => { .then((values) => {
......
<template> <template>
<div class="trainer-list"> <div class="trainer-list">
<v-row>
<v-col cols="12">
<v-card> <v-card>
<v-card-title>트레이너 목록</v-card-title> <v-card-title>트레이너 목록</v-card-title>
<v-card-text> <v-card-text>
<v-row <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="createTrainer"
>
<v-icon left>mdi-plus</v-icon>
새 트레이너 등록
</v-btn>
</v-col>
<v-col <v-col
cols="12" cols="12"
sm="4" sm="4"
...@@ -48,10 +65,14 @@ ...@@ -48,10 +65,14 @@
</v-data-table> </v-data-table>
</v-card-text> </v-card-text>
</v-card> </v-card>
</v-col>
</v-row>
</div> </div>
</template> </template>
<script> <script>
import moment from 'moment';
import APISetting from '@/settings/api'; import APISetting from '@/settings/api';
export default { export default {
...@@ -86,8 +107,8 @@ export default { ...@@ -86,8 +107,8 @@ export default {
value: 'phone', value: 'phone',
}, },
{ {
text: '소개', text: '등록 시각',
value: 'bio', value: 'createdAt',
}, },
{ {
text: '', text: '',
...@@ -109,11 +130,15 @@ export default { ...@@ -109,11 +130,15 @@ export default {
fetch(APISetting.endpoints.trainer.list, APISetting.settings.get) fetch(APISetting.endpoints.trainer.list, APISetting.settings.get)
.then((res) => { .then((res) => {
if (res.status === 200) return res.json(); if (res.status === 200) return res.json();
// If response status is not equal to 200, go to catch.
throw new Error('알 수 없는 응답입니다.'); throw new Error('알 수 없는 응답입니다.');
}) })
.then((json) => { .then((json) => {
this.trainerList.data = json.trainers; const { trainers } = json;
trainers.forEach((trainer) => {
// eslint-disable-next-line no-param-reassign
trainer.createdAt = moment(trainer.createdAt).format('YYYY-MM-DD HH:mm:ss');
});
this.trainerList.data = trainers;
}) })
.catch((e) => { .catch((e) => {
this.error.message = e.message; this.error.message = e.message;
...@@ -123,31 +148,34 @@ export default { ...@@ -123,31 +148,34 @@ export default {
this.isProcessing = false; this.isProcessing = false;
}); });
}, },
createTrainer() {
this.$router.push('/trainer/create');
},
editTrainer(id) { editTrainer(id) {
this.$router.push(`/trainer/${id}`); this.$router.push(`/trainer/${id}`);
}, },
deleteTrainer(id) { deleteTrainer(id) {
this.error.isError = false; this.error.isError = false;
this.error.message = ''; this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.trainer.detail(id), APISetting.settings.delete) fetch(APISetting.endpoints.trainer.detail(id), APISetting.settings.delete)
.then((res) => { .then((res) => {
if (res.status === 204) return Promise.all([null, res]); if (res.status === 204) return Promise.all([null, res]);
if ([204, 400, 404, 500].includes(res.status)) return Promise.all([res.json(), res]); if ([400, 404, 500].includes(res.status)) return Promise.all([res.json(), res]);
// If response status is not equal to 204, 400, 404, 500, go to catch.
throw new Error('알 수 없는 응답입니다.'); throw new Error('알 수 없는 응답입니다.');
}) })
.then((values) => { .then((values) => {
const [json, res] = values; const [json, res] = values;
// If trainer successfully deleted and response status is equal to 204,
// update trainer list.
if (res.status === 204) return this.getTrainerList(); if (res.status === 204) return this.getTrainerList();
// Otherwise, go to catch.
throw new Error(json.message); throw new Error(json.message);
}) })
.catch((e) => { .catch((e) => {
this.error.message = e.message; this.error.message = e.message;
this.error.isError = true; this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
}); });
}, },
}, },
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment