Merge branch 'Antrean-Code' of https://git.rssa.top/arie.bagus.2905/Web-Antrean into Antrean-Code
This commit is contained in:
No files matched your search
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<v-menu
|
||||
v-model="menu"
|
||||
:close-on-content-click="false"
|
||||
location="top end"
|
||||
offset="8"
|
||||
origin="bottom right"
|
||||
transition="slide-y-transition"
|
||||
>
|
||||
<template v-slot:activator="{ props: menuProps }">
|
||||
<div
|
||||
v-bind="menuProps"
|
||||
class="d-flex align-center cursor-pointer pa-2 rounded-lg hover-bg"
|
||||
>
|
||||
<v-avatar size="40">
|
||||
<v-img
|
||||
:src="user.picture"
|
||||
:alt="`${user.name} Profile`"
|
||||
></v-img>
|
||||
<v-badge
|
||||
dot
|
||||
color="orange"
|
||||
location="bottom right"
|
||||
offset-x="2"
|
||||
offset-y="2"
|
||||
></v-badge>
|
||||
</v-avatar>
|
||||
|
||||
<div v-show="!rail" class="ml-3 flex-grow-1">
|
||||
<div class="text-subtitle-2 font-weight-bold">
|
||||
{{ user.name }}
|
||||
</div>
|
||||
<div class="text-caption text-grey">
|
||||
{{ user.email }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<v-btn v-show="!rail" icon size="small" variant="text">
|
||||
<v-icon size="20">mdi-dots-vertical</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<v-card width="300" elevation="8" rounded="lg">
|
||||
<v-card-text class="pa-4">
|
||||
<div class="d-flex align-center mb-4">
|
||||
<v-avatar size="48">
|
||||
<v-img :src="user.picture"></v-img>
|
||||
</v-avatar>
|
||||
<div class="ml-3">
|
||||
<div class="text-subtitle-1 font-weight-bold">
|
||||
{{ user.name }}
|
||||
</div>
|
||||
<div class="text-caption text-grey">
|
||||
{{ user.email }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<v-list density="compact" class="pa-0">
|
||||
<v-list-item
|
||||
prepend-icon="mdi-cog-outline"
|
||||
class="px-2 rounded-lg"
|
||||
link
|
||||
@click="handleAction('setting')"
|
||||
>
|
||||
<v-list-item-title class="text-body-2">Setting</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item
|
||||
prepend-icon="mdi-help-circle-outline"
|
||||
class="px-2 rounded-lg"
|
||||
link
|
||||
@click="handleAction('help')"
|
||||
>
|
||||
<v-list-item-title class="text-body-2">Bantuan</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-divider class="my-2"></v-divider>
|
||||
|
||||
<v-list-item
|
||||
prepend-icon="mdi-logout"
|
||||
class="px-2 rounded-lg text-red"
|
||||
link
|
||||
@click="signOut"
|
||||
:disabled="isLoggingOut"
|
||||
>
|
||||
<v-list-item-title class="text-body-2">
|
||||
{{ isLoggingOut ? 'Log out...' : 'Log out' }}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
<div class="text-caption text-grey mt-3 text-center">
|
||||
v2.5.18 · Terms & Conditions
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-menu>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
// --- PROPS & EMITS ---
|
||||
const props = defineProps({
|
||||
user: {
|
||||
type: Object,
|
||||
// Diubah menjadi required: false dengan default yang aman
|
||||
required: false,
|
||||
default: () => ({
|
||||
name: 'Guest',
|
||||
email: '[email protected]',
|
||||
picture: 'https://i.pravatar.cc/150?img=33'
|
||||
})
|
||||
},
|
||||
rail: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
});
|
||||
const emit = defineEmits(['logout']); // Hanya emit logout
|
||||
|
||||
// --- STATE ---
|
||||
const menu = ref(false);
|
||||
const isLoggingOut = ref(false);
|
||||
|
||||
// --- METHODS ---
|
||||
const signOut = () => {
|
||||
if (isLoggingOut.value) return;
|
||||
isLoggingOut.value = true;
|
||||
menu.value = false;
|
||||
|
||||
// Memicu event untuk ditangani oleh komponen induk (SideBar)
|
||||
emit('logout');
|
||||
// Biarkan parent yang mengurus redirect/state global
|
||||
setTimeout(() => isLoggingOut.value = false, 1000);
|
||||
};
|
||||
|
||||
const handleAction = (action) => {
|
||||
console.log(`[PopupSidebar] Action: ${action} triggered.`);
|
||||
// TODO: Tambahkan logika navigasi/fungsi di sini, misal: router.push('/settings')
|
||||
menu.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Tambahkan kembali style yang relevan untuk aktivator di sini */
|
||||
.hover-bg:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
.text-red {
|
||||
color: rgb(244, 67, 54) !important;
|
||||
}
|
||||
</style>
|
||||
+80
-40
@@ -4,8 +4,7 @@
|
||||
:rail="rail"
|
||||
permanent
|
||||
app
|
||||
class="bg-white"
|
||||
@update:model-value="emit('update:drawer', $event)"
|
||||
class="bg-white d-flex flex-column" @update:model-value="emit('update:drawer', $event)"
|
||||
|
||||
@mouseenter="handleMouseEnter"
|
||||
@mouseleave="handleMouseLeave"
|
||||
@@ -23,6 +22,7 @@
|
||||
</v-list-item>
|
||||
<v-divider></v-divider>
|
||||
|
||||
<<<<<<< HEAD
|
||||
<v-list density="compact" nav class="mt-2" v-model:opened="openedGroups">
|
||||
<template v-for="item in items" :key="item.name">
|
||||
|
||||
@@ -40,53 +40,74 @@
|
||||
active-class="bg-orange-lighten-5 text-orange-darken-2 font-weight-bold"
|
||||
></v-list-item>
|
||||
</template>
|
||||
=======
|
||||
<v-list
|
||||
density="compact"
|
||||
nav
|
||||
class="mt-2 flex-grow-1" v-model:opened="openedGroups"
|
||||
>
|
||||
<template v-for="item in items" :key="item.name">
|
||||
<v-list-group
|
||||
v-if="item.children"
|
||||
:value="item.name"
|
||||
:disabled="rail"
|
||||
>
|
||||
<template v-slot:activator="{ props: groupProps }">
|
||||
<v-list-item
|
||||
v-bind="groupProps"
|
||||
:prepend-icon="item.icon"
|
||||
:title="item.name"
|
||||
color="orange-darken-2"
|
||||
active-class="bg-orange-lighten-5 text-orange-darken-2 font-weight-bold"
|
||||
></v-list-item>
|
||||
</template>
|
||||
>>>>>>> d7f3240a8226d36d66c5dc319c7a665539d5d8e3
|
||||
|
||||
<v-list-item
|
||||
v-for="child in item.children"
|
||||
:key="child.name"
|
||||
:to="child.path"
|
||||
:title="child.name"
|
||||
:prepend-icon="child.icon"
|
||||
link
|
||||
class="pl-8"
|
||||
color="orange-darken-2"
|
||||
active-class="bg-orange-lighten-5 text-orange-darken-2 font-weight-bold"
|
||||
></v-list-item>
|
||||
</v-list-group>
|
||||
<v-list-item
|
||||
v-for="child in item.children"
|
||||
:key="child.name"
|
||||
:to="child.path"
|
||||
:title="child.name"
|
||||
:prepend-icon="child.icon"
|
||||
link
|
||||
class="pl-8"
|
||||
color="orange-darken-2"
|
||||
active-class="bg-orange-lighten-5 text-orange-darken-2 font-weight-bold"
|
||||
></v-list-item>
|
||||
</v-list-group>
|
||||
|
||||
<v-tooltip
|
||||
v-else
|
||||
:disabled="!rail"
|
||||
open-on-hover
|
||||
location="end"
|
||||
:text="item.name"
|
||||
>
|
||||
<template #activator="{ props: tooltipProps }">
|
||||
<v-list-item
|
||||
v-bind="tooltipProps"
|
||||
:prepend-icon="item.icon"
|
||||
:title="item.name"
|
||||
:to="item.path"
|
||||
link
|
||||
color="orange-darken-2"
|
||||
active-class="bg-orange-lighten-5 text-orange-darken-2 font-weight-bold"
|
||||
></v-list-item>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</template>
|
||||
<v-tooltip
|
||||
v-else
|
||||
:disabled="!rail"
|
||||
open-on-hover
|
||||
location="end"
|
||||
:text="item.name"
|
||||
>
|
||||
<template #activator="{ props: tooltipProps }">
|
||||
<v-list-item
|
||||
v-bind="tooltipProps"
|
||||
:prepend-icon="item.icon"
|
||||
:title="item.name"
|
||||
:to="item.path"
|
||||
link
|
||||
color="orange-darken-2"
|
||||
active-class="bg-orange-lighten-5 text-orange-darken-2 font-weight-bold"
|
||||
></v-list-item>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</template>
|
||||
</v-list>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-list v-if="user" nav density="compact" class="pa-2">
|
||||
|
||||
<v-list v-if="user" nav density="compact" class="pa-2 flex-shrink-0">
|
||||
<ProfilePopup
|
||||
:user="user"
|
||||
@logout="handleLogout"
|
||||
:rail="rail"
|
||||
/>
|
||||
</v-list>
|
||||
<v-list v-else nav density="compact">
|
||||
<v-list v-else nav density="compact" class="flex-shrink-0">
|
||||
<v-list-item
|
||||
@click="redirectToLogin"
|
||||
prepend-icon="mdi-login"
|
||||
@@ -98,10 +119,14 @@
|
||||
|
||||
</v-navigation-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<<<<<<< HEAD
|
||||
import { defineProps, defineEmits, onMounted, ref, watch } from 'vue';
|
||||
import { navigateTo, useRoute } from '#app';
|
||||
=======
|
||||
import { defineProps, defineEmits, onMounted, ref, watch } from 'vue';
|
||||
import { navigateTo } from '#app';
|
||||
>>>>>>> d7f3240a8226d36d66c5dc319c7a665539d5d8e3
|
||||
import ProfilePopup from './ProfilePopup.vue';
|
||||
import { useAuth } from '~/composables/useAuth'; // Ensure this path is correct
|
||||
|
||||
@@ -133,14 +158,25 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['update:drawer', 'toggle-rail']);
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
|
||||
>>>>>>> d7f3240a8226d36d66c5dc319c7a665539d5d8e3
|
||||
const openedGroups = ref<string[]>([]);
|
||||
const isHovering = ref(false);
|
||||
|
||||
<<<<<<< HEAD
|
||||
// --- WATCHERS FOR DROPDOWN AND HIGHLIGHTING ---
|
||||
|
||||
// 1. WATCHER: Close dropdowns when sidebar collapses (rail = true)
|
||||
watch(() => props.rail, (newRailState) => {
|
||||
if (newRailState === true) {
|
||||
=======
|
||||
|
||||
watch(() => props.rail, (newRailState) => {
|
||||
if (newRailState === true) {
|
||||
|
||||
>>>>>>> d7f3240a8226d36d66c5dc319c7a665539d5d8e3
|
||||
openedGroups.value = [];
|
||||
}
|
||||
});
|
||||
@@ -165,8 +201,12 @@ watch(() => route.path, (newPath) => {
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
const isHovering = ref(false);
|
||||
>>>>>>> d7f3240a8226d36d66c5dc319c7a665539d5d8e3
|
||||
|
||||
|
||||
// --- HOVER LOGIC for Rail Expansion ---
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
if (props.rail) {
|
||||
|
||||
Reference in New Issue
Block a user