sajjad 3 years ago
commit fc51240d96

@ -1,6 +1,6 @@
import axios from "axios";
import url from "@/router/url";
import { getArray, setQuery } from "../resources/userResource";
import { getArray, setQuery, getJson } from "../resources/userResource";
import { getArray as getArrayTrainee } from "../resources/traineeResource";
export default class UserRepository {
@ -18,6 +18,12 @@ export default class UserRepository {
return getArrayTrainee(response.data)
}
}
async show(userId) {
let response = await axios.get(url("showUser", { user: userId }));
if (response.status === 200) {
return getJson(response.data.data);
}
}
async delete(userId) {
await axios.delete(url("destroyUser", { user: userId }));
}

@ -1,4 +1,5 @@
import { objectToFormData } from "@/utils/objectToFormData";
import { getJson as getJsonCountry } from "./countryResource";
export const getJson = (data) => ({
id: data.id,
first_name: data.first_name,
@ -13,9 +14,7 @@ export const getJson = (data) => ({
address: data.address,
email: data.email,
cell_number: data.cell_number,
is_admin: data.is_admin,
is_trainer: data.is_trainer,
country: data?.country,
country: data.country ? getJsonCountry(data?.country) : {},
country_id: data.country?.id,
created_courses_count: data.created_courses_count,
joined_courses_count: data.joined_courses_count,

@ -3,6 +3,7 @@ import { getJsonTrainer } from './trainerProgramResource';
import { getJsonSportCategory } from './sportCategoryPorgramResource';
export const getJson = (data) => ({
id: data.id,
active_trainee_count: data.active_trainee_count,
trainer: data.trainer ? getJsonTrainer(data.trainer) : {},
trainer_id: data.trainer_id,
sport_category: data.trainer ? getJsonSportCategory(data.trainer) : {},

@ -1,5 +1,6 @@
export const getJsonTrainer = (data) => ({
id: data.id,
name: data.name,
first_name: data.first_name,
last_name: data.last_name,
birthday: data.birthday,
@ -12,6 +13,4 @@ export const getJsonTrainer = (data) => ({
address: data.address,
email: data.email,
cell_number: data.cell_number,
is_admin: data.is_admin,
is_trainer: data.is_trainer,
});

@ -1,4 +1,5 @@
import { SetPagination, SetQueriesObject } from "@/utils/setQueriesObject";
import { getJson as getJsonCountry } from "./countryResource";
export const getJson = (data) => {
let role_id = null;
data.roles.map(x => role_id = x.id);
@ -23,8 +24,12 @@ export const getJson = (data) => {
role: role,
roles: data.roles,
role_id: role_id,
country: data.country ? getJsonCountry(data.country) : {},
created_courses_count: data.created_courses_count,
joined_courses_count: data.joined_courses_count
joined_courses_count: data.joined_courses_count,
created_at: data.created_at,
// joined_date -> The correct format of created_at
joined_date: data.created_at?.slice(0, 10),
})
};
export const getArray = ({ data, meta }) => {

@ -17,6 +17,7 @@ export const getJson = (data) => ({
set: data.set,
per_set: data.per_set,
estimate_time: data.estimate_time,
workout_category: data.workout_category
});
export const setData = (data) => ({
id: data.id,

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

@ -12,7 +12,7 @@
class="custom-btn ml-1"
height="32"
icon="WMi-trash"
@click.native="deleteBookmarksProgram(program.id)"
@click="deleteBookmarksProgram(program.id)"
/>
</div>
</div>

@ -39,7 +39,7 @@
height="26"
icon="WMi-trash"
class="custom-btn ml-1"
@click.native="deleteBookmarkWorkout(workout.id)"
@click="deleteBookmarkWorkout(workout.id)"
/>
</div>
</div>

@ -4,21 +4,17 @@
depressed
:height="height"
:width="width"
:class="`color-${color} ${bgColor}`"
:class="`color-${color} bg-${bgColor}`"
:type="type"
:x-small="xs"
:small="sm"
:large="lg"
:x-large="xl"
:loading="loading"
@click.native="$emit('click')"
>
<template v-if="text">
<template v-if="icon"
><v-icon
:size="size"
:class="[icon, { 'mr-1': !isModal, modal__icon: isModal }]"
></v-icon
></template>
<template v-if="icon"><v-icon :size="size" :class="icon"></v-icon></template>
{{ text }}
<template v-if="iconRight"
><v-icon :size="size" :class="[iconRight, 'ml-1']"></v-icon
@ -50,9 +46,6 @@ export default {
bgColor: {
default: "transparent",
},
isModal: {
default: false,
},
type: {
type: String,
default: "button",
@ -75,16 +68,12 @@ export default {
.filter-btn .v-btn__content .v-icon::before {
margin-left: 0 !important;
}
// .modal__icon::before {
// margin-right: 0 !important;
// margin-left: 0 !important;
// }
@import "../../../styles/setup/variables.scss";
@each $color, $value in $allColors {
.v-btn.color-#{ "" + $color} {
color: $value !important;
}
.v-btn.#{"" + $color} {
.v-btn.bg-#{"" + $color} {
background-color: $value !important;
}
}

@ -28,4 +28,10 @@ export default {
label: {},
},
};
</script>
</script>
<style>
.default__chip {
font-size: 16px !important;
font-family: "Montserrat-light";
}
</style>

@ -22,7 +22,7 @@
bg-color="white"
color="black"
v-if="hiddenInput"
@click.native="$refs.fileInput.$refs.input.click()"
@click="$refs.fileInput.$refs.input.click()"
/>
<v-file-input
accept="image/png, image/jpeg, image/bmp"

@ -7,11 +7,7 @@
dark
>
<main-back height="100%" :is-modal="true">
<component
:is="tag"
@submit="$emit('submit')"
:ref="tag == 'form' ? 'form' : null"
>
<component :is="tag" @submit="$emit('submit')" :ref="tag == 'form' ? 'form' : null">
<v-card class="wa__modal">
<div class="wa__modal-header">
<slot name="header" :modal="modal" :data="data" v-if="modal"></slot>
@ -19,9 +15,9 @@
<v-card-text class="wa__modal-content pb-0">
<slot :modal="modal" :data="data" v-if="modal"></slot>
</v-card-text>
<template v-if="!notFooter">
<div v-if="hasFooter" class="px-4">
<v-divider class="mb-0"></v-divider>
</template>
</div>
<v-card-actions class="wa__modal-footer px-0">
<slot name="footer" :modal="modal" :data="data" v-if="modal"></slot>
</v-card-actions>
@ -39,8 +35,8 @@ export default {
maxWidth: { default: null },
name: { default: null },
transition: { default: "slide-x-transition" },
notFooter: {
default: false,
hasFooter: {
default: true,
},
tag: {
default: "div",

@ -0,0 +1,79 @@
<template>
<div class="info__box pl-2">
<div class="info__title text-uppercase">{{ title }}</div>
<div class="info__sub__title">
<!-- If the sub title is text -->
<template v-if="subTitle">
<component
:is="tag"
:class="['white--text sub__text', { 'ml-n1': tag === 'pre' }]"
>
<slot name="sub-title" :text="subTitle">{{ subTitle }}</slot>
</component>
</template>
<!-- If the sub title is link -->
<template v-if="link">
<a :href="link" v-text="link" class="white--text link"></a>
</template>
<!-- If the subtitle is an array and needs a loop-->
<div>
<slot
name="items"
:item="item"
v-for="(item, i) in items"
:index="i"
:itemNumber="i + 1"
>
<Chip
class="item__chip mr-2"
:text="item"
label
sm
color="white"
text-color="black"
/>
</slot>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
},
subTitle: {
type: [String, Number],
},
link: {
type: String,
},
items: {
type: Array,
},
tag: {
type: String,
default: "div",
},
},
};
</script>
<style scoped>
.info__box {
line-height: 18px;
border-left: 1px solid #707070;
}
.info__box .info__title {
color: #bebebe;
font-size: 12px;
font-family: "Montserrat-regular";
}
.info__box .info__sub__title .link {
border-bottom: 1px solid #bebebe;
}
.info__box .info__sub__title .item__chip {
font-size: 16px;
font-family: "montserrat-light";
}
</style>

@ -169,6 +169,7 @@
label
color="white"
text-color="black"
classes="defult__chip"
sm
@close="removeTags(item)"
:text="item"

@ -11,7 +11,9 @@
<v-row>
<v-col cols="3">
<div>
<div class="series__name">series {{ seriesNumber }}: {{ series.name }}</div>
<div class="series__name" :title="series.name">
series {{ seriesNumber }}: {{ series.name }}
</div>
</div>
</v-col>
<v-col cols="3">

@ -19,7 +19,7 @@
height="54"
:text-mode="true"
size="xx-large"
@click.native="$_openModal('add_series')"
@click="$_openModal('add_series')"
/>
</div>
</div>

@ -9,7 +9,7 @@
>
<template #header>
<div class="close__modal">
<v-icon class="WMi-cancel-1" large @click="$_closeModal()"></v-icon>
<v-icon class="WMi-cancel-linear" @click="$_closeModal()"></v-icon>
</div>
</template>
<template #default>
@ -62,17 +62,14 @@
</div>
</template>
<template #footer>
<v-spacer></v-spacer>
<div class="d-flex justify-space-between align-items-center w-100 pb-10">
<div class="d-flex justify-space-between align-items-center w-100 pb-10 px-4">
<RectangleButton
class="btn__modal--cancel pl-0"
text="cancel"
icon="WMi-cancel-1"
icon="WMi-cancel-linear"
text-mode="text"
size="large"
:is-modal="true"
height="29"
@click.native="$_closeModal()"
@click="$_closeModal()"
/>
<RectangleButton
height="29"

@ -12,7 +12,7 @@
<div class="wa__program__image__button--icon">
<RectangleButton
v-if="role === 'admin'"
@click.native="verifyProgram(program.id)"
@click="verifyProgram(program.id)"
size="large"
class="custom-btn ml-1"
height="32"
@ -30,6 +30,7 @@
/>
</router-link>
<router-link
v-if="program.active_trainee_count === 0"
:to="{
name: 'editProgram',
params: { id: program.id },
@ -44,7 +45,7 @@
</router-link>
<RectangleButton
v-if="role === 'admin'"
@click.native="removeProgram(program.id)"
@click="removeProgram(program.id)"
size="large"
class="custom-btn ml-1"
height="32"
@ -53,7 +54,7 @@
</div>
</div>
</div>
<div class="title__box">
<div class="title__box" @click="openDetailModal">
<div class="d-flex align-center mt-1">
<div class="program__title">
{{ program.title }}
@ -77,7 +78,7 @@
text-color="black"
xs
label
class="mr-1 text-uppercase"
class="mr-1 text-uppercase program__chip"
:text="`${program.series_count} sets`"
/>
<Chip
@ -92,7 +93,7 @@
</div>
</template>
<script>
import { mapActions } from "vuex";
import { mapActions, mapGetters } from "vuex";
import toast from "@/utils/toast";
import { UserStorage } from "@/utils/storage";
@ -105,12 +106,29 @@ export default {
type: Object,
},
},
computed: {
...mapGetters("programs", ["getProgram"]),
},
methods: {
...mapActions("programs", ["verifyProgram", "deleteProgram"]),
...mapActions("programs", ["verifyProgram", "deleteProgram", "loadProgram"]),
removeProgram(id) {
toast.question("Are sure delete program?", "Delete program", () => {
this.deleteProgram(id);
});
console.log("this.program.active_trainee_count", this.program.active_trainee_count);
if (this.program.active_trainee_count === 0) {
console.log("is not started");
toast.question("Are sure delete program?", "Delete program", async () => {
await this.deleteProgram({ courseId: id, isStarted: false });
});
} else {
console.log("is started");
toast.question("Are sure delete program?", "Delete program", async () => {
await this.deleteProgram({ courseId: id, isStarted: true });
this.program.verified = false;
});
}
},
async openDetailModal() {
await this.loadProgram(this.program.id);
this.$_openModal("program_detail", { data: this.getProgram });
},
},
};
@ -164,6 +182,10 @@ export default {
.wa__program__image__button--icon {
width: max-content;
}
.program__chip {
font-size: 12px;
font-family: "montserrat-light";
}
</style>
<style>
.shrink .v-input__slot i {

@ -20,7 +20,7 @@
size="x-large"
:text-mode="true"
:text="getFilterCount ? getFilterCount : '0'"
@click.native="$_openModal('filters')"
@click="$_openModal('filters')"
/>
<router-link :to="{ name: 'addProgram' }" class="text-decoration-none">
<RectangleButton
@ -57,13 +57,17 @@
</main-back>
<div class="text-center">
<FiltersModal @filter="load" v-if="isModal('modal_filters')" />
<ProgramDetailModal @filter="load" v-if="isModal('modal_program_detail')" />
<UserDetailModal v-if="isModal('modal_user_detail')" />
</div>
</div>
</template>
<script>
import FiltersModal from "./Modals/FiltersModal.vue";
import SectionTitle from "../Global/Section/SectionTitle.vue";
import ProgramItem from "./Item.vue";
import FiltersModal from "./Modals/FiltersModal.vue";
import ProgramDetailModal from "./Modals/Detail.vue";
import UserDetailModal from "@/components/Users/Modals/Detail.vue";
import { mapGetters, mapActions, mapMutations } from "vuex";
import { UserStorage } from "@/utils/storage";
export default {
@ -71,6 +75,8 @@ export default {
SectionTitle,
ProgramItem,
FiltersModal,
ProgramDetailModal,
UserDetailModal,
},
data: () => ({
role: UserStorage.getRole() ? UserStorage.getRole() : null,

@ -0,0 +1,114 @@
<template>
<basic-modal width="900" transition="slide-x-transition" @open="openModal">
<template #header>
<div class="close__modal">
<v-icon class="WMi-cancel-linear" @click="$_closeModal()"></v-icon>
</div>
</template>
<template #default>
<div>
<SectionTitle
title="program details"
subTitle="The details you need"
:is-modal="true"
/>
</div>
<div class="mt-4 mb-10">
<v-row>
<v-col cols="4">
<img
class="program__img w-100"
:src="
program.thumbnail
? program.thumbnail
: 'https://via.placeholder.com/1280x720'
"
alt="program image"
/>
</v-col>
<v-col cols="8">
<v-row>
<v-col cols="12">
<Info title="NAME" :sub-title="program.title" />
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<Info title="trainer" :sub-title="program.trainer.name">
<template #sub-title="{ text }">
<div class="d-flex align-center">
<div class="sub__text--slot">{{ text }}</div>
<div>
<RectangleButton
size="large"
height="16"
class="btn-more ml-3 px-4 py-2 rounded"
text="know more"
color="white"
@click="openUserDetailModal"
/>
</div>
</div>
</template>
</Info>
</v-col>
</v-row>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<Info title="description" :sub-title="program.description" />
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<Info title="tags" :items="program.tags" />
</v-col>
</v-row>
</div>
</template>
<template #footer>
<v-spacer></v-spacer>
<div class="px-4">
<RectangleButton
height="29"
class="btn__modal--confirm custom-btn wa__f__m__eb"
text="close"
@click="$_closeModal()"
/>
</div>
</template>
</basic-modal>
</template>
<script>
import { mapGetters, mapActions } from "vuex";
export default {
name: "modal_program_detail",
data: () => ({
program: {},
}),
computed: {
...mapGetters("users", ["getUser"]),
},
methods: {
...mapActions("users", ["loadUser"]),
openModal({ data }) {
this.program = { ...data };
},
async openUserDetailModal() {
await this.loadUser(this.program.trainer.id);
this.$_openModal("user_detail", { data: this.getUser });
},
},
};
</script>
<style lang="scss" scoped>
.program__img {
border-radius: 5px;
}
.btn-more {
font-family: "Montserrat-extralight";
font-size: 10px;
border: 1px solid var(--color-white);
}
</style>

@ -7,7 +7,7 @@
>
<template #header>
<div class="close__modal">
<v-icon class="WMi-cancel-1" large @click="$_closeModal()"></v-icon>
<v-icon class="WMi-cancel-linear" @click="$_closeModal()"></v-icon>
</div>
</template>
<template #default>
@ -70,17 +70,14 @@
</div>
</template>
<template #footer>
<v-spacer></v-spacer>
<div class="d-flex justify-space-between align-items-center w-100">
<div class="d-flex justify-space-between align-items-center w-100 px-4">
<RectangleButton
class="btn__modal--cancel pl-0"
text="cancel"
icon="WMi-cancel-1"
icon="WMi-cancel-linear"
text-mode="text"
size="large"
:is-modal="true"
height="29"
@click.native="clearFilter"
@click="clearFilter"
/>
<RectangleButton
height="29"

@ -1,7 +1,7 @@
<template>
<div class="user__card">
<v-row>
<v-col cols="3">
<v-col cols="3" @click="openUserDetailModal">
<div class="d-flex align-center h-100" style="overflow: hidden">
<div style="line-height: 14px">
<div class="user__name wa__f__m__eb">
@ -43,9 +43,9 @@
<RectangleButton
height="35"
width="48"
class="ml-1 custom-btn"
class="ml-1 custom-btn"
icon="WMi-gold-medal"
@click.native="chageRole"
@click="chageRole"
v-if="role === 'admin'"
size="large"
/>
@ -64,7 +64,7 @@
class="ml-1 custom-btn"
icon=" WMi-trash"
size="large"
@click.native="removeUser(user.id)"
@click="removeUser(user.id)"
/>
<i class="WMi-right-open ml-3"></i>
</div>
@ -73,7 +73,7 @@
</div>
</template>
<script>
import { mapActions } from "vuex";
import { mapActions, mapGetters } from "vuex";
import { UserStorage } from "@/utils/storage";
import toast from "@/utils/toast";
export default {
@ -85,8 +85,11 @@ export default {
data: () => ({
role: UserStorage.getRole() ? UserStorage.getRole() : null,
}),
computed: {
...mapGetters("users", ["getUser", "getRoles"]),
},
methods: {
...mapActions("users", ["deleteUser"]),
...mapActions("users", ["deleteUser", "loadUser"]),
removeUser(id) {
toast.question("Are sure delete User?", "Delete User", () => {
this.deleteUser(id);
@ -95,10 +98,16 @@ export default {
chageRole() {
this.$emit("userId", this.user.id);
// let role = this.user.userRoles.map((role) => role.id);
// console.log(this.user.role_id ? this.user.role_id : null);
this.$_openModal("changeRole", {
role: this.user.role_id ? this.user.role_id : null,
roles: this.getRoles,
});
},
async openUserDetailModal() {
await this.loadUser(this.user.id);
this.$_openModal("user_detail", { data: this.getUser });
},
},
};
</script>

@ -24,7 +24,7 @@
height="54"
:text-mode="true"
:text="getFilterCount ? getFilterCount : '0'"
@click.native="$_openModal('filters')"
@click="$_openModal('filters', { roles: getRoles })"
/>
</div>
</div>
@ -54,15 +54,11 @@
</div> -->
</main-back>
<div class="text-center">
<ChangeRoleModal
:allRoles="getRoles"
:userId="id"
v-if="isModal('modal_changeRole')"
/><FiltersModal
<ChangeRoleModal :userId="id" v-if="isModal('modal_changeRole')" /><FiltersModal
@filter="load"
:allRoles="getRoles"
v-if="isModal('modal_filters')"
/>
<UserDetailModal v-if="isModal('modal_user_detail')" />
</div>
</div>
</template>
@ -70,6 +66,7 @@
import SectionTitle from "../Global/Section/SectionTitle.vue";
import ChangeRoleModal from "./Modals/ChangeRoleModal.vue";
import FiltersModal from "./Modals/FiltersModal.vue";
import UserDetailModal from "./Modals/Detail.vue";
import UserItem from "./Item.vue";
import { mapActions, mapGetters, mapMutations, mapState } from "vuex";
import { UserStorage } from "@/utils/storage";
@ -80,6 +77,7 @@ export default {
UserItem,
ChangeRoleModal,
FiltersModal,
UserDetailModal,
},
data: () => ({
role: UserStorage.getRole() ? UserStorage.getRole() : null,

@ -2,7 +2,7 @@
<basic-modal @open="openModal" width="458" transition="slide-x-transition">
<template #header>
<div class="close__modal">
<v-icon class="WMi-cancel-1" large @click="$_closeModal()"></v-icon>
<v-icon class="WMi-cancel-linear" @click="$_closeModal()"></v-icon>
</div>
</template>
<template #default>
@ -11,7 +11,7 @@
</div>
<v-item-group class="mt-10 mb-16" mandatory v-model="role_id" @change="change">
<v-row>
<v-col cols="12" v-for="(role, i) in allRoles" :key="i" class="py-1">
<v-col cols="12" v-for="(role, i) in roles" :key="i" class="py-1">
<v-item v-slot="{ active, toggle }" :value="role.id">
<main-back :social="true">
<v-card
@ -29,23 +29,20 @@
</v-item-group>
</template>
<template #footer>
<v-spacer></v-spacer>
<div class="d-flex justify-space-between align-items-center w-100">
<div class="d-flex justify-space-between align-items-center w-100 px-4">
<RectangleButton
class="btn__modal--cancel pl-0"
text="cancel"
icon="WMi-cancel-1"
icon="WMi-cancel-linear"
text-mode="text"
size="large"
:is-modal="true"
height="29"
@click.native="$_closeModal()"
@click="$_closeModal()"
/>
<RectangleButton
height="29"
class="btn__modal--confirm custom-btn wa__f__m__eb"
text="change"
@click.native="changeRole"
@click="changeRole"
:loading="changeRoleRequestLoading"
/>
</div>
@ -60,15 +57,13 @@ export default {
name: "modal_changeRole",
components: { SectionTitle },
props: {
allRoles: {
type: Array,
},
userId: {},
},
data: () => ({
role_id: null,
currectRoleId: null,
changeRoleRequestLoading: false,
roles: null,
}),
computed: {
form() {
@ -77,7 +72,8 @@ export default {
},
methods: {
...mapActions("users", ["updateRole"]),
openModal({ role }) {
openModal({ role, roles }) {
this.roles = { ...roles };
this.currectRoleId = role ? role : 0;
this.role_id = role ? role : 0;
},

@ -0,0 +1,97 @@
<template>
<basic-modal width="900" transition="slide-x-transition" @open="openModal">
<template #header>
<div class="close__modal">
<v-icon class="WMi-cancel-linear" @click="$_closeModal()"></v-icon>
</div>
</template>
<template #default>
<div>
<SectionTitle
title="user details"
subTitle="The details you need"
:is-modal="true"
/>
</div>
<div class="mt-4 mb-10">
<v-row>
<v-col cols="4">
<img
class="user__img w-100"
:src="user.profile ? user.profile : require('@Assets/anonymous.png')"
alt="user image"
/>
</v-col>
<v-col cols="8">
<v-row>
<v-col cols="6">
<Info title="NAME" :sub-title="user.first_name" />
</v-col>
<v-col cols="6">
<Info title="LAST NAME" :sub-title="user.last_name" />
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<Info title="EMAIL ADDRESS" :sub-title="user.email" />
</v-col>
</v-row>
<v-row>
<v-col cols="4">
<Info title="role" :sub-title="user.role" />
</v-col>
<v-col cols="4">
<Info title="joined date" :sub-title="user.joined_date" />
</v-col>
<v-col cols="4">
<Info title="BIRTHDAY" :sub-title="user.birthday" />
</v-col>
</v-row>
</v-col>
</v-row>
<v-row>
<v-col cols="3">
<Info title="country" :sub-title="user.country.name" />
</v-col>
<v-col cols="9">
<Info title="address" :sub-title="user.address" />
</v-col>
</v-row>
</div>
</template>
<template #footer>
<v-spacer></v-spacer>
<div class="px-4">
<RectangleButton
height="29"
class="btn__modal--confirm custom-btn wa__f__m__eb"
text="close"
@click="$_closeModal()"
/>
</div>
</template>
</basic-modal>
</template>
<script>
export default {
name: "modal_user_detail",
data: () => ({
user: {},
}),
methods: {
openModal({ data }) {
this.user = { ...data };
},
},
};
</script>
<style lang="scss" scoped>
.user__img {
border-radius: 5px;
}
.btn-more {
font-family: "Montserrat-extralight";
font-size: 10px;
border: 1px solid var(--color-white);
}
</style>

@ -4,10 +4,11 @@
transition="slide-x-transition"
tag="vee-form"
@submit="filterUser"
@open="openModal"
>
<template #header>
<div class="close__modal">
<v-icon class="WMi-cancel-1" large @click="$_closeModal()"></v-icon>
<v-icon class="WMi-cancel-linear" @click="$_closeModal()"></v-icon>
</div>
</template>
<template #default>
@ -61,17 +62,14 @@
</div>
</template>
<template #footer>
<v-spacer></v-spacer>
<div class="d-flex justify-space-between align-items-center w-100">
<div class="d-flex justify-space-between align-items-center w-100 px-4">
<RectangleButton
class="btn__modal--cancel pl-0"
text="clear"
icon="WMi-cancel-1"
icon="WMi-cancel-linear"
text-mode="text"
size="large"
:is-modal="true"
height="29"
@click.native="clearFilter"
@click="clearFilter"
/>
<RectangleButton
height="29"
@ -110,16 +108,17 @@ export default {
data: () => ({
filter: cloneDeep(defaultFilter),
role: UserStorage.getRole() ? UserStorage.getRole() : null,
allRoles: null,
}),
props: {
allRoles: {},
},
computed: {
...mapGetters("users", ["getFilters"]),
},
methods: {
...mapMutations("users", ["SET_FILTER_USER", "SET_IS_FILTERED_USER"]),
// ...mapActions("users", ["laodRoles"]),
openModal({ roles }) {
this.allRoles = roles;
},
filterUser() {
this.SET_IS_FILTERED_USER(true);
this.SET_FILTER_USER(this.filter);

@ -1,5 +1,5 @@
<template>
<div class="border-bottom">
<div class="border-bottom" @click="openDetailModal">
<v-row>
<v-col cols="4" class="pr-0">
<!-- <div
@ -30,7 +30,7 @@
text-color="black"
xs
label
class="mr-1 text-uppercase"
class="mr-1 text-uppercase workout__chip"
v-for="(item, i) in workout.tags"
:key="i"
:text="item"
@ -42,9 +42,9 @@
height="26"
icon="WMi-trash"
class="custom-btn ml-1"
@click.native="removeWorkout(workout.id)"
@click.native.stop="removeWorkout(workout.id)"
/>
<router-link
<!-- <router-link
:to="{
name: 'editWorkout',
params: { id: workout.id },
@ -56,6 +56,23 @@
icon="WMi-pencil"
class="custom-btn ml-1"
/>
</router-link> -->
<router-link
:to="{
name: 'editWorkout',
params: { id: workout.id },
}"
custom
v-slot="{ navigate, href }"
>
<a :href="href" @click.stop="navigate">
<RectangleButton
size="large"
height="26"
icon="WMi-pencil"
class="custom-btn ml-1"
/>
</a>
</router-link>
</div>
</div>
@ -66,21 +83,28 @@
</div>
</template>
<script>
import { mapActions } from "vuex";
import toast from '@/utils/toast'
import { mapActions, mapGetters } from "vuex";
import toast from "@/utils/toast";
export default {
props: {
workout: {
type: Object,
},
},
computed: {
...mapGetters("workouts", ["getWorkout"]),
},
methods: {
...mapActions("workouts", ["deleteWorkout"]),
...mapActions("workouts", ["deleteWorkout", "loadWorkout"]),
removeWorkout(id) {
toast.question("Are sure delete workout?", "Delete workout", () => {
this.deleteWorkout(id);
});
},
async openDetailModal() {
await this.loadWorkout(this.workout.id);
this.$_openModal("workout_detail", { data: this.getWorkout });
},
},
};
</script>
@ -106,4 +130,8 @@ export default {
height: 100%;
justify-content: space-between;
}
.workout__chip {
font-size: 12px;
font-family: "montserrat-light";
}
</style>

@ -19,7 +19,7 @@
class="custom-btn filter-btn mr-2"
height="54"
:text="getFilterCount ? getFilterCount : '0'"
@click.native="$_openModal('filters')"
@click="$_openModal('filters')"
/>
<router-link class="text-decoration-none" :to="{ name: 'addWorkout' }"
><RectangleButton
@ -52,6 +52,7 @@
</main-back>
<div class="text-center">
<FiltersModal @filter="load" v-if="isModal('modal_filters')" />
<DetailModal v-if="isModal('modal_workout_detail')" />
</div>
</div>
</template>
@ -59,12 +60,14 @@
import WorkoutItem from "./Item";
import SectionTitle from "../Global/Section/SectionTitle.vue";
import FiltersModal from "./Modals/FiltersModal.vue";
import DetailModal from "./Modals/Detail.vue";
import { mapGetters, mapActions, mapMutations } from "vuex";
export default {
components: {
WorkoutItem,
SectionTitle,
FiltersModal,
DetailModal,
},
computed: {
...mapGetters("workouts", [

@ -0,0 +1,114 @@
<template>
<basic-modal width="1200" transition="slide-x-transition" @open="openModal">
<template #header>
<div class="close__modal">
<v-icon class="WMi-cancel-linear" @click="$_closeModal()"></v-icon>
</div>
</template>
<template #default>
<div>
<SectionTitle
title="workout details"
subTitle="The details you need"
:is-modal="true"
/>
</div>
<div class="mt-4 mb-10">
<v-row>
<v-col cols="4">
<img
class="workout__img w-100"
:src="
workout.thumbnail
? workout.thumbnail
: 'https://via.placeholder.com/1280x720'
"
alt="workout image"
/>
</v-col>
<v-col cols="8">
<v-row>
<v-col cols="6">
<Info
title="category"
:sub-title="workout.workout_category.sport_category.name"
/>
</v-col>
<v-col cols="6">
<Info title="sub category" :sub-title="workout.workout_category.name" />
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<Info title="NAME" :sub-title="workout.name" />
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<Info title="a short quote" :sub-title="workout.title" />
</v-col>
</v-row>
</v-col>
</v-row>
<v-row>
<v-col cols="4">
<Info title="suggested course time?" :sub-title="workout.suggested_set" />
</v-col>
<v-col cols="4">
<Info
title="suggested times each course?"
:sub-title="workout.suggested_per_set"
/>
</v-col>
<v-col cols="4">
<Info title="suggested ESTIMATED TIME" :sub-title="workout.suggested_time" />
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<Info title="VIDEO LINK" :sub-title="workout.video" />
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<Info title="description" :sub-title="workout.description" />
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<Info title="tags" :items="workout.tags" />
</v-col>
</v-row>
</div>
</template>
<template #footer>
<v-spacer></v-spacer>
<div class="px-4">
<RectangleButton
height="29"
class="btn__modal--confirm custom-btn wa__f__m__eb"
text="close"
@click="$_closeModal()"
/>
</div>
</template>
</basic-modal>
</template>
<script>
export default {
name: "modal_workout_detail",
data: () => ({
workout: {},
}),
methods: {
openModal({ data }) {
this.workout = { ...data };
},
},
};
</script>
<style lang="scss" scoped>
.workout__img {
border-radius: 5px;
}
</style>

@ -7,7 +7,7 @@
>
<template #header>
<div class="close__modal">
<v-icon class="WMi-cancel-1" large @click="$_closeModal()"></v-icon>
<v-icon class="WMi-cancel-linear" @click="$_closeModal()"></v-icon>
</div>
</template>
<template #default>
@ -49,17 +49,14 @@
</div>
</template>
<template #footer>
<v-spacer></v-spacer>
<div class="d-flex justify-space-between align-items-center w-100">
<div class="d-flex justify-space-between align-items-center w-100 px-4">
<RectangleButton
class="btn__modal--cancel pl-0"
text="clear"
icon="WMi-cancel-1"
icon="WMi-cancel-linear"
text-mode="text"
size="large"
:is-modal="true"
height="29"
@click.native="clearFilter"
@click="clearFilter"
/>
<RectangleButton
height="29"

@ -46,7 +46,7 @@
height="26"
icon="WMi-trash"
class="custom-btn ml-1"
@click.native="removeWorkoutFromSeries(seriesWorkout)"
@click="removeWorkoutFromSeries(seriesWorkout)"
/>
<RectangleButton
size="large"

@ -20,7 +20,7 @@
size="xx-large"
height="54"
:text-mode="true"
@click.native="$_openModal('add_workout')"
@click="$_openModal('add_workout')"
/>
</div>
</div>
@ -44,21 +44,21 @@
</div>
</main-back>
<div class="text-center">
<AddWorkoutModal v-if="isModal('modal_add_workout')" />
<AttachWorkoutModal v-if="isModal('modal_add_workout')" />
</div>
</div>
</template>
<script>
import SectionTitle from "../Global/Section/SectionTitle.vue";
import WorkoutsSeriesItem from "./Item.vue";
import AddWorkoutModal from "./Modals/AddWorkoutModal.vue";
import AttachWorkoutModal from "./Modals/AttachWorkoutModal.vue";
import { mapGetters, mapActions, mapMutations } from "vuex";
export default {
components: {
SectionTitle,
WorkoutsSeriesItem,
AddWorkoutModal,
AttachWorkoutModal,
},
computed: {
...mapGetters("workoutToSeries", ["getWorkouts", "getProgramSeriesWorkoutsLoading"]),
@ -81,8 +81,8 @@ export default {
},
async created() {
await this.loadProgramSeriesWorkouts({
courseId: Number(this.programId),
seriesId: Number(this.seriesId),
courseId: +this.programId,
seriesId: +this.seriesId,
});
await this.SET_CURRENT_SERIES_ID(this.seriesId);
},

@ -2,13 +2,14 @@
<basic-modal
width="800"
transition="slide-x-transition"
tag="form"
tag="vee-form"
ref="modal"
@submit="WorkoutToSeries"
@close="closeModal"
>
<template #header>
<div class="close__modal">
<v-icon class="WMi-cancel-1" large @click="$_closeModal()"></v-icon>
<v-icon class="WMi-cancel-linear" @click="$_closeModal()"></v-icon>
</div>
</template>
<template #default>
@ -44,14 +45,7 @@
class="mt-3"
/> -->
<div class="pb-3 align mt-2">
<div
class="
series__workout__title
wa__f__m__eb
text-uppercase
mb-2
"
>
<div class="series__workout__title wa__f__m__eb text-uppercase mb-2">
{{ item.name }}
</div>
<div class="series__workout__description">
@ -65,9 +59,7 @@
<template v-if="Object.keys(selectedWorkout).length !== 0">
<v-divider class="mt-6"></v-divider>
<v-row class="mt-1">
<v-col cols="12"
><AddWorkoutsItem :addWorkout="selectedWorkout"
/></v-col>
<v-col cols="12"><AddWorkoutsItem :addWorkout="selectedWorkout" /></v-col>
</v-row>
</template>
<div class="mt-6">
@ -111,17 +103,14 @@
</div>
</template>
<template #footer>
<v-spacer></v-spacer>
<div class="d-flex justify-space-between align-items-center w-100">
<div class="d-flex justify-space-between align-items-center w-100 px-4">
<RectangleButton
class="btn__modal--cancel pl-0"
text="cancel"
icon="WMi-cancel-1"
icon="WMi-cancel-linear"
text-mode="text"
size="large"
:is-modal="true"
height="29"
@click.native="$_closeModal()"
@click="$_closeModal()"
/>
<RectangleButton
height="29"
@ -183,10 +172,7 @@ export default {
},
},
methods: {
...mapActions("workoutToSeries", [
"loadWorkoutsToSeries",
"addWorkoutToSeries",
]),
...mapActions("workoutToSeries", ["loadWorkoutsToSeries", "attachWorkoutToSeries"]),
...mapMutations("workoutToSeries", ["SET_FILTER_WORKOUTS_TO_SERIES"]),
closeModal() {
this.SET_FILTER_WORKOUTS_TO_SERIES({});
@ -194,20 +180,25 @@ export default {
async joinWorkout(id) {
this.workoutId = id;
let repository = new WorkoutToSeriesRepository();
this.selectedWorkout = await repository.show(this.workoutId);
let response = await repository.show(this.workoutId);
this.selectedWorkout = response;
this.form["set"] = response.suggested_set;
this.form["per_set"] = response.suggested_per_set;
this.form["estimate_time"] = response.suggested_time;
},
async WorkoutToSeries() {
console.log(this.workoutId);
if (this.workoutId) {
await this.addWorkoutToSeries({
await this.attachWorkoutToSeries({
data: this.form,
seriesId: Number(this.getCurrentSeriesId),
seriesId: +this.getCurrentSeriesId,
workoutId: this.workoutId,
});
this.isLoading = false;
this.$_closeModal();
return;
}
return toast.error("Please select a workout firstt", "Error");
toast.error("Please select a workout first", "Error");
},
},
async created() {
@ -239,4 +230,4 @@ export default {
.align {
line-height: 4px;
}
</style>
</style>

@ -53,6 +53,7 @@ const urls = {
indexProductCategories: "admin/product-categories",
// users
indexUsers: "admin/users",
showUser: "admin/users/:user",
destroyUser: "admin/users/:user",
indexTrainerTrainee: "trainer/trainees",
indexRoles: "admin/roles",

@ -55,14 +55,15 @@ export default {
const resource = await repository.update(data.id, data);
commit("UPDATE_PROGRAM", resource);
},
async deleteProgram({ commit }, courseId) {
async deleteProgram({ commit }, { courseId, isStarted }) {
let repository = new ProgramRepository();
if (role === 'admin') {
await repository.delete(courseId);
} else {
await repository.deleteTrainer(courseId);
}
commit('DELETE_PROGRAM', courseId);
console.log('is started', isStarted);
!isStarted && commit('DELETE_PROGRAM', courseId);
},
async verifyProgram({ commit }, courseId) {
let repository = new ProgramRepository();

@ -33,6 +33,11 @@ export default {
}
},
async loadUser({ commit }, userId) {
let repository = new UserRepository();
let resource = await repository.show(userId)
commit("SET_USER", resource);
},
async laodRoles({ commit }) {
let repository = new RoleRepository();
const resource = await repository.index();

@ -1,5 +1,6 @@
export default {
getUsers: state => state.users,
getUser: state => state.user,
getRoles: state => state.roles,
getPaginationUser: state => state.pagination,
getFilters: state => state.filters,

@ -4,6 +4,9 @@ export default {
SET_USERS(state, payload) {
Vue.set(state, "users", payload);
},
SET_USER(state, payload) {
Vue.set(state, "user", payload);
},
SET_PAGINATION(state, pagination) {
pagination = { ...state.pagination, ...pagination };
Vue.set(state, "pagination", pagination);

@ -1,5 +1,6 @@
export default {
users: [],
user: {},
roles: [],
pagination: {
itemsPerPage: 12

@ -26,7 +26,7 @@ export default {
// const resource = await repository.show(workoutId);
// commit("SET_WORKOUT_TO_SERIES", resource);
// },
async addWorkoutToSeries({ commit }, { data, seriesId, workoutId }) {
async attachWorkoutToSeries({ commit }, { data, seriesId, workoutId }) {
const resource = await repository.store(data, seriesId, workoutId);
commit("SET_PROGRAM_SERIES_WORKOUTS", resource.data);

@ -3,23 +3,33 @@
src: url("./font/montserrat/Montserrat-Regular.ttf") format("truetype");
/* Safari, Android, iOS */
}
@font-face {
font-family: "Montserrat-light";
src: url("./font/montserrat/Montserrat-Light.ttf") format("truetype");
/* Safari, Android, iOS */
}
@font-face {
font-family: "Montserrat-extralight";
src: url("./font/montserrat/Montserrat-ExtraLight.ttf") format("truetype");
/* Safari, Android, iOS */
}
@font-face {
font-family: "Montserrat-extrabold";
src: url("./font/montserrat/Montserrat-ExtraBold.ttf") format("truetype");
/* Safari, Android, iOS */
}
@font-face {
font-family: "Montserrat-medium";
src: url("./font/montserrat/Montserrat-Medium.ttf") format("truetype");
/* Safari, Android, iOS */
}
@font-face {
font-family: "Team-america";
src: url("./font/teamAmerica/TeamAmerica-oLVd.otf") format("truetype");
/* Safari, Android, iOS */
}
}

@ -17,6 +17,8 @@ import SideBar from '../components/Global/Section/SideBar';
import Loading from "../components/Global/Misc/Loading";
import NoItems from "../components/Global/Misc/NoItems";
import DataIterator from "../components/Global/Input/DataIterator.vue";
import SectionTitle from "@/components/Global/Section/SectionTitle.vue";
import Info from "@/components/Global/Section/Info";
import 'bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min.js';
@ -33,7 +35,9 @@ Vue.component('TimeInput', TimeInput);
Vue.component('basic-modal', BasicModal);
Vue.component('pagination', Pagination);
Vue.component('Chip', Chip);
Vue.component('SectionTitle', SectionTitle);
Vue.component('SideBar', SideBar);
Vue.component('Info', Info);
Vue.component('data-iterator', DataIterator);
Vue.component('loading', Loading);
Vue.component('no-items', NoItems);

@ -148,7 +148,7 @@
height="29"
lg
icon="WMi-left-open"
@click.native="toggleVerifyCodePage"
@click="toggleVerifyCodePage"
/>
</div>
</v-col>

Loading…
Cancel
Save