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

Merge branch 'development' into temp

parents 94ec94ab 32fc2a47
Branches temp
No related tags found
1 merge request!42Merge Temp Branch into Development
Pipeline #4402 passed
...@@ -35,9 +35,10 @@ deployToS3: ...@@ -35,9 +35,10 @@ deployToS3:
before_script: before_script:
- curl "https://d1vvhvl2y92vvt.cloudfront.net/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" - curl "https://d1vvhvl2y92vvt.cloudfront.net/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
- unzip awscliv2.zip - unzip awscliv2.zip
- sudo ./aws/install - ./aws/install
script: script:
- aws2 s3 rm s3://$S3_BUCKET_NAME/ --recursive - aws2 s3 rm s3://$S3_BUCKET_NAME/ --recursive
- npm run build
- aws2 s3 cp dist s3://$S3_BUCKET_NAME/ --recursive --acl public-read - aws2 s3 cp dist s3://$S3_BUCKET_NAME/ --recursive --acl public-read
when: manual when: manual
only: only:
......
...@@ -5,10 +5,8 @@ ...@@ -5,10 +5,8 @@
:value="isNavDrawerVisible" :value="isNavDrawerVisible"
> >
<v-list> <v-list>
<v-subheader>회원 관리</v-subheader> <v-subheader>회원</v-subheader>
<v-list-item-group <v-list-item-group color="primary">
color="primary"
>
<v-list-item <v-list-item
link link
:to="{ name: 'TraineeList' }" :to="{ name: 'TraineeList' }"
...@@ -17,14 +15,35 @@ ...@@ -17,14 +15,35 @@
<v-icon>mdi-account-group</v-icon> <v-icon>mdi-account-group</v-icon>
</v-list-item-icon> </v-list-item-icon>
<v-list-item-content> <v-list-item-content>
<v-list-item-title>회원 목록</v-list-item-title> <v-list-item-title>전체 회원</v-list-item-title>
</v-list-item-content> </v-list-item-content>
</v-list-item> </v-list-item>
</v-list-item-group> <v-list-item
<v-subheader>프로그램 관리</v-subheader> link
<v-list-item-group :to="{ name: 'DietList' }"
color="primary"
> >
<v-list-item-icon>
<v-icon>mdi-pasta</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
link
:to="{ name: 'ExerciseList' }"
>
<v-list-item-icon>
<v-icon>mdi-pasta</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-list-item-group color="primary">
<v-list-item <v-list-item
link link
:to="{ name: 'ProgramList' }" :to="{ name: 'ProgramList' }"
...@@ -33,7 +52,7 @@ ...@@ -33,7 +52,7 @@
<v-icon>mdi-shape</v-icon> <v-icon>mdi-shape</v-icon>
</v-list-item-icon> </v-list-item-icon>
<v-list-item-content> <v-list-item-content>
<v-list-item-title>프로그램 목록</v-list-item-title> <v-list-item-title>전체 프로그램</v-list-item-title>
</v-list-item-content> </v-list-item-content>
</v-list-item> </v-list-item>
<v-list-item <v-list-item
...@@ -44,14 +63,13 @@ ...@@ -44,14 +63,13 @@
<v-icon>mdi-ticket</v-icon> <v-icon>mdi-ticket</v-icon>
</v-list-item-icon> </v-list-item-icon>
<v-list-item-content> <v-list-item-content>
<v-list-item-title>이용권 목록</v-list-item-title> <v-list-item-title>프로그램 이용권 관리</v-list-item-title>
</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 <v-subheader>일정</v-subheader>
color="primary" <v-list-item-group color="primary">
>
<v-list-item <v-list-item
link link
:to="{ name: 'ScheduleList' }" :to="{ name: 'ScheduleList' }"
...@@ -60,14 +78,13 @@ ...@@ -60,14 +78,13 @@
<v-icon>mdi-shape</v-icon> <v-icon>mdi-shape</v-icon>
</v-list-item-icon> </v-list-item-icon>
<v-list-item-content> <v-list-item-content>
<v-list-item-title>일정 목록</v-list-item-title> <v-list-item-title>전체 일정</v-list-item-title>
</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 <v-subheader>매장</v-subheader>
color="primary" <v-list-item-group color="primary">
>
<v-list-item <v-list-item
link link
:to="{ name: 'TrainerList' }" :to="{ name: 'TrainerList' }"
...@@ -76,7 +93,7 @@ ...@@ -76,7 +93,7 @@
<v-icon>mdi-account-supervisor</v-icon> <v-icon>mdi-account-supervisor</v-icon>
</v-list-item-icon> </v-list-item-icon>
<v-list-item-content> <v-list-item-content>
<v-list-item-title>트레이너 목록</v-list-item-title> <v-list-item-title>트레이너 관리</v-list-item-title>
</v-list-item-content> </v-list-item-content>
</v-list-item> </v-list-item>
</v-list-item-group> </v-list-item-group>
......
...@@ -5,6 +5,10 @@ import Store from '@/store/index'; ...@@ -5,6 +5,10 @@ import Store from '@/store/index';
import APISetting from '@/settings/api'; import APISetting from '@/settings/api';
import Login from '@/views/Login.vue'; import Login from '@/views/Login.vue';
import Main from '@/views/Main.vue'; import Main from '@/views/Main.vue';
import DietList from '@/views/DietList.vue';
import DietDetail from '@/views/DietDetail.vue';
import ExerciseList from '@/views/ExerciseList.vue';
import ExerciseDetail from '@/views/ExerciseDetail.vue';
import ProgramList from '@/views/ProgramList.vue'; import ProgramList from '@/views/ProgramList.vue';
import ProgramCreate from '@/views/ProgramCreate.vue'; import ProgramCreate from '@/views/ProgramCreate.vue';
import ProgramDetail from '@/views/ProgramDetail.vue'; import ProgramDetail from '@/views/ProgramDetail.vue';
...@@ -35,6 +39,26 @@ const routes = [ ...@@ -35,6 +39,26 @@ const routes = [
name: 'Main', name: 'Main',
component: Main, component: Main,
}, },
{
path: '/diet',
name: 'DietList',
component: DietList,
},
{
path: '/diet/:id',
name: 'DietDetail',
component: DietDetail,
},
{
path: '/exercise',
name: 'ExerciseList',
component: ExerciseList,
},
{
path: '/exercise/:id',
name: 'ExerciseDetail',
component: ExerciseDetail,
},
{ {
path: '/program', path: '/program',
name: 'ProgramList', name: 'ProgramList',
......
...@@ -14,6 +14,10 @@ export default { ...@@ -14,6 +14,10 @@ export default {
list: `${host}/diet`, list: `${host}/diet`,
detail: id => (`${host}/diet/${id}`), detail: id => (`${host}/diet/${id}`),
}, },
exercise: {
list: `${host}/exercise`,
detail: id => (`${host}/exercise/${id}`),
},
program: { program: {
list: `${host}/program`, list: `${host}/program`,
detail: id => (`${host}/program/${id}`), detail: id => (`${host}/program/${id}`),
...@@ -25,6 +29,10 @@ export default { ...@@ -25,6 +29,10 @@ export default {
trainee: { trainee: {
list: `${host}/trainee`, list: `${host}/trainee`,
detail: id => (`${host}/trainee/${id}`), detail: id => (`${host}/trainee/${id}`),
booking: id => (`${host}/trainee/${id}/booking`),
diet: id => (`${host}/trainee/${id}/diet`),
exercise: id => (`${host}/trainee/${id}/exercise`),
inventory: id => (`${host}/trainee/${id}/inventory`),
}, },
trainer: { trainer: {
list: `${host}/trainer`, list: `${host}/trainer`,
......
<template>
<div class="diet-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>
<v-textarea
auto-grow
label="식단"
readonly
v-model="diet.diet"
></v-textarea>
<v-textarea
auto-grow
label="피드백"
v-model="diet.feedback"
></v-textarea>
<v-text-field
label="등록 시각"
readonly
v-model="diet.createdAt"
></v-text-field>
<v-text-field
label="최종 수정 시각"
readonly
v-model="diet.updatedAt"
></v-text-field>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="error"
outlined
@click="deleteDiet(id)"
>
<v-icon left>mdi-delete</v-icon>
삭제
</v-btn>
<v-btn
color="primary"
outlined
@click="updateDiet(id)"
>
<v-icon left>mdi-content-save</v-icon>
저장
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import moment from 'moment';
import APISetting from '@/settings/api';
export default {
name: 'DietDetail',
data: () => ({
isProcessing: false,
error: {
isError: false,
message: '',
},
showDatePicker: false,
diet: {
diet: '',
feedback: '',
createdAt: '',
updatedAt: '',
},
}),
computed: {
id() {
if ('id' in this.$route.params) return this.$route.params.id;
return null;
},
},
methods: {
getDiet(id) {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.diet.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);
const { diet } = json;
diet.createdAt = moment(diet.createdAt).format('YYYY-MM-DD HH:mm:ss');
diet.updatedAt = moment(diet.updatedAt).format('YYYY-MM-DD HH:mm:ss');
this.diet = diet;
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
});
},
updateDiet(id) {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.diet.detail(id), APISetting.settings.put(this.diet))
.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);
const { diet } = json;
diet.createdAt = moment(diet.createdAt).format('YYYY-MM-DD HH:mm:ss');
diet.updatedAt = moment(diet.updatedAt).format('YYYY-MM-DD HH:mm:ss');
this.diet = diet;
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
});
},
deleteDiet(id) {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.diet.detail(id), APISetting.settings.delete)
.then((res) => {
if ([204, 404].includes(res.status)) return Promise.all([null, res]);
if ([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 !== 204) throw new Error(json.message);
return this.$router.push('/diet');
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
});
},
},
created() {
this.getDiet(this.id);
},
};
</script>
<template>
<div class="diet-list">
<v-row>
<v-col cols="12">
<v-card>
<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="dietList.searchKeyword"
></v-text-field>
</v-col>
</v-row>
<v-data-table
:headers="dietList.headers"
item-key="id"
:items="dietList.data"
:loading="isProcessing"
loading-text="데이터를 불러오는 중입니다."
:search="dietList.searchKeyword"
no-results-text="일치하는 식단을 찾지 못했습니다."
>
<template v-slot:item.action="{ item }">
<v-icon
small
class="mr-2"
@click="editDiet(item.id)"
>
mdi-pencil
</v-icon>
<v-icon
small
@click="deleteDiet(item.id)"
>
mdi-delete
</v-icon>
</template>
</v-data-table>
</v-card-text>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import moment from 'moment';
import APISetting from '@/settings/api';
export default {
name: 'DietList',
data: () => ({
isProcessing: false,
error: {
isError: false,
message: '',
},
dietList: {
headers: [
{
text: '#',
value: 'id',
},
{
text: '회원',
value: 'trainee.name',
},
{
text: '식단',
value: 'diet',
},
{
text: '피드백 여부',
value: 'hasFeedback',
},
{
text: '등록 시각',
value: 'createdAt',
},
{
text: '',
value: 'action',
sortable: false,
},
],
data: [],
searchKeyword: '',
},
}),
methods: {
getDietList() {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.diet.list, APISetting.settings.get)
.then((res) => {
if (res.status === 200) return res.json();
throw new Error('알 수 없는 응답입니다.');
})
.then((json) => {
this.dietList.data = json.diets;
this.dietList.data.forEach((diet) => {
// eslint-disable-next-line no-param-reassign
diet.hasFeedback = diet.feedback ? '완료' : '미완료';
// eslint-disable-next-line no-param-reassign
diet.createdAt = moment(diet.createdAt).format('YYYY-MM-DD HH:mm:ss');
});
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
});
},
editDiet(id) {
this.$router.push(`/diet/${id}`);
},
deleteDiet(id) {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.diet.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.getDietList();
throw new Error(json.message);
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = true;
});
},
},
created() {
this.getDietList();
},
};
</script>
<template>
<div class="exercise-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>
<v-textarea
auto-grow
label="운동"
readonly
v-model="exercise.exercise"
></v-textarea>
<v-textarea
auto-grow
label="피드백"
v-model="exercise.feedback"
></v-textarea>
<v-text-field
label="등록 시각"
readonly
v-model="exercise.createdAt"
></v-text-field>
<v-text-field
label="최종 수정 시각"
readonly
v-model="exercise.updatedAt"
></v-text-field>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="error"
outlined
@click="deleteExercise(id)"
>
<v-icon left>mdi-delete</v-icon>
삭제
</v-btn>
<v-btn
color="primary"
outlined
@click="updateExercise(id)"
>
<v-icon left>mdi-content-save</v-icon>
저장
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import moment from 'moment';
import APISetting from '@/settings/api';
export default {
name: 'ExerciseDetail',
data: () => ({
isProcessing: false,
error: {
isError: false,
message: '',
},
showDatePicker: false,
exercise: {
exercise: '',
feedback: '',
createdAt: '',
updatedAt: '',
},
}),
computed: {
id() {
if ('id' in this.$route.params) return this.$route.params.id;
return null;
},
},
methods: {
getExercise(id) {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.exercise.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);
const { exercise } = json;
exercise.createdAt = moment(exercise.createdAt).format('YYYY-MM-DD HH:mm:ss');
exercise.updatedAt = moment(exercise.updatedAt).format('YYYY-MM-DD HH:mm:ss');
this.exercise = exercise;
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
});
},
updateExercise(id) {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.exercise.detail(id), APISetting.settings.put(this.exercise))
.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);
const { exercise } = json;
exercise.createdAt = moment(exercise.createdAt).format('YYYY-MM-DD HH:mm:ss');
exercise.updatedAt = moment(exercise.updatedAt).format('YYYY-MM-DD HH:mm:ss');
this.exercise = exercise;
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
});
},
deleteExercise(id) {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.exercise.detail(id), APISetting.settings.delete)
.then((res) => {
if ([204, 404].includes(res.status)) return Promise.all([null, res]);
if ([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 !== 204) throw new Error(json.message);
return this.$router.push('/exercise');
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
});
},
},
created() {
this.getExercise(this.id);
},
};
</script>
<template>
<div class="exercise-list">
<v-row>
<v-col cols="12">
<v-card>
<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="exerciseList.searchKeyword"
></v-text-field>
</v-col>
</v-row>
<v-data-table
:headers="exerciseList.headers"
item-key="id"
:items="exerciseList.data"
:loading="isProcessing"
loading-text="데이터를 불러오는 중입니다."
:search="exerciseList.searchKeyword"
no-results-text="일치하는 운동을 찾지 못했습니다."
>
<template v-slot:item.action="{ item }">
<v-icon
small
class="mr-2"
@click="editExercise(item.id)"
>
mdi-pencil
</v-icon>
<v-icon
small
@click="deleteExercise(item.id)"
>
mdi-delete
</v-icon>
</template>
</v-data-table>
</v-card-text>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import moment from 'moment';
import APISetting from '@/settings/api';
export default {
name: 'ExerciseList',
data: () => ({
isProcessing: false,
error: {
isError: false,
message: '',
},
exerciseList: {
headers: [
{
text: '#',
value: 'id',
},
{
text: '회원',
value: 'trainee.name',
},
{
text: '운동',
value: 'exercise',
},
{
text: '피드백 여부',
value: 'hasFeedback',
},
{
text: '등록 시각',
value: 'createdAt',
},
{
text: '',
value: 'action',
sortable: false,
},
],
data: [],
searchKeyword: '',
},
}),
methods: {
getExerciseList() {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.exercise.list, APISetting.settings.get)
.then((res) => {
if (res.status === 200) return res.json();
throw new Error('알 수 없는 응답입니다.');
})
.then((json) => {
this.exerciseList.data = json.exercises;
this.exerciseList.data.forEach((exercise) => {
// eslint-disable-next-line no-param-reassign
exercise.hasFeedback = exercise.feedback ? '완료' : '미완료';
// eslint-disable-next-line no-param-reassign
exercise.createdAt = moment(exercise.createdAt).format('YYYY-MM-DD HH:mm:ss');
});
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
});
},
editExercise(id) {
this.$router.push(`/exercise/${id}`);
},
deleteExercise(id) {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.exercise.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.getExerciseList();
throw new Error(json.message);
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = true;
});
},
},
created() {
this.getExerciseList();
},
};
</script>
...@@ -226,7 +226,10 @@ export default { ...@@ -226,7 +226,10 @@ 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);
this.schedule = json.schedule; const { schedule } = json;
schedule.createdAt = moment(schedule.createdAt).format('YYYY-MM-DD HH:mm:ss');
schedule.updatedAt = moment(schedule.updatedAt).format('YYYY-MM-DD HH:mm:ss');
this.schedule = schedule;
}) })
.catch((e) => { .catch((e) => {
this.error.message = e.message; this.error.message = e.message;
......
...@@ -82,6 +82,174 @@ ...@@ -82,6 +82,174 @@
</v-card> </v-card>
</v-col> </v-col>
</v-row> </v-row>
<v-row>
<v-col cols="12">
<v-card :loading="booking.isProcessing">
<v-card-title>예약 정보</v-card-title>
<v-card-text>
<v-alert
v-if="booking.error.isError"
dense
text
type="error"
>
{{ booking.error.message }}
</v-alert>
<v-data-table
:headers="booking.list.headers"
item-key="id"
:items="booking.list.data"
:loading="booking.isProcessing"
loading-text="데이터를 불러오는 중입니다."
:search="booking.list.searchKeyword"
no-results-text="일치하는 예약을 찾지 못했습니다."
>
<template v-slot:item.action="{ item }">
<v-icon
small
class="mr-2"
@click="editBooking(item.id)"
>
mdi-pencil
</v-icon>
<v-icon
small
@click="deleteBooking(item.id)"
>
mdi-delete
</v-icon>
</template>
</v-data-table>
</v-card-text>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-card :loading="inventory.isProcessing">
<v-card-title>이용권 정보</v-card-title>
<v-card-text>
<v-alert
v-if="inventory.error.isError"
dense
text
type="error"
>
{{ inventory.error.message }}
</v-alert>
<v-data-table
:headers="inventory.list.headers"
item-key="id"
:items="inventory.list.data"
:loading="inventory.isProcessing"
loading-text="데이터를 불러오는 중입니다."
:search="inventory.list.searchKeyword"
no-results-text="일치하는 이용권을 찾지 못했습니다."
>
<template v-slot:item.action="{ item }">
<v-icon
small
class="mr-2"
@click="editInventory(item.id)"
>
mdi-pencil
</v-icon>
<v-icon
small
@click="deleteInventory(item.id)"
>
mdi-delete
</v-icon>
</template>
</v-data-table>
</v-card-text>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-card :loading="diet.isProcessing">
<v-card-title>식단 정보</v-card-title>
<v-card-text>
<v-alert
v-if="diet.error.isError"
dense
text
type="error"
>
{{ diet.error.message }}
</v-alert>
<v-data-table
:headers="diet.list.headers"
item-key="id"
:items="diet.list.data"
:loading="diet.isProcessing"
loading-text="데이터를 불러오는 중입니다."
:search="diet.list.searchKeyword"
no-results-text="일치하는 식단을 찾지 못했습니다."
>
<template v-slot:item.action="{ item }">
<v-icon
small
class="mr-2"
@click="editDiet(item.id)"
>
mdi-pencil
</v-icon>
<v-icon
small
@click="deleteDiet(item.id)"
>
mdi-delete
</v-icon>
</template>
</v-data-table>
</v-card-text>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-card :loading="exercise.isProcessing">
<v-card-title>운동 정보</v-card-title>
<v-card-text>
<v-alert
v-if="exercise.error.isError"
dense
text
type="error"
>
{{ exercise.error.message }}
</v-alert>
<v-data-table
:headers="exercise.list.headers"
item-key="id"
:items="exercise.list.data"
:loading="exercise.isProcessing"
loading-text="데이터를 불러오는 중입니다."
:search="exercise.list.searchKeyword"
no-results-text="일치하는 운동을 찾지 못했습니다."
>
<template v-slot:item.action="{ item }">
<v-icon
small
class="mr-2"
@click="editExercise(item.id)"
>
mdi-pencil
</v-icon>
<v-icon
small
@click="deleteExercise(item.id)"
>
mdi-delete
</v-icon>
</template>
</v-data-table>
</v-card-text>
</v-card>
</v-col>
</v-row>
</div> </div>
</template> </template>
...@@ -108,6 +276,146 @@ export default { ...@@ -108,6 +276,146 @@ export default {
createdAt: '', createdAt: '',
updatedAt: '', updatedAt: '',
}, },
booking: {
isProcessing: false,
error: {
isError: false,
message: '',
},
list: {
headers: [
{
text: '프로그램 이름',
value: 'schedule.program.title',
},
{
text: '시작 시각',
value: 'schedule.startAt',
},
{
text: '메모',
value: 'memo',
},
{
text: '등록 시각',
value: 'createdAt',
},
{
text: '',
value: 'action',
sortable: false,
},
],
data: [],
searchKeyword: '',
},
},
inventory: {
isProcessing: false,
error: {
isError: false,
message: '',
},
list: {
headers: [
{
text: '#',
value: 'id',
},
{
text: '프로그램 이름',
value: 'program.title',
},
{
text: '사용 완료 횟수',
value: 'usedCount',
},
{
text: '사용 가능 횟수',
value: 'maxCount',
},
{
text: '등록 시각',
value: 'createdAt',
},
{
text: '',
value: 'action',
sortable: false,
},
],
data: [],
searchKeyword: '',
},
},
diet: {
isProcessing: false,
error: {
isError: false,
message: '',
},
list: {
headers: [
{
text: '#',
value: 'id',
},
{
text: '식단',
value: 'diet',
},
{
text: '피드백 여부',
value: 'hasFeedback',
},
{
text: '등록 시각',
value: 'createdAt',
},
{
text: '',
value: 'action',
sortable: false,
},
],
data: [],
searchKeyword: '',
},
},
exercise: {
isProcessing: false,
error: {
isError: false,
message: '',
},
list: {
headers: [
{
text: '#',
value: 'id',
},
{
text: '운동',
value: 'exercise',
},
{
text: '피드백 여부',
value: 'hasFeedback',
},
{
text: '등록 시각',
value: 'createdAt',
},
{
text: '',
value: 'action',
sortable: false,
},
],
data: [],
searchKeyword: '',
},
},
}), }),
computed: { computed: {
...@@ -137,6 +445,10 @@ export default { ...@@ -137,6 +445,10 @@ export default {
trainee.createdAt = moment(trainee.createdAt).format('YYYY-MM-DD HH:mm:ss'); trainee.createdAt = moment(trainee.createdAt).format('YYYY-MM-DD HH:mm:ss');
trainee.updatedAt = moment(trainee.updatedAt).format('YYYY-MM-DD HH:mm:ss'); trainee.updatedAt = moment(trainee.updatedAt).format('YYYY-MM-DD HH:mm:ss');
this.trainee = trainee; this.trainee = trainee;
this.getBookingList(trainee.id);
this.getInventoryList(trainee.id);
this.getDietList(trainee.id);
this.getExerciseList(trainee.id);
}) })
.catch((e) => { .catch((e) => {
this.error.message = e.message; this.error.message = e.message;
...@@ -165,6 +477,10 @@ export default { ...@@ -165,6 +477,10 @@ export default {
trainee.createdAt = moment(trainee.createdAt).format('YYYY-MM-DD HH:mm:ss'); trainee.createdAt = moment(trainee.createdAt).format('YYYY-MM-DD HH:mm:ss');
trainee.updatedAt = moment(trainee.updatedAt).format('YYYY-MM-DD HH:mm:ss'); trainee.updatedAt = moment(trainee.updatedAt).format('YYYY-MM-DD HH:mm:ss');
this.trainee = trainee; this.trainee = trainee;
this.getBookingList(trainee.id);
this.getInventoryList(trainee.id);
this.getDietList(trainee.id);
this.getExerciseList(trainee.id);
}) })
.catch((e) => { .catch((e) => {
this.error.message = e.message; this.error.message = e.message;
...@@ -199,6 +515,220 @@ export default { ...@@ -199,6 +515,220 @@ export default {
this.isProcessing = false; this.isProcessing = false;
}); });
}, },
getBookingList(id) {
this.booking.error.isError = false;
this.booking.error.message = '';
this.booking.isProcessing = true;
fetch(APISetting.endpoints.trainee.booking(id), APISetting.settings.get)
.then((res) => {
if (res.status === 200) return res.json();
throw new Error('알 수 없는 응답입니다.');
})
.then((json) => {
this.booking.list.data = json.bookings;
this.booking.list.data.forEach((item) => {
// eslint-disable-next-line no-param-reassign
item.schedule.startAt = moment(item.schedule.startAt).format('YYYY-MM-DD HH:mm:ss');
// eslint-disable-next-line no-param-reassign
item.createdAt = moment(item.createdAt).format('YYYY-MM-DD HH:mm:ss');
});
})
.catch((e) => {
this.booking.error.message = e.message;
this.booking.error.isError = true;
})
.finally(() => {
this.booking.isProcessing = false;
});
},
editBooking(id) {
this.$router.push(`/booking/${id}`);
},
deleteBooking(id) {
this.booking.error.isError = false;
this.booking.error.message = '';
this.booking.isProcessing = true;
fetch(APISetting.endpoints.booking.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.getBookingList(id);
throw new Error(json.message);
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = true;
});
},
getDietList() {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.diet.list, APISetting.settings.get)
.then((res) => {
if (res.status === 200) return res.json();
throw new Error('알 수 없는 응답입니다.');
})
.then((json) => {
this.diet.list.data = json.diets;
this.diet.list.data.forEach((diet) => {
// eslint-disable-next-line no-param-reassign
diet.hasFeedback = diet.feedback ? '완료' : '미완료';
// eslint-disable-next-line no-param-reassign
diet.createdAt = moment(diet.createdAt).format('YYYY-MM-DD HH:mm:ss');
});
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = false;
});
},
editDiet(id) {
this.$router.push(`/diet/${id}`);
},
deleteDiet(id) {
this.error.isError = false;
this.error.message = '';
this.isProcessing = true;
fetch(APISetting.endpoints.diet.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.getDietList();
throw new Error(json.message);
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = true;
});
},
getInventoryList(id) {
this.inventory.error.isError = false;
this.inventory.error.message = '';
this.inventory.isProcessing = true;
fetch(APISetting.endpoints.trainee.inventory(id), APISetting.settings.get)
.then((res) => {
if (res.status === 200) return res.json();
throw new Error('알 수 없는 응답입니다.');
})
.then((json) => {
this.inventory.list.data = json.inventories;
this.inventory.list.data.forEach((item) => {
// eslint-disable-next-line no-param-reassign
item.createdAt = moment(item.createdAt).format('YYYY-MM-DD HH:mm:ss');
});
})
.catch((e) => {
this.inventory.error.message = e.message;
this.inventory.error.isError = true;
})
.finally(() => {
this.inventory.isProcessing = false;
});
},
editInventory(id) {
this.$router.push(`/inventory/${id}`);
},
deleteInventory(id) {
this.inventory.error.isError = false;
this.inventory.error.message = '';
this.inventory.isProcessing = true;
fetch(APISetting.endpoints.inventory.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.getInventoryList(id);
throw new Error(json.message);
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = true;
});
},
getExerciseList(id) {
this.exercise.error.isError = false;
this.exercise.error.message = '';
this.exercise.isProcessing = true;
fetch(APISetting.endpoints.trainee.exercise(id), APISetting.settings.get)
.then((res) => {
if (res.status === 200) return res.json();
throw new Error('알 수 없는 응답입니다.');
})
.then((json) => {
this.exercise.list.data = json.exercises;
this.exercise.list.data.forEach((item) => {
// eslint-disable-next-line no-param-reassign
item.hasFeedback = item.feedback ? '완료' : '미완료';
// eslint-disable-next-line no-param-reassign
item.createdAt = moment(item.createdAt).format('YYYY-MM-DD HH:mm:ss');
});
})
.catch((e) => {
this.exercise.error.message = e.message;
this.exercise.error.isError = true;
})
.finally(() => {
this.exercise.isProcessing = false;
});
},
editExercise(id) {
this.$router.push(`/exercise/${id}`);
},
deleteExercise(id) {
this.exercise.error.isError = false;
this.exercise.error.message = '';
this.exercise.isProcessing = true;
fetch(APISetting.endpoints.exercise.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.getExerciseList(id);
throw new Error(json.message);
})
.catch((e) => {
this.error.message = e.message;
this.error.isError = true;
})
.finally(() => {
this.isProcessing = true;
});
},
}, },
created() { created() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment