Initial Version

This commit is contained in:
root
2025-12-21 10:09:54 -05:00
commit 4ae6befc7b
422 changed files with 47225 additions and 0 deletions
+110
View File
@@ -0,0 +1,110 @@
<script setup lang="ts">
import { computed } from 'vue';
import { useTheme } from 'vuetify';
import { useUserStore } from '@KTXC/stores/userStore';
import { useIntegrationStore } from '@KTXC/stores/integrationStore';
import { useLayoutStore } from '@KTXC/stores/layoutStore';
import { useRouter } from 'vue-router';
import defaultAvatar from '@KTXC/assets/images/users/avatar-1.png';
const theme = useTheme();
const router = useRouter();
const userStore = useUserStore();
const integrationStore = useIntegrationStore();
const layoutStore = useLayoutStore();
const userAuth = computed(() => userStore.auth);
const profileMenuItems = computed(() => integrationStore.getItems('profile_menu'));
const userAvatar = computed(() => userStore.getProfileField('avatar') || defaultAvatar);
const userName = computed(() => {
const given = userStore.getProfileField('name_given');
const family = userStore.getProfileField('name_family');
if (given && family) return `${given} ${family}`;
return userAuth.value?.label || 'User';
});
const userEmail = computed(() => userStore.getProfileField('email') || '');
// Theme toggle
const isDarkMode = computed(() => theme.global.name.value === 'dark');
const toggleTheme = () => {
const newTheme = theme.global.name.value === 'light' ? 'dark' : 'light';
theme.global.name.value = newTheme;
layoutStore.setTheme(newTheme);
};
// Navigate to settings
const goToSettings = () => {
layoutStore.setMenuMode('settings');
// Navigate to first settings item or a default settings route
router.push('/modules'); // TODO: Make this dynamic based on first settings menu item
};
</script>
<template>
<!-- ---------------------------------------------- -->
<!-- Profile Dropdown -->
<!-- ---------------------------------------------- -->
<div>
<!-- User Info Header -->
<div class="d-flex align-center pa-5 pb-4">
<v-avatar size="40" class="mr-3">
<v-img :src="userAvatar" :alt="userName" cover />
</v-avatar>
<div class="flex-grow-1">
<h6 class="text-h6 mb-0 font-weight-medium">
{{ userName }}
</h6>
<p class="text-caption mb-0 text-medium-emphasis">{{ userEmail }}</p>
</div>
</div>
<v-divider />
<perfect-scrollbar style="max-height: 280px">
<v-list class="py-0" aria-label="profile menu" aria-busy="true">
<!-- Dynamic Profile Menu Items (from modules) -->
<v-list-item
v-for="item in profileMenuItems"
:key="item.id"
:to="item.toType === 'external' ? undefined : item.to"
:href="item.toType === 'external' ? item.to : undefined"
:target="item.toType === 'external' ? '_blank' : undefined"
color="primary"
rounded="0"
>
<template v-slot:prepend>
<v-icon v-if="item.icon">{{ item.icon }}</v-icon>
</template>
<v-list-item-title class="text-h6">{{ item.label }}</v-list-item-title>
</v-list-item>
<v-divider v-if="profileMenuItems.length" class="my-2" />
<!-- Theme Toggle -->
<v-list-item @click="toggleTheme" color="primary" rounded="0">
<template v-slot:prepend>
<v-icon>{{ isDarkMode ? 'mdi-weather-sunny' : 'mdi-weather-night' }}</v-icon>
</template>
<v-list-item-title class="text-h6">{{ isDarkMode ? 'Light Mode' : 'Dark Mode' }}</v-list-item-title>
</v-list-item>
<!-- Go to Settings -->
<v-list-item @click="goToSettings" color="primary" rounded="0">
<template v-slot:prepend>
<v-icon>mdi-cog-outline</v-icon>
</template>
<v-list-item-title class="text-h6">Settings</v-list-item-title>
</v-list-item>
<v-divider class="my-2" />
<!-- Logout -->
<v-list-item @click="userStore.logout()" color="secondary" rounded="0">
<template v-slot:prepend>
<v-icon>mdi-logout</v-icon>
</template>
<v-list-item-title class="text-h6">Logout</v-list-item-title>
</v-list-item>
</v-list>
</perfect-scrollbar>
</div>
</template>