Initial Nuxt frontend import
Some checks failed
continuous-integration/drone/push Build is failing

- 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:
Joris Slagter
2025-12-02 17:48:48 +01:00
parent 0f691e83e3
commit 791aebc346
290 changed files with 113801 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
<template>
<v-footer app class="grey--text overline" id="admin-footer">
<span class="mr-2">3110</span>
<span>&copy; Turning thougts into pixels</span>
<!-- <span>{{ new Date().getFullYear() }}</span> -->
<v-spacer />
<v-btn text small class="grey--text">General terms</v-btn>
<v-btn text small class="grey--text">Privacy Settings</v-btn>
<v-btn text small class="grey--text">Help</v-btn>
</v-footer>
</template>
<style>
#admin-footer {
border-top: 1px solid #dfdbe3 !important;
z-index: 4
}
</style>

View File

@@ -0,0 +1,213 @@
<template>
<v-list class="pa-4">
<div class="mt-4 mb-10 d-flex">
<v-btn fab text class="mr-6" @click="$emit('close-left-menu')">
<v-icon x-small>icon-close</v-icon>
</v-btn>
<router-link :to="localePath('/manager')">
<app-logo width="180" />
</router-link>
<v-spacer />
</div>
<v-list-group
v-for="item in items"
:key="item.title"
v-model="item.active"
:prepend-icon="item.icon"
no-action
color="accent"
append-icon=""
>
<template v-slot:activator>
<v-list-item-content>
<v-list-item-subtitle v-text="item.title"></v-list-item-subtitle>
</v-list-item-content>
</template>
<template v-for="subItem in item.items">
<v-list-item
nuxt
@click
exact
:key="subItem.title"
:to="localePath(subItem.to)"
>
<v-list-item-content>
<v-list-item-subtitle v-text="subItem.title"></v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</template>
</v-list-group>
</v-list>
</template>
<script>
import Util from '~/util'
import AppLogo from '~/components/Logo'
export default {
components: {
AppLogo,
},
data() {
return {
drawer: null,
item: 1,
roles: [],
}
},
mounted() {
this.roles = this.$auth.user.roles.map(({ name }) => name);
},
methods: {
shouldShowItemByAllowRules(allowRules) {
for (const allowRule of allowRules) {
if (!this.checkAllowRule(allowRule)) {
return false;
}
}
return true;
},
checkAllowRule(allowRule) {
if (Array.isArray(allowRule)) {
return Util.findCommonValuesInArray(allowRule, this.roles);
} else if ('boolean' === typeof allowRule) {
return allowRule;
} else {
throw new Error('Unexpected allow rule');
}
},
},
computed: {
userIsOnlyMemberEditor() {
return this.$store.getters.isOnlyMemberEditor;
},
items() {
const itemsArray = [
{
icon: 'icon-learningproducts',
title: this.$t('learning.products'),
allowed: [['super_admin', 'admin', 'operator']],
items: [
{
title: this.$t('learning.all_products'),
to: '/manager/learning/',
allowed: [['super_admin', 'admin', 'operator', 'user']],
},
{
title: this.$t('learning.filters.title'),
to: '/manager/learning/filters',
allowed: [['super_admin', 'admin', 'operator']],
},
{
title: this.$t('learning.synonyms'),
to: '/manager/learning/synonyms/',
allowed: [['super_admin', 'admin', 'operator']],
},
{
title: this.$t('learning.quality_standards'),
to: '/manager/learning/quality-standards/',
allowed: [['super_admin', 'admin', 'operator']],
},
],
},
{
icon: 'icon-members',
title: this.$t('auth.account.management'),
allowed: [['super_admin']],
items: [
{
title: this.$t('learning.manage'),
to: '/manager/accounts/',
allowed: [['super_admin', 'admin']],
},
],
},
{
icon: 'icon-members',
title: this.$t('members.management'),
allowed: [
['super_admin', 'admin', 'operator', 'user'],
!this.userIsOnlyMemberEditor,
],
items: [
{
title: 'Ledencontrole',
to: '/manager/members/control',
allowed: [['super_admin', 'admin']],
},
{
title: this.$store.getters.isSuperAdminOrAdmin
? this.$t('learning.manage')
: 'Alle leden',
to: '/manager/members/',
allowed: [['super_admin', 'admin', 'operator', 'user']],
},
{
title: 'Branches',
to: '/manager/members/branches',
allowed: [['super_admin', 'admin']],
},
],
},
{
icon: 'icon-members',
title: this.$t('members.managementinfo'),
allowed: [['super_admin', 'admin', 'operator']],
items: [
{
title: this.$t('members.report'),
to: '/manager/members/report',
allowed: [['member']],
},
{
title: this.$t('members.manage'),
to: '/manager/members/managementinfo',
allowed: [['super_admin', 'admin']],
},
],
},
{
icon: 'icon-attributes',
title: 'Lidmaatschapgegevens',
allowed: [this.userIsOnlyMemberEditor],
items: [{
title: 'Bekijken',
to: '/manager/members',
}],
},
{
icon: 'icon-managementinfo',
title: 'Managementinformatie',
allowed: [this.userIsOnlyMemberEditor],
items: [{
title: this.$t('members.report'),
to: '/manager/members/report',
}],
},
];
return itemsArray.filter(item => {
if (!('allowed' in item)) {
return true;
} else if (Array.isArray(item.allowed)) {
return this.shouldShowItemByAllowRules(item.allowed);
} else {
throw new Error('Expected allow ruleset to be an array');
}
});
},
},
}
</script>

View File

@@ -0,0 +1,85 @@
<template>
<v-card class="pa-6" :color="$vuetify.theme.dark ? 'primary' : 'txt'" flat>
<v-card-title class="white--text lighten-1 font-weight-bold"
>{{ $t('general.hi') }}
{{ $auth.user.first_name | capitalize }}!</v-card-title
>
<v-card-text class="white--text text font-weight-light">
<span v-if="hasNotifications">
{{ $t('general.dashboard.current') }}
<span
class="warning--text mx-1"
@click.stop="
$store.commit('navigation/SWITCH_RIGHT_DRAWER', {
component: 'Notifications',
})
"
:style="{ cursor: 'pointer' }"
>{{ notifications.length }} {{ $t('rightMenu.notes') }}</span
>
{{ $t('general.dashboard.require') }}<br
/></span>
<span v-if="$store.getters.isMember">
Goed om je te zien. Update de lidmaatschapgegevens of bekijk de management informatie via de tegels hieronder of via het menu.</span>
<span v-else>Welkom in je dashboard van MijnGGZEcademy. Klik op onderstaande tegels of navigeer via het menu linksboven in je scherm.<br /><br />
Succes!</span>
<span v-if="$auth.user.last_login_at">
De laatste keer heb je ingelogd op
{{ formatDate($auth.user.last_login_at) }}. Fijne dag!
</span>
</v-card-text>
<v-img
class="img plant"
:src="require(`@/assets/img/plant.png`)"
contain
></v-img>
<v-img
class="img cat"
:src="require(`@/assets/img/cat.png`)"
contain
></v-img>
</v-card>
</template>
<script>
import dayjs from 'dayjs'
import nl from 'dayjs/locale/nl'
export default {
computed: {
notifications() {
return this.$store.getters.notifications
},
hasNotifications() {
return this.$store.getters.hasNotifications
},
},
methods: {
formatDate(date) {
dayjs.locale('nl')
return dayjs(date).format('dddd D MMMM YYYY').toLowerCase()
},
},
}
</script>
<style lang="scss" scoped>
.text {
width: 650px;
color: white !important;
}
.img {
position: absolute;
}
.plant {
right: -35px;
top: -21px;
}
.cat {
right: 150px;
top: -96px;
}
</style>

View File

@@ -0,0 +1,6 @@
<template class="m-12">
<span class="ml-19" style="text-transform: none !important; letter-spacing: normal !important; font-size: 12px; color: #bac7cb;"
>&copy; {{ new Date().getFullYear() }} MijnGGZEcademy is onderdeel van GGZ
Ecademy Coöperatie U.A.</span
>
</template>

View File

@@ -0,0 +1,21 @@
<template>
<v-footer app class="overline" color="primary" height="60">
<span class="grey--text"> <Copyright /> </span>
<v-spacer />
<v-btn text x-small href="https://www.ggzecademy.nl" target="_blank"
>ggzecademy.nl</v-btn
>
<v-btn text x-small href="https://portaal.ggzecademy.nl" target="_blank">centraal leerplatform</v-btn>
<v-btn text x-small href="https://support.ggzecademy.nl" target="_blank">support platform</v-btn>
</v-footer>
</template>
<script>
import Copyright from '@/components/Admin/ggz/Footer/Copyright'
export default {
components: {
Copyright,
},
}
</script>