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,341 @@
<template>
<div>
<div class="pa-6">
<page-header class="d-flex justify-space-between">
<div class="subtitle-1">
<span
:class="{ 'display-1': selector === 'published' }"
:style="{ cursor: 'pointer' }"
@click="selector = 'published'"
class="mr-4"
>Managementinformatie</span>
</div>
<div>
<!-- here checks -->
</div>
</page-header>
</div>
<!-- kaal -->
<div class="management-block-container">
<div class="row header-top">
<div class="col-md-2 titel">#</div>
<div class="col-md-3 titel">lid</div>
<div class="col-md-3 titel">rapportages</div>
</div>
<div class="management-block" v-for="member in members" :key="member.formal_name" >
<div class="header row">
<div class="col-md-2 titel">{{ member.id }}</div>
<div class="col-md-3 titel">{{ member.formal_name }}</div>
<div class="col-md-3 titel">{{ member.management_links.length }}</div>
</div>
<div class="body row">
<div class="link col-md-12" v-for="link in member.management_links" :key="link.url">
<div class="flex space-between h-50 space-between">
<div>
<strong class="titel">Rapportage</strong>
<span class="titel">{{member.formal_name}} (#{{member.id}})</span>
</div>
<div>
<button class="delete" @click="deleteLink(link.id)">
<span class="icon-close"></span>
</button>
</div>
</div>
<div class="form row">
<div class="col-md-4 flex flex-col">
<label>
<b class="titel">Titel</b>
</label>
<input
type="text"
class="link"
:value="link.title"
@change="setField($event, link.id, 'title')"
/>
<!-- <button class="demo" @click="openWindow(link.url)">
<span class="icon-download"></span>
</button>-->
</div>
<div class="col-md-4 flex flex-col">
<label>
<b class="url">Koppeling url</b>
</label>
<input
type="text"
class="link"
:value="link.url"
@change="setField($event, link.id, 'url')"
/>
</div>
<!-- <input type="text" :value="link.target" @change="setField($event, link.id, 'target')" /><br />-->
<div class="col-md-4">
<div class="flex flex-col p-0">
<label>
<b class="display">Weergave</b>
</label>
<div class="flex flex-row p-0">
<div class="col-md-6 p-0">
<label>
<input
class="radio"
type="radio"
value="self"
@change="setField($event, link.id, 'target')"
:checked="link.target === 'self'"
/>
IFrame
</label>
</div>
<div class="col-md-6 p-0">
<label>
<input
class="radio"
type="radio"
value="blank"
@change="setField($event, link.id, 'target')"
:checked="link.target === 'blank'"
/>
Externe link
</label>
</div>
</div>
</div>
</div>
</div>
</div>
<button @click="addLink(member.id)">
<span class="icon-add"></span>
<b class="toevoegen">Nog een rapportage koppeling toevoegen</b>
</button>
</div>
</div>
</div>
<v-footer
fixed
style="z-index: 4"
height="90"
color="primary"
v-if="$store.getters.isAdmin || $store.getters.isOperator"
>
<v-btn text nuxt :to="localePath('/manager')">
<v-icon>icon-arrow-left</v-icon>
</v-btn>
<div class="mx-10"></div>
<v-spacer />
</v-footer>
</div>
</template>
<script>
import Util from '@/util'
import PageHeader from '~/components/UI/PageHeader/PageHeader'
export default {
layout: `${process.env.CUSTOMER}Admin`,
middleware: 'allowSuperAdminOrAdmin',
components: {
PageHeader,
},
data() {
return {
selector: 'published',
showAddButton: false,
}
},
computed: {
members() {
return this.$store.getters['members/membersFiltered']
},
},
methods: {
async addLink(memberId) {
this.$nextTick(() => this.$nuxt.$loading.start())
try {
await this.$store.dispatch('members/addManagementLink', memberId)
this.$nuxt.$loading.finish()
} catch (error) {
console.log('addLink -> error', error)
this.$nuxt.$loading.finish()
}
},
async setField(e, linkId, target) {
let data = { value: e.target.value, link_id: linkId, field: target }
try {
await this.$store.dispatch('members/changeManagementLink', data)
} catch (error) {
console.log('addLink -> error', error)
}
},
async deleteLink(linkId) {
try {
await this.$store.dispatch('members/deleteManagementLink', linkId)
} catch (error) {
console.log('deleteLink -> error', error)
}
},
openWindow(url) {
window.open(url, '_blank').focus()
},
openBlock(){
this.showAddButton = !this.showAddButton;
}
},
async asyncData({ $axios, store }) {
try {
if (!store.getters['members/hasMembers']) {
await store.dispatch('members/pullData')
}
} catch (error) {
console.log('Data -> error', error)
}
},
async mounted() {},
async beforeRouteLeave(to, from, next) {
next()
},
}
</script>
<style scoped lang="scss">
.management-block-container {
background-color: var(--v-primary-base);
border-radius: 5px;
padding: 20px 40px;
.flex {
display: flex;
}
.flex-col {
flex-direction: column;
}
.flex-row {
flex-direction: row;
}
.p-0 {
padding: 0;
}
.h-50 {
height: 50px;
}
.space-between {
justify-content: space-between;
align-items: baseline;
}
span.icon-add {
position: relative;
top: 1px;
padding-right: 5px;
}
.titel,
.url,
.display,
.toevoegen,
.icon-add{
color: var(--v-txt-base);
}
}
.header-top {
font-size: 14px;
color: var(--v-txt-base);
font-weight: bold;
margin-bottom: 15px;
margin-top: 15px;
}
.header {
padding: 10px;
border: 1px solid var(--v-lines-base);
}
.body {
// border-bottom: 1px solid #eef7f9;
// border-left: 1px solid #eef7f9;
// border-right: 1px solid #eef7f9;
border: 1px solid var(--v-lines-base);
border-top: unset;
padding: 25px 10px;
margin-bottom: 35px;
}
.form {
margin-top: 15px;
margin-bottom: 35px;
}
.form div {
padding-top: 10px;
}
.form div {
padding-bottom: 10px;
}
.form {
background-color: var(--v-secondary-base);
position: relative;
}
.form input {
width: calc(100% - 30px);
background-color: var(--v-primary-base);
color: var(--v-txt-base);
border-radius: 5px;
padding: 4px;
border: 1px solid var(--v-lines-base);
}
.form input.link {
width: calc(100% - 46px);
padding: 10px;
}
.form label {
display: block;
line-height: 2.5;
}
button {
width: 100%;
margin: 15px auto 30px auto;
padding-top: 20px;
padding-bottom: 20px;
text-align: center;
border: 2px dashed var(--v-lines-base);
}
.delete {
right: -40px;
top: 8px;
border: 0px solid transparent;
width: auto;
z-index: 999;
}
.demo {
border: 0px solid transparent;
width: auto;
cursor: pointer;
}
.form input.radio {
width: 30px;
display: inline-block;
}
</style>