Merge pull request 'special_place_holder' (#6) from special_place_holder into master

Reviewed-on: https://git.lilianamodels.com/champya/champya-front/pulls/6
master
sajjad_talkhabi 2 years ago
commit a4f9727177

160
package-lock.json generated

@ -2844,63 +2844,6 @@
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
"dev": true "dev": true
}, },
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"loader-utils": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
"integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"ssri": { "ssri": {
"version": "8.0.1", "version": "8.0.1",
"resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
@ -2909,28 +2852,6 @@
"requires": { "requires": {
"minipass": "^3.1.1" "minipass": "^3.1.1"
} }
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.3",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
}
} }
} }
}, },
@ -12495,6 +12416,87 @@
} }
} }
}, },
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.3",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"loader-utils": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
"integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"vue-meta": { "vue-meta": {
"version": "2.4.0", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/vue-meta/-/vue-meta-2.4.0.tgz", "resolved": "https://registry.npmjs.org/vue-meta/-/vue-meta-2.4.0.tgz",

@ -0,0 +1,18 @@
import axios from "axios";
import url from '@/router/url';
import { setData, getArray, getJson } from '../resources/appSectionResource';
export default class AppSectionRepository {
async index({ modelType, modelId }) {
let response = await axios.get(url('indexAppSection', { model_type: modelType, model_id: modelId }));
if (response.status === 200) {
return getArray(response.data)
}
}
async update(data) {
let json = setData(data);
let response = await axios.post(url("updateAppSection"), json);
if (response.status === 201 || response.status === 200) {
return getJson(response.data.data);
}
}
}

@ -0,0 +1,22 @@
export const getJson = data => ({
id: data.id,
created_at: data.created_at,
model_type: data.model_type,
item_available: data.item_available,
page: data.page,
slug: data.slug,
sort: data.sort,
sub_title: data.sub_title,
title: data.title,
updated_at: data.updated_at,
});
export const getArray = ({ data }) => {
data = data.map(user => getJson(user));
return { data };
};
export const setData = data => ({
model_id: data.model_id,
model_type: data.model_type,
join_to: data.join_to,
})

@ -0,0 +1,124 @@
<template>
<basic-modal
@open="openModal"
tag="vee-form"
@submit="submit"
width="900"
transition="slide-x-transition"
>
<template #header>
<div class="close__modal">
<v-icon class="WMi-cancel-linear" @click="$_closeModal()"></v-icon>
</div>
</template>
<template #default>
<loading v-if="loading" class="loading-data" />
<div :class="{ 'loading-form': loading }">
<div>
<SectionTitle :title="title" :subTitle="subTitle" :is-modal="true" />
</div>
<div class="mt-8 mb-10">
<v-switch
v-for="item in items"
:key="item.id"
inset
color="#ffd600"
:label="item.title"
v-model="values[item.id]"
class="special__place__holder"
@change="changeSwitch(item.id)"
></v-switch>
</div>
</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="save"
type="submit"
/>
</div>
</template>
</basic-modal>
</template>
<script>
import AppSectionRepository from "@/abstraction/repository/appSectionRepository";
const repository = new AppSectionRepository();
export default {
name: "modal_app_section",
data: () => ({
loading: false,
form: {
join_to: [],
},
items: [],
values: [],
}),
props: {
title: {
type: String,
},
subTitle: {
type: String,
default: "Select a place holder",
},
},
methods: {
openModal({ model_id, model_type }) {
this.form["model_id"] = model_id;
this.form["model_type"] = model_type;
this.load({ model_id, model_type });
},
async load({ model_type, model_id }) {
try {
this.loading = true;
const { data } = await repository.index({
modelType: model_type,
modelId: model_id,
});
// Fill in items to display to the user
this.items = data;
this.items.map((item) => {
// Adjust the position of the switch (on or off)
this.values[item.id] = item.item_available;
// Get active items and fill join_to in form obj to send it
if (item.item_available) {
this.form.join_to.push(item.id);
}
});
} catch (error) {
return error;
} finally {
this.loading = false;
}
},
changeSwitch(id) {
const value = this.values[id];
if (value) {
this.form.join_to.push(id);
} else {
this.$delete(
this.form.join_to,
this.form.join_to.findIndex((x) => x === id)
);
}
},
async submit() {
await repository.update(this.form);
this.$_closeModal();
},
},
};
</script>
<style lang="scss">
/* -------------------- switch ------------------------------*/
.v-input--switch.special__place__holder label {
margin-bottom: 0;
color: var(--color-white) !important;
font-family: "montserrat-light" !important;
font-size: 26px !important;
}
</style>

@ -4,7 +4,9 @@
<img <img
class="wa__program__image w-100" class="wa__program__image w-100"
:src=" :src="
program.thumbnail ? program.thumbnail : 'https://via.placeholder.com/1280x720' program.thumbnail
? program.thumbnail
: 'https://via.placeholder.com/1280x720'
" "
alt="product image" alt="product image"
/> />
@ -14,8 +16,8 @@
v-if="role === 'admin'" v-if="role === 'admin'"
@click="verifyProgram(program.id)" @click="verifyProgram(program.id)"
size="large" size="large"
class="custom-btn ml-1" class="custom-btn"
height="32" height="35"
:icon="program.verified ? 'WMi-cancel' : 'WMi-ok'" :icon="program.verified ? 'WMi-cancel' : 'WMi-ok'"
/> />
<router-link <router-link
@ -24,8 +26,8 @@
> >
<RectangleButton <RectangleButton
size="large" size="large"
class="custom-btn ml-1" class="custom-btn ml-2"
height="32" height="35"
icon="WMi-align-left" icon="WMi-align-left"
/> />
</router-link> </router-link>
@ -38,17 +40,30 @@
> >
<RectangleButton <RectangleButton
size="large" size="large"
class="custom-btn ml-1" class="custom-btn ml-2"
height="32" height="35"
icon="WMi-pencil" icon="WMi-pencil"
/> />
</router-link> </router-link>
<RectangleButton
v-if="role === 'admin'"
@click="
$_openModal('app_section', {
model_id: program.id,
model_type: 'course',
})
"
size="large"
class="custom-btn ml-2"
height="35"
icon="WMi-star"
/>
<RectangleButton <RectangleButton
v-if="role === 'admin'" v-if="role === 'admin'"
@click="removeProgram(program.id)" @click="removeProgram(program.id)"
size="large" size="large"
class="custom-btn ml-1" class="custom-btn ml-2"
height="32" height="35"
icon="WMi-trash" icon="WMi-trash"
/> />
</div> </div>
@ -96,7 +111,7 @@
import { mapActions, mapGetters } from "vuex"; import { mapActions, mapGetters } from "vuex";
import toast from "@/utils/toast"; import toast from "@/utils/toast";
import { UserStorage } from "@/utils/storage"; import { UserStorage } from "@/utils/storage";
import AppSectionRepository from "@/abstraction/repository/appSectionRepository";
export default { export default {
data: () => ({ data: () => ({
role: UserStorage.getRole() ? UserStorage.getRole() : null, role: UserStorage.getRole() ? UserStorage.getRole() : null,
@ -110,7 +125,11 @@ export default {
...mapGetters("programs", ["getProgram"]), ...mapGetters("programs", ["getProgram"]),
}, },
methods: { methods: {
...mapActions("programs", ["verifyProgram", "deleteProgram", "loadProgram"]), ...mapActions("programs", [
"verifyProgram",
"deleteProgram",
"loadProgram",
]),
removeProgram(id) { removeProgram(id) {
console.log("this.program.active_trainee_count", this.program.active_trainee_count); console.log("this.program.active_trainee_count", this.program.active_trainee_count);
if (this.program.active_trainee_count === 0) { if (this.program.active_trainee_count === 0) {

@ -59,6 +59,7 @@
<FiltersModal @filter="load" v-if="isModal('modal_filters')" /> <FiltersModal @filter="load" v-if="isModal('modal_filters')" />
<ProgramDetailModal @filter="load" v-if="isModal('modal_program_detail')" /> <ProgramDetailModal @filter="load" v-if="isModal('modal_program_detail')" />
<UserDetailModal v-if="isModal('modal_user_detail')" /> <UserDetailModal v-if="isModal('modal_user_detail')" />
<AppSectionModal v-if="isModal('modal_app_section')" title="make the program special" />
</div> </div>
</div> </div>
</template> </template>
@ -67,6 +68,7 @@ import ProgramItem from "./Item.vue";
import FiltersModal from "./Modals/FiltersModal.vue"; import FiltersModal from "./Modals/FiltersModal.vue";
import ProgramDetailModal from "./Modals/Detail.vue"; import ProgramDetailModal from "./Modals/Detail.vue";
import UserDetailModal from "@/components/Users/Modals/Detail.vue"; import UserDetailModal from "@/components/Users/Modals/Detail.vue";
import AppSectionModal from "@/components/Global/Modal/AppSection.vue";
import { mapGetters, mapActions, mapMutations } from "vuex"; import { mapGetters, mapActions, mapMutations } from "vuex";
import { UserStorage } from "@/utils/storage"; import { UserStorage } from "@/utils/storage";
export default { export default {
@ -75,6 +77,7 @@ export default {
FiltersModal, FiltersModal,
ProgramDetailModal, ProgramDetailModal,
UserDetailModal, UserDetailModal,
AppSectionModal,
}, },
data: () => ({ data: () => ({
role: UserStorage.getRole() ? UserStorage.getRole() : null, role: UserStorage.getRole() ? UserStorage.getRole() : null,

@ -9,7 +9,9 @@
<img <img
class="workout__img w-100" class="workout__img w-100"
:src=" :src="
workout.thumbnail ? workout.thumbnail : 'https://via.placeholder.com/1280x720' workout.thumbnail
? workout.thumbnail
: 'https://via.placeholder.com/1280x720'
" "
alt="workout image" alt="workout image"
/> />
@ -39,24 +41,16 @@
<div class="d-flex"> <div class="d-flex">
<RectangleButton <RectangleButton
size="large" size="large"
height="26" height="31"
icon="WMi-trash" icon="WMi-star"
class="custom-btn ml-1" class="custom-btn"
@click.native.stop="removeWorkout(workout.id)" @click.native.stop="
$_openModal('app_section', {
model_id: workout.id,
model_type: 'workout',
})
"
/> />
<!-- <router-link
:to="{
name: 'editWorkout',
params: { id: workout.id },
}"
>
<RectangleButton
size="large"
height="26"
icon="WMi-pencil"
class="custom-btn ml-1"
/>
</router-link> -->
<router-link <router-link
:to="{ :to="{
name: 'editWorkout', name: 'editWorkout',
@ -68,12 +62,19 @@
<a :href="href" @click.stop="navigate"> <a :href="href" @click.stop="navigate">
<RectangleButton <RectangleButton
size="large" size="large"
height="26" height="31"
icon="WMi-pencil" icon="WMi-pencil"
class="custom-btn ml-1" class="custom-btn ml-2"
/> />
</a> </a>
</router-link> </router-link>
<RectangleButton
size="large"
height="31"
icon="WMi-trash"
class="custom-btn ml-2"
@click.native.stop="removeWorkout(workout.id)"
/>
</div> </div>
</div> </div>
</div> </div>
@ -85,6 +86,8 @@
<script> <script>
import { mapActions, mapGetters } from "vuex"; import { mapActions, mapGetters } from "vuex";
import toast from "@/utils/toast"; import toast from "@/utils/toast";
import AppSectionRepository from "@/abstraction/repository/appSectionRepository";
export default { export default {
props: { props: {
workout: { workout: {

@ -53,6 +53,7 @@
<div class="text-center"> <div class="text-center">
<FiltersModal @filter="load" v-if="isModal('modal_filters')" /> <FiltersModal @filter="load" v-if="isModal('modal_filters')" />
<DetailModal v-if="isModal('modal_workout_detail')" /> <DetailModal v-if="isModal('modal_workout_detail')" />
<AppSectionModal v-if="isModal('modal_app_section')" title="make the workout special" />
</div> </div>
</div> </div>
</template> </template>
@ -60,12 +61,14 @@
import WorkoutItem from "./Item"; import WorkoutItem from "./Item";
import FiltersModal from "./Modals/FiltersModal.vue"; import FiltersModal from "./Modals/FiltersModal.vue";
import DetailModal from "./Modals/Detail.vue"; import DetailModal from "./Modals/Detail.vue";
import AppSectionModal from "@/components/Global/Modal/AppSection.vue";
import { mapGetters, mapActions, mapMutations } from "vuex"; import { mapGetters, mapActions, mapMutations } from "vuex";
export default { export default {
components: { components: {
WorkoutItem, WorkoutItem,
FiltersModal, FiltersModal,
DetailModal, DetailModal,
AppSectionModal,
}, },
computed: { computed: {
...mapGetters("workouts", [ ...mapGetters("workouts", [

@ -72,6 +72,9 @@ const urls = {
indexAdmin: "admin-dashboard-statistic", indexAdmin: "admin-dashboard-statistic",
indexTrainer: "trainer-dashboard-statistic", indexTrainer: "trainer-dashboard-statistic",
indexTrainee: "trainee-dashboard-statistic", indexTrainee: "trainee-dashboard-statistic",
// app section
indexAppSection: 'app-section-list/:model_type/:model_id',
updateAppSection: 'app-section-items',
// file // file
storeFile: "media", storeFile: "media",
destroyFile: "media/:media" destroyFile: "media/:media"

@ -285,7 +285,7 @@ input::placeholder {
/* -------------------- button on modal ------------------------------*/ /* -------------------- button on modal ------------------------------*/
.close__modal { .close__modal {
position: absolute; position: absolute;
top: 0; top: 13%;
right: 0; right: 0;
cursor: pointer; cursor: pointer;
} }

Loading…
Cancel
Save