feat: frontend fase 2 sessies 1-3
- Member management pagina + invite flow - Persons module met filters, KPI tiles, detail panel - Event horizontale tabs navigatie (EventTabsNav component) - Route conflict opgelost - OrganisationSwitcher verbeterd (collapsed staat WIP)
This commit is contained in:
@@ -1,64 +1,111 @@
|
||||
<script setup lang="ts">
|
||||
import { layoutConfig } from '@layouts'
|
||||
import { useLayoutConfigStore } from '@layouts/stores/config'
|
||||
import { useAuthStore } from '@/stores/useAuthStore'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const configStore = useLayoutConfigStore()
|
||||
const hideTitleAndBadge = configStore.isVerticalNavMini()
|
||||
|
||||
const hasMultipleOrgs = computed(() => authStore.organisations.length > 1)
|
||||
const currentOrgName = computed(() => authStore.currentOrganisation?.name ?? 'Geen organisatie')
|
||||
const organisations = computed(() => authStore.organisations)
|
||||
const activeOrg = computed(() => authStore.currentOrganisation)
|
||||
const hasMultiple = computed(() => organisations.value.length > 1)
|
||||
|
||||
const activeOrgName = computed(() => {
|
||||
const name = activeOrg.value?.name ?? 'Geen organisatie'
|
||||
return name.length > 18 ? `${name.slice(0, 18)}…` : name
|
||||
})
|
||||
|
||||
const isMenuOpen = ref(false)
|
||||
|
||||
const roleColor = (role: string) => ({
|
||||
org_admin: 'primary',
|
||||
org_member: 'info',
|
||||
event_manager: 'success',
|
||||
staff_coordinator: 'warning',
|
||||
volunteer_coordinator: 'secondary',
|
||||
}[role] ?? 'default')
|
||||
|
||||
function toggleMenu() {
|
||||
if (hasMultiple.value)
|
||||
isMenuOpen.value = !isMenuOpen.value
|
||||
}
|
||||
|
||||
function selectOrg(id: string) {
|
||||
authStore.setActiveOrganisation(id)
|
||||
isMenuOpen.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="organisation-switcher mx-4 mb-2">
|
||||
<!-- Single org: just show the name -->
|
||||
<div
|
||||
v-if="!hasMultipleOrgs"
|
||||
class="d-flex align-center gap-x-2 pa-2"
|
||||
<li
|
||||
class="nav-link"
|
||||
style="margin-block-end: 8px;"
|
||||
>
|
||||
<VMenu
|
||||
v-model="isMenuOpen"
|
||||
:location="hideTitleAndBadge ? 'end' : 'bottom'"
|
||||
:offset="hideTitleAndBadge ? 8 : 0"
|
||||
:width="hideTitleAndBadge ? undefined : 260"
|
||||
:min-width="hideTitleAndBadge ? 220 : undefined"
|
||||
:disabled="!hasMultiple"
|
||||
>
|
||||
<VIcon
|
||||
icon="tabler-building"
|
||||
size="20"
|
||||
color="primary"
|
||||
/>
|
||||
<span class="text-body-2 font-weight-medium text-truncate">
|
||||
{{ currentOrgName }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Multiple orgs: dropdown -->
|
||||
<VBtn
|
||||
v-else
|
||||
variant="tonal"
|
||||
color="primary"
|
||||
block
|
||||
class="text-none justify-start"
|
||||
prepend-icon="tabler-building"
|
||||
>
|
||||
<span class="text-truncate">{{ currentOrgName }}</span>
|
||||
|
||||
<VMenu
|
||||
activator="parent"
|
||||
width="250"
|
||||
location="bottom start"
|
||||
>
|
||||
<VList density="compact">
|
||||
<VListItem
|
||||
v-for="org in authStore.organisations"
|
||||
:key="org.id"
|
||||
:active="org.id === authStore.currentOrganisation?.id"
|
||||
@click="authStore.setActiveOrganisation(org.id)"
|
||||
>
|
||||
<VListItemTitle>{{ org.name }}</VListItemTitle>
|
||||
<template #append>
|
||||
<VChip
|
||||
size="x-small"
|
||||
variant="text"
|
||||
>
|
||||
{{ org.role }}
|
||||
</VChip>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
</VBtn>
|
||||
</div>
|
||||
<template #activator="{ props: menuProps }">
|
||||
<a
|
||||
v-bind="hasMultiple ? menuProps : undefined"
|
||||
:class="{ 'cursor-pointer': hasMultiple }"
|
||||
>
|
||||
<Component
|
||||
:is="layoutConfig.app.iconRenderer || 'div'"
|
||||
v-bind="{ icon: 'tabler-building' }"
|
||||
class="nav-item-icon"
|
||||
/>
|
||||
<TransitionGroup name="transition-slide-x">
|
||||
<span
|
||||
v-show="!hideTitleAndBadge"
|
||||
key="title"
|
||||
class="nav-item-title"
|
||||
>
|
||||
{{ activeOrgName }}
|
||||
</span>
|
||||
<Component
|
||||
v-if="hasMultiple"
|
||||
v-show="!hideTitleAndBadge"
|
||||
:is="layoutConfig.app.iconRenderer || 'div'"
|
||||
v-bind="{ icon: 'tabler-chevron-down' }"
|
||||
key="chevron"
|
||||
class="nav-item-badge"
|
||||
:style="{
|
||||
transition: 'transform 0.2s ease',
|
||||
transform: isMenuOpen ? 'rotate(180deg)' : 'rotate(0deg)',
|
||||
'font-size': '18px',
|
||||
'margin-inline-start': 'auto',
|
||||
}"
|
||||
/>
|
||||
</TransitionGroup>
|
||||
</a>
|
||||
</template>
|
||||
<VList density="compact">
|
||||
<VListItem
|
||||
v-for="org in organisations"
|
||||
:key="org.id"
|
||||
:active="org.id === activeOrg?.id"
|
||||
active-color="primary"
|
||||
@click="selectOrg(org.id)"
|
||||
>
|
||||
<VListItemTitle>{{ org.name }}</VListItemTitle>
|
||||
<template #append>
|
||||
<VChip
|
||||
:color="roleColor(org.role)"
|
||||
size="x-small"
|
||||
variant="tonal"
|
||||
label
|
||||
>
|
||||
{{ org.role }}
|
||||
</VChip>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user