74 lines
2.6 KiB
Vue
74 lines
2.6 KiB
Vue
<script setup lang="ts">
|
|
import { Lucide } from '@/components/ui/lucide'
|
|
import { useAuthStore } from '@/stores/auth'
|
|
|
|
interface Props {
|
|
class?: string
|
|
innerClass?: any
|
|
avatarClass?: string
|
|
textClass?: string
|
|
}
|
|
|
|
const props = defineProps<Props>()
|
|
const open = defineModel<boolean>('open', { default: false })
|
|
const authStore = useAuthStore()
|
|
|
|
function handleClick(event: MouseEvent) {
|
|
if (!window.matchMedia('(max-width: 1279px)').matches) return
|
|
event.stopPropagation()
|
|
open.value = !open.value
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div :class="['side-menu__account group/profile transition-[width]', props.class]">
|
|
<div :class="['flex cursor-pointer items-center transition', props.innerClass]" @click="handleClick">
|
|
<div :class="[
|
|
'relative flex-none overflow-hidden rounded-full border-4',
|
|
props.avatarClass ?? 'h-10 w-10 border-background/20 dark:border-foreground/20',
|
|
]">
|
|
<img v-if="authStore.userImageUrl" class="absolute top-0 h-full w-full object-cover"
|
|
:src="authStore.userImageUrl" :alt="authStore.userName" />
|
|
<div v-else
|
|
class="bg-primary text-primary-foreground absolute inset-0 flex items-center justify-center text-sm font-medium">
|
|
{{ authStore.userName }}
|
|
</div>
|
|
</div>
|
|
<div class="ms-3 flex w-full items-center gap-3 overflow-hidden transition-opacity
|
|
group-[.side-menu--collapsed]:group-hover:opacity-100
|
|
xl:group-[.side-menu--collapsed]:opacity-0">
|
|
<div :class="['flex-1 min-w-0', props.textClass]">
|
|
<!-- Name + Active Role -->
|
|
<div class="flex items-center gap-2">
|
|
<div class="truncate font-semibold text-sm">
|
|
{{ authStore.userName }}
|
|
</div>
|
|
|
|
<span class="shrink-0 rounded-full bg-green-500 px-2 py-0.5 text-[10px] font-medium text-white">
|
|
{{ authStore.userActiveRole }}
|
|
</span>
|
|
</div>
|
|
|
|
<!-- Position -->
|
|
<div class="mt-0.5 truncate text-xs text-slate-500">
|
|
<span class="font-medium text-slate-600">Jawatan:</span>
|
|
{{ authStore.userPosition }}
|
|
</div>
|
|
|
|
<!-- Roles Summary -->
|
|
<div class="mt-2 flex items-center gap-1 text-[11px] text-slate-500">
|
|
<Lucide icon="Shield" class="h-3 w-3" />
|
|
<span class="truncate">
|
|
{{authStore.roles.map(role => role.name).join(' • ')}}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<Lucide icon="ChevronRight"
|
|
class="h-4 w-4 flex-none text-slate-400 transition-transform group-hover:translate-x-1" />
|
|
</div>
|
|
</div>
|
|
<slot />
|
|
</div>
|
|
</template>
|