- Complete GGZ Ecademy Nuxt.js user portal - Learning products browser and management - Member management interface - User authentication and roles - Multi-language support (NL/EN) - Vuex store for state management - Component-based architecture
This commit is contained in:
604
components/Learning/ProductOverview/Accreditation.vue
Normal file
604
components/Learning/ProductOverview/Accreditation.vue
Normal file
@@ -0,0 +1,604 @@
|
||||
<template>
|
||||
<accordion-card :title="$t('learning.product_overview.accreditation')">
|
||||
<v-data-table
|
||||
:headers="headers"
|
||||
:items="accreditations"
|
||||
:options="options"
|
||||
hide-default-footer
|
||||
item-key="accreditation"
|
||||
flat
|
||||
v-if="hasAccreditations"
|
||||
>
|
||||
<!-- Translates dynamically headers -->
|
||||
<template v-for="h in headers" v-slot:[`header.${h.value}`]="{ header }">
|
||||
{{ h.text ? $t(`learning.accreditation.${h.text}`) : '' }}
|
||||
</template>
|
||||
|
||||
<template v-slot:item.register="{ item }">
|
||||
{{ getFilterItem('register', item).title }}
|
||||
</template>
|
||||
|
||||
<template v-slot:item.date_start="{ item }">
|
||||
{{ formatDate(item.date_start) }}
|
||||
</template>
|
||||
|
||||
<template v-slot:item.date_end="{ item }">
|
||||
{{ formatDate(item.date_end) }}
|
||||
</template>
|
||||
|
||||
<template v-slot:item.actions="{ item }">
|
||||
<v-menu
|
||||
offset-y
|
||||
v-if="
|
||||
editMode && ($store.getters.isAdmin || $store.getters.isOperator)
|
||||
"
|
||||
>
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-hover v-slot:default="{ hover }">
|
||||
<v-btn
|
||||
:color="hover ? 'info' : ''"
|
||||
:outlined="hover"
|
||||
depressed
|
||||
fab
|
||||
small
|
||||
v-on="on"
|
||||
>
|
||||
<v-icon>icon-options</v-icon>
|
||||
</v-btn>
|
||||
</v-hover>
|
||||
</template>
|
||||
<v-list width="200">
|
||||
<v-list-item @click="editItem(item)">
|
||||
<v-list-item-icon class="mr-1">
|
||||
<v-icon small>icon-edit</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-subtitle>{{
|
||||
$t('general.edit') | capitalize
|
||||
}}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<v-dialog max-width="740" persistent v-model="dialogDelete">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-list-item v-on="on">
|
||||
<v-list-item-icon class="mr-1">
|
||||
<v-icon small>icon-remove</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-subtitle>{{
|
||||
$t('general.delete') | capitalize
|
||||
}}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</template>
|
||||
<v-card class="primary pa-10" flat>
|
||||
<v-card-title class="headline">
|
||||
{{ $t('learning.delete_accreditation_confirmation') }}
|
||||
</v-card-title>
|
||||
<v-card-actions>
|
||||
<div class="ma-4">
|
||||
<v-btn
|
||||
@click="deleteItem(item)"
|
||||
class="mx-2"
|
||||
color="accent"
|
||||
depressed
|
||||
rounded
|
||||
>{{ $t('general.delete') }}</v-btn
|
||||
>
|
||||
<v-btn
|
||||
@click="dialogDelete = false"
|
||||
class="mx-2"
|
||||
color="info"
|
||||
depressed
|
||||
rounded
|
||||
>{{ $t('general.cancel') }}</v-btn
|
||||
>
|
||||
</div>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-data-table>
|
||||
|
||||
<v-dialog
|
||||
v-model="dialogAccreditation"
|
||||
max-width="75%"
|
||||
v-if="editMode && ($store.getters.isAdmin || $store.getters.isOperator)"
|
||||
>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn
|
||||
class="cta-secondary my-10"
|
||||
block
|
||||
depressed
|
||||
min-height="60px"
|
||||
:disabled="isCreateMode"
|
||||
v-on="on"
|
||||
@click="resetAccreditationsFilters"
|
||||
>
|
||||
<v-icon x-small class="mx-4">icon-add</v-icon>
|
||||
|
||||
{{ $t('learning.add_new_accreditation') }}</v-btn
|
||||
>
|
||||
</template>
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<span class="headline">{{ formTitle }}</span>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t(`learning.filters.register`)
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<universalFilterSelector
|
||||
filterTitle="register"
|
||||
:editMode="editMode"
|
||||
target="accreditations"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-text-field
|
||||
v-model="editedItem.credits"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.accreditation_period')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="9" class="d-flex pl-2">
|
||||
<v-menu
|
||||
ref="menuStart"
|
||||
v-model="menuStart"
|
||||
:close-on-content-click="false"
|
||||
transition="scale-transition"
|
||||
offset-y
|
||||
margin-top="20px"
|
||||
min-width="290px"
|
||||
>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-text-field
|
||||
:name="`accreditation-start-date-${Math.random()}`"
|
||||
v-model="computedDateFormattedStart"
|
||||
append-icon="icon-events"
|
||||
max-height="100px"
|
||||
v-bind="attrs"
|
||||
v-on="on"
|
||||
readonly
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<v-icon v-on="on">icon-events</v-icon>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</template>
|
||||
<v-date-picker
|
||||
v-model="editedItem.date_start"
|
||||
no-title
|
||||
scrollable
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
locale="nl-NL"
|
||||
>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn text @click="menuStart = false">Cancel</v-btn>
|
||||
<v-btn
|
||||
text
|
||||
@click="$refs.menuStart.save(editedItem.date_start)"
|
||||
>OK</v-btn
|
||||
>
|
||||
</v-date-picker>
|
||||
</v-menu>
|
||||
<span class="mx-5 my-3 font-weight-bold">
|
||||
tot
|
||||
</span>
|
||||
<v-menu
|
||||
ref="menuEnd"
|
||||
v-model="menuEnd"
|
||||
:close-on-content-click="false"
|
||||
transition="scale-transition"
|
||||
offset-y
|
||||
min-width="290px"
|
||||
>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-text-field
|
||||
:name="`accreditation-end-date-${Math.random()}`"
|
||||
v-model="computedDateFormattedEnd"
|
||||
append-icon="icon-events"
|
||||
readonly
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
max-height="100px"
|
||||
v-bind="attrs"
|
||||
v-on="on"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<v-icon v-on="on">icon-events</v-icon>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</template>
|
||||
<v-date-picker
|
||||
v-model="editedItem.date_end"
|
||||
no-title
|
||||
scrollable
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
locale="nl-NL"
|
||||
>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn text @click="menuEnd = false">Cancel</v-btn>
|
||||
<v-btn text @click="$refs.menuEnd.save(editedItem.date_end)"
|
||||
>OK</v-btn
|
||||
>
|
||||
</v-date-picker>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-card-text>
|
||||
|
||||
<v-divider />
|
||||
<v-card-actions v-if="editMode">
|
||||
<v-btn
|
||||
class="ma-2 white--text"
|
||||
color="info"
|
||||
depressed
|
||||
rounded
|
||||
:disabled="loading"
|
||||
@click="save"
|
||||
>{{ $t('general.save') }}</v-btn
|
||||
>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
class="ma-2 white--text"
|
||||
color="txt"
|
||||
depressed
|
||||
text
|
||||
:disabled="loading"
|
||||
@click="close"
|
||||
>{{ $t('general.cancel') }}</v-btn
|
||||
>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<p v-if="isCreateMode" class="text-center">
|
||||
Bij het aanmaken van een nieuw product kiest u eerst voor 'Opslaan' om
|
||||
deze functie te activeren.
|
||||
</p>
|
||||
</accordion-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import accordionCard from '@/components/UI/AccordionCard/AccordionCard'
|
||||
import universalFilterSelector from '@/components/UniversalFilterSelector/UniversalFilterSelector'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
accordionCard,
|
||||
universalFilterSelector,
|
||||
},
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isCreateMode: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: {
|
||||
itemsPerPage: -1,
|
||||
},
|
||||
headers: [
|
||||
{ text: 'register', value: 'register' },
|
||||
{ text: 'credits', value: 'credits' },
|
||||
{ text: 'date_start', value: 'date_start' },
|
||||
{ text: 'date_end', value: 'date_end' },
|
||||
{ text: '', value: 'actions' },
|
||||
],
|
||||
accreditationEditMode: false,
|
||||
dialogAccreditation: false,
|
||||
dialogDelete: false,
|
||||
editedIndex: -1,
|
||||
editedItem: {
|
||||
date_start: '',
|
||||
date_end: '',
|
||||
credits: '',
|
||||
},
|
||||
defaultItem: {
|
||||
date_start: '',
|
||||
date_end: '',
|
||||
credits: '',
|
||||
},
|
||||
loading: false,
|
||||
date: null,
|
||||
menuStart: false,
|
||||
menuEnd: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
remote() {
|
||||
return this.$store.state.learning.remote
|
||||
},
|
||||
local() {
|
||||
return this.$store.state.learning.local
|
||||
},
|
||||
accreditations() {
|
||||
if (!this.local || !Array.isArray(this.local.accreditations)) return []
|
||||
return this.local.accreditations
|
||||
},
|
||||
hasAccreditations() {
|
||||
if (!this.accreditations) return false
|
||||
return this.accreditations.length > 0
|
||||
},
|
||||
formTitle() {
|
||||
return this.editedIndex === -1
|
||||
? this.$t('learning.new_accreditation')
|
||||
: this.$t('learning.edit_accreditation')
|
||||
},
|
||||
accreditationsFiltersSelected() {
|
||||
return this.$store.state.learning.accreditationsFiltersSelected
|
||||
},
|
||||
computedDateFormattedStart() {
|
||||
return this.formatDate(this.editedItem.date_start)
|
||||
},
|
||||
computedDateFormattedEnd() {
|
||||
return this.formatDate(this.editedItem.date_end)
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
dialogAccreditation(val) {
|
||||
val || this.close()
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
getFilterItem(filterTitle, accreditation) {
|
||||
const filter = this.$store.getters.getFilterByTitle(filterTitle)
|
||||
|
||||
const arrayTmp = []
|
||||
if (!accreditation.filters) return {}
|
||||
accreditation.filters.forEach((f) => {
|
||||
const filterItemTmp = this.$store.getters.getFilterItemById(
|
||||
f.filter_item_id
|
||||
)
|
||||
arrayTmp.push(filterItemTmp)
|
||||
})
|
||||
|
||||
const filterItem = arrayTmp.find((e) => e.filter_id === filter.id)
|
||||
return filterItem || {}
|
||||
},
|
||||
formatDate(date) {
|
||||
if (!date) return null
|
||||
|
||||
const [year, month, day, time] = date.replace(' ', '-').split('-')
|
||||
return `${day}/${month}/${year}`
|
||||
},
|
||||
|
||||
resetAccreditationsFilters() {
|
||||
this.$store.commit('learning/RESET_ACCREDITATIONS_FILTERS')
|
||||
},
|
||||
|
||||
setAccreditationsFilters(item) {
|
||||
item.filters.forEach(async (f) => {
|
||||
const filterItem = this.$store.getters.getFilterItemById(
|
||||
f.filter_item_id
|
||||
)
|
||||
|
||||
await this.$store.commit('learning/UPDATE_FILTERS', {
|
||||
filterId: filterItem.filter_id,
|
||||
target: 'accreditations',
|
||||
value: f.filter_item_id,
|
||||
})
|
||||
})
|
||||
|
||||
this.editedIndex = this.accreditations.indexOf(item)
|
||||
this.editedItem = Object.assign({}, item)
|
||||
this.$forceUpdate()
|
||||
},
|
||||
|
||||
close() {
|
||||
this.dialogAccreditation = false
|
||||
this.$nextTick(() => {
|
||||
this.editedItem = Object.assign({}, this.defaultItem)
|
||||
this.editedIndex = -1
|
||||
})
|
||||
},
|
||||
|
||||
setFiltersSelectedInEditedItem() {
|
||||
let accreditationFiltersItemsIds = []
|
||||
|
||||
for (const [key, value] of Object.entries(
|
||||
this.accreditationsFiltersSelected
|
||||
)) {
|
||||
accreditationFiltersItemsIds.push(value)
|
||||
}
|
||||
|
||||
this.editedItem['filter_items'] = accreditationFiltersItemsIds
|
||||
},
|
||||
|
||||
editItem(item) {
|
||||
if (!this.editMode) return
|
||||
this.setAccreditationsFilters(item)
|
||||
this.dialogAccreditation = true
|
||||
},
|
||||
|
||||
async deleteItem(item) {
|
||||
this.$nextTick(() => this.$nuxt.$loading.start())
|
||||
if (!item.id) {
|
||||
this.$notifier.showMessage({
|
||||
content: `No accredication to delete selected`,
|
||||
color: 'error',
|
||||
icon: 'icon-message',
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this.$axios.delete(`/accreditations/${item.id}`)
|
||||
|
||||
this.$store.commit('learning/DELETE_ACCREDITATION_LOCAL', item)
|
||||
|
||||
this.dialogDelete = false
|
||||
this.dialogAccreditation = false
|
||||
this.$nuxt.$loading.finish()
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Accreditation deleted`,
|
||||
color: 'success',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
} catch (error) {
|
||||
this.$nuxt.$loading.finish()
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to delete the selected accreditation`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
async save() {
|
||||
this.loading = true
|
||||
this.$nextTick(() => this.$nuxt.$loading.start())
|
||||
|
||||
// Edit mode
|
||||
if (this.editedIndex > -1) {
|
||||
try {
|
||||
this.editedItem.learning_product_id = this.local.id
|
||||
|
||||
this.setFiltersSelectedInEditedItem()
|
||||
|
||||
const response = await this.$axios.post(
|
||||
'/accreditations',
|
||||
this.editedItem
|
||||
)
|
||||
|
||||
this.$store.commit('learning/EDIT_ACCREDITATION_LOCAL', {
|
||||
index: this.editedIndex,
|
||||
accreditation: response.data,
|
||||
})
|
||||
|
||||
this.dialogAccreditation = false
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Accreditation stored`,
|
||||
color: 'success',
|
||||
icon: 'icon-checkmark',
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('save -> error', error)
|
||||
|
||||
this.dialogAccreditation = false
|
||||
|
||||
this.$nuxt.$loading.finish()
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to store the accreditation`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
// Create new mode
|
||||
} else {
|
||||
try {
|
||||
this.editedItem.learning_product_id = this.local.id
|
||||
|
||||
this.setFiltersSelectedInEditedItem()
|
||||
|
||||
const response = await this.$axios.post(
|
||||
'/accreditations',
|
||||
this.editedItem
|
||||
)
|
||||
|
||||
this.dialog = false
|
||||
|
||||
this.$store.commit('learning/ADD_ACCREDITATION_LOCAL', response.data)
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Accreditation stored`,
|
||||
color: 'success',
|
||||
icon: 'icon-checkmark',
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('save -> error', error)
|
||||
|
||||
this.dialogAccreditation = false
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to store the accreditation`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.$nuxt.$loading.finish()
|
||||
this.loading = false
|
||||
this.close()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.v-application >>> .v-menu__content{
|
||||
top: 230px !important;
|
||||
}
|
||||
.v-card >>> table,
|
||||
.v-card >>> .v-data-table-header tr,
|
||||
.v-card >>> .v-data-footer {
|
||||
background-color: var(--v-primary-base);
|
||||
}
|
||||
.v-card >>> .v-data-table-header th span {
|
||||
color: var(--v-tertiary-base);
|
||||
}
|
||||
.v-card >>> .text-start,
|
||||
.v-card >>> .v-icon,
|
||||
.v-dialog__content >>> .v-subheader,
|
||||
.v-dialog__content >>> i {
|
||||
color: var(--v-txt-base);
|
||||
font-weight: bold;
|
||||
}
|
||||
.v-dialog__content >>> .v-dialog {
|
||||
border: 4px solid var(--v-secAccent-base);
|
||||
/* box-shadow: inset 0px 0px 2px 2px var(--v-secAccent-base),
|
||||
inset 6px 6px 14px -14px var(--v-secAccent-base) !important; */
|
||||
}
|
||||
.v-dialog .v-card {
|
||||
background: var(--v-secondary-base);
|
||||
}
|
||||
|
||||
.v-dialog__content >>> .v-input__slot {
|
||||
background: var(--v-primary-base);
|
||||
border: 1px solid var(--v-lines-base);
|
||||
}
|
||||
.v-menu__content >>> .v-date-picker-table {
|
||||
height: 242px !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user