Files
nuxt-frontend/store/members.js
Joris Slagter 791aebc346
Some checks failed
continuous-integration/drone/push Build is failing
Initial Nuxt frontend import
- 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
2025-12-02 17:48:48 +01:00

678 lines
19 KiB
JavaScript

import Vue from 'vue'
import Util from '@/util'
export const state = () => ({
list: [],
remote: {},
local: {},
logo: {
name: '',
url: '',
file: null,
},
branches: [],
});
export const getters = {
hasMembers: (state) => state.list.length > 0,
hasChanges: (state) => {
if (!Util.areEqualInputs(
state.remote,
state.local,
['summaries', 'addresses', 'contacts', 'contributions']
)) return true
if (state.logo.url) return true
return false
},
revision: (state) => {
if (!state.local.revision) return false
return JSON.parse(state.local.revision.data)
},
revisionHasChanges: (state, getters) => {
if (!getters.revision) return false
if (Util.areEqualInputs(
state.local,
getters.revision
)) return true
return false
},
membersFiltered: (state, getters, rootState, rootGetters) => {
if (rootGetters.isSuperAdmin || rootGetters.isAdmin || rootGetters.isOperator) {
return state.list
}
if (rootGetters.loggedInUser.isMemberEditor) return state.list.filter(
(member) => member.user_id === rootGetters.loggedInUser.id
)
return state.list
},
isSuperAdminAdminOrDelegated: (state, getters, rootState, rootGetters) => {
if (rootGetters.isSuperAdmin || rootGetters.isAdmin) return true
if (!state.local.user_id) return false
return state.local.user_id === rootGetters.loggedInUser.id
},
isMemberValidated: (state) => {
return !!state.local.informal_name && !!state.local.formal_name && !!state.local.kvk_number
},
getBranchById: (state) => (id) => state.branches.find(b => b.id === id),
}
/** @type {import('@typedefs/store').ActionTree} */
export const actions = {
async pullData({ commit, state }) {
try {
const response = await this.$axios.get('/members')
await commit('STORE_MEMBERS', response.data)
} catch (error) {
console.log("pullMembers -> error", error)
$nuxt.$notifier.showMessage({
content: error,
color: "error",
icon: "mdi-close",
});
}
},
async pullBranches({ commit, state }) {
try {
const response = await this.$axios.get('members/branches')
await commit("STORE_BRANCHES", response.data)
} catch (error) {
console.log("pullBranches -> error", error)
$nuxt.$notifier.showMessage({
content: error,
color: "error",
icon: "mdi-close",
});
}
},
async pullTypes({ commit }) {
try {
const response = await this.$axios.get('members/types');
await commit('STORE_TYPES', response.data);
} catch (error) {
console.log('pullTypes -> error', error)
$nuxt.$notifier.showMessage({
content: error,
color: 'error',
icon: 'mdi-close',
});
}
},
async getAndSetMember({ commit, dispatch, state }, url) {
try {
const response = await dispatch('get', url)
await commit('SET_MEMBER', response)
} catch (error) {
$nuxt.$notifier.showMessage({
content: error,
color: "error",
icon: "mdi-close",
});
}
},
async get({ state }, url) {
try {
const response = await this.$axios.get(`/members/${url}`)
return response.data
} catch (error) {
$nuxt.error({ statusCode: 401, message: 'Lid niet gevonden' })
$nuxt.$notifier.showMessage({
content: error,
color: "error",
icon: "mdi-close",
});
}
},
async store({ dispatch, commit, state, getters, rootGetters }, revision = false) {
const formData = new FormData()
let data;
if (revision) {
data = { ...getters.revision }
if (revision.show_on_website) data.show_on_website = 1
if (data.sub_branches.some(branch => branch.id)) {
const subBranchesIds = data.sub_branches.map(({ id }) => id)
data.sub_branches = [...subBranchesIds]
}
data.revisor_id = rootGetters.loggedInUser.id
} else {
if (state.local.show_on_website) await commit('UPDATE_FIELD', { field: 'show_on_website', value: 1 })
if (state.local.sub_branches.some(branch => branch.id)) {
const subBranchesIds = state.local.sub_branches.map(({ id }) => id)
await commit('UPDATE_FIELD', { field: 'sub_branches', value: subBranchesIds })
}
data = { ...state.local }
}
const fieldsAllowedNull = this.$constants.store.members.fieldsAllowedNull
for (let key in data) {
if ((data[key] && data[key] != "null")
|| (data[key] === null && fieldsAllowedNull.indexOf(key) !== -1)
) {
const value = data[key] ?? ''
// If value is array/object, stringify that
formData.append(
key,
typeof value === 'object'
? JSON.stringify(value)
: value
)
}
}
if (state.logo.file) formData.append('logo', state.logo.file)
else formData.delete('logo')
let slug = '';
// console.log([...formData])
await this.$axios.post('/members', formData)
.then(async response => {
Promise.resolve(response)
await dispatch('pullData');
slug = response.data.slug
})
.catch(error => Promise.reject(error))
return slug
},
async storeRevision({ state, rootGetters, dispatch }) {
const formData = new FormData()
const tmpObj = { ...state.local }
// Remove not useful data attached
delete tmpObj.revision;
delete tmpObj.data;
delete tmpObj.addresses;
delete tmpObj.summaries;
delete tmpObj.contacts;
const revision = JSON.stringify(tmpObj)
if (state.local.revision) formData.append('id', state.local.revision.id)
if (state.logo.file) formData.append('logo', state.logo.file)
formData.append('member_id', state.local.id)
formData.append('user_id', rootGetters.loggedInUser.id)
formData.append('data', revision)
// console.log([...formData])
await this.$axios.post('/members/revision', formData)
.then(async response => {
Promise.resolve(response)
await dispatch('pullData');
})
.catch(error => Promise.reject(error))
},
async deleteMember({ dispatch, state }, memberId = state.remote.id) {
if (!memberId) return
try {
await this.$axios.delete(`/members/${memberId}`)
await dispatch('pullData');
$nuxt.$notifier.showMessage({
content: `Member deleted`,
color: 'success',
icon: 'mdi-delete',
});
} catch (error) {
console.log("deleteMember -> error", error)
$nuxt.$notifier.showMessage({
content: error,
color: "error",
icon: "mdi-close",
});
}
},
async storeSummary({ dispatch, state }, data) {
if (!state.remote.id) return
data['member_id'] = state.remote.id
if (data['toAll'] === false) { delete data['toAll'] }
await this.$axios.post(`/members/summaries`, data)
.then(async response => {
Promise.resolve(response)
await dispatch('getAndSetMember', data['member_id'])
$nuxt.$notifier.showMessage({
content: 'Werknemers opgeslagen',
color: 'success',
icon: 'mdi-check',
});
})
.catch(error => {
Promise.reject(error)
$nuxt.$notifier.showMessage({
content: error,
color: "error",
icon: "mdi-close",
});
})
},
async storeContribution({ dispatch, state, rootGetters }, data) {
if (!state.remote.id) return
if (!rootGetters.isSuperAdminOrAdmin && data.toAll) return
data['member_id'] = state.remote.id
if (data['toAll'] === false) { delete data['toAll'] }
await this.$axios.post(`/members/contributions`, data)
.then(async response => {
Promise.resolve(response)
// if (!data.toAll) {
await dispatch('getAndSetMember', data['member_id'])
// }
$nuxt.$notifier.showMessage({
content: `Contribution added`,
color: 'success',
icon: 'mdi-check',
});
})
.catch(error => {
Promise.reject(error)
$nuxt.$notifier.showMessage({
content: error,
color: "error",
icon: "mdi-close",
});
})
},
async storeAddress({ dispatch, state }, data) {
if (!state.remote.id) return
data['member_id'] = state.remote.id
await this.$axios.post(`/members/addresses`, data)
.then(async response => {
Promise.resolve(response)
await dispatch('getAndSetMember', data['member_id'])
$nuxt.$notifier.showMessage({
content: `Address added`,
color: 'success',
icon: 'mdi-check',
});
})
.catch(error => {
Promise.reject(error)
$nuxt.$notifier.showMessage({
content: error,
color: "error",
icon: "mdi-close",
});
})
},
async storeContact({ dispatch, state }, data) {
if (!state.remote.id) return
data['member_id'] = state.remote.id
await this.$axios.post(`/members/contacts`, data)
.then(async response => {
Promise.resolve(response)
await dispatch('getAndSetMember', data['member_id'])
$nuxt.$notifier.showMessage({
content: `Contact added`,
color: 'success',
icon: 'mdi-check',
});
})
.catch(error => {
Promise.reject(error)
$nuxt.$notifier.showMessage({
content: `${error.response ? error.response.data.message : error}.`,
...(error.response && {
errors: error.response.data.errors,
}),
color: "error",
icon: "mdi-close",
});
})
},
async deleteSummary({ commit, state }, item) {
if (!item.id) return
try {
await this.$axios.delete(`/members/summaries/${item.id}`)
await commit('DELETE_SUMMARY_LOCAL', item)
$nuxt.$notifier.showMessage({
content: `Summary deleted`,
color: 'success',
icon: 'mdi-delete',
});
} catch (error) {
console.log("addSummary -> error", error)
$nuxt.$notifier.showMessage({
content: error,
color: "error",
icon: "mdi-close",
});
}
},
async deleteContribution({ commit, state }, item) {
if (!item.id) return
try {
await this.$axios.delete(`/members/contributions/${item.id}`)
await commit('DELETE_CONTRIBUTION_LOCAL', item)
$nuxt.$notifier.showMessage({
content: `Contribution deleted`,
color: 'success',
icon: 'mdi-delete',
});
} catch (error) {
console.log(error)
$nuxt.$notifier.showMessage({
content: error,
color: "error",
icon: "mdi-close",
});
}
},
async addManagementLink({ dispatch, commit, stage }, data) {
if (!data) return
let link = { member_id: data };
await this.$axios.post(`/members/managementlink/addlink`, link)
.then(async response => {
Promise.resolve(response)
await dispatch('pullData');
$nuxt.$notifier.showMessage({
content: `Link added`,
color: 'success',
icon: 'mdi-check',
});
})
.catch(error => {
Promise.reject(error)
$nuxt.$notifier.showMessage({
content: `${error.response ? error.response.data.message : error}.`,
...(error.response && {
errors: error.response.data.errors,
}),
color: "error",
icon: "mdi-close",
});
})
},
async deleteManagementLink({ dispatch, commit, stage }, data) {
if (!data) return
let link = { link_id: data };
await this.$axios.post(`/members/managementlink/deletelink`, link)
.then(async response => {
Promise.resolve(response)
await dispatch('pullData');
$nuxt.$notifier.showMessage({
content: `Link removed`,
color: 'success',
icon: 'mdi-check',
});
})
.catch(error => {
Promise.reject(error)
$nuxt.$notifier.showMessage({
content: `${error.response ? error.response.data.message : error}.`,
...(error.response && {
errors: error.response.data.errors,
}),
color: "error",
icon: "mdi-close",
});
})
},
async changeManagementLink({ dispatch, commit, stage }, data) {
if (!data) return
await this.$axios.post(`/members/managementlink/changelink`, data)
.then(async response => {
Promise.resolve(response)
await dispatch('pullData');
$nuxt.$notifier.showMessage({
content: `Link added`,
color: 'success',
icon: 'mdi-check',
});
})
.catch(error => {
Promise.reject(error)
$nuxt.$notifier.showMessage({
content: `${error.response ? error.response.data.message : error}.`,
...(error.response && {
errors: error.response.data.errors,
}),
color: "error",
icon: "mdi-close",
});
})
},
async deleteAddress({ commit, state }, item) {
if (!item.id) return
try {
await this.$axios.delete(`/members/addresses/${item.id}`)
await commit('DELETE_ADDRESS_LOCAL', item)
$nuxt.$notifier.showMessage({
content: `Address deleted`,
color: 'success',
icon: 'mdi-delete',
});
} catch (error) {
console.log("deleteAddress -> error", error)
$nuxt.$notifier.showMessage({
content: error,
color: "error",
icon: "mdi-close",
});
}
},
async deleteContact({ commit, state }, item) {
if (!item.id) return
try {
await this.$axios.delete(`/members/contacts/${item.id}`)
await commit('DELETE_CONTACT_LOCAL', item)
$nuxt.$notifier.showMessage({
content: `Contact deleted`,
color: 'success',
icon: 'mdi-delete',
});
} catch (error) {
console.log("deleteContact -> error", error)
$nuxt.$notifier.showMessage({
content: error,
color: "error",
icon: "mdi-close",
});
}
},
async updateManagementLinks({ commit, state }, item) {
console.log(item);
},
async resetMember({ commit }) {
await commit('RESET_MEMBER');
await commit('RESET_LOGO');
},
}
export const mutations = {
STORE_MEMBERS: (state, payload) => state.list = payload,
STORE_BRANCHES: (state, payload) => state.branches = payload,
STORE_TYPES: (state, payload) => state.types = payload,
SET_MEMBER: (state, payload) => {
state.remote = { ...payload };
state.local = { ...payload };
},
UPDATE_FIELD: (state, payload) => {
// Old way with reactivity problems
// state.local[payload.field] = payload.value
// New way that solves with reactivity
Vue.set(state.local, payload.field, payload.value)
},
RESET_MEMBER: (state) => {
state.remote = {};
state.local = {};
},
RESET_MEMBERS: (state) => state.list = [],
RESET_LOGO: (state) => {
state.logo = {
name: '',
url: '',
file: null,
};
},
UPDATE_LOGO: (state, payload) => {
state.logo = payload;
},
DELETE_ADDRESS_LOCAL: (state, payload) => {
// Workaround because Vuex doesn't recognize changes otherwise
const tmp = [...state.local.addresses];
const index = tmp.indexOf(payload)
tmp.splice(index, 1)
state.local.addresses = []
state.local.addresses = [...tmp]
},
DELETE_CONTACT_LOCAL: (state, payload) => {
// Workaround because Vuex doesn't recognize changes otherwise
const tmp = [...state.local.contacts];
const index = tmp.indexOf(payload)
tmp.splice(index, 1)
state.local.contacts = []
state.local.contacts = [...tmp]
},
DELETE_SUMMARY_LOCAL: (state, payload) => {
// Workaround because Vuex doesn't recognize changes otherwise
const tmp = [...state.local.summaries];
const index = tmp.indexOf(payload)
tmp.splice(index, 1)
state.local.summaries = []
state.local.summaries = [...tmp]
},
DELETE_CONTRIBUTION_LOCAL: (state, payload) => {
// Workaround because Vuex doesn't recognize changes otherwise
const tmp = [...state.local.contributions];
const index = tmp.indexOf(payload)
tmp.splice(index, 1)
state.local.contributions = []
state.local.contributions = [...tmp]
},
}