first commit
This commit is contained in:
227
components/layout/full/vertical-header/ProfileDD.vue
Executable file
227
components/layout/full/vertical-header/ProfileDD.vue
Executable file
@@ -0,0 +1,227 @@
|
||||
<!-- components/layout/ProfileDD.vue -->
|
||||
<script setup lang="ts">
|
||||
import { MailIcon } from "vue-tabler-icons";
|
||||
import { profileDD } from "~/_mockApis/headerData";
|
||||
import { PerfectScrollbar } from "vue3-perfect-scrollbar";
|
||||
import { useUserInfo } from "~/composables/useUserInfo";
|
||||
import { computed } from "vue";
|
||||
|
||||
const userInfo = useUserInfo();
|
||||
|
||||
// Enhanced logout with proper error handling
|
||||
const logout = async () => {
|
||||
try {
|
||||
// Use the updated logout method from useUserInfo that handles Keycloak logout and session clearing
|
||||
await userInfo.logout({
|
||||
reason: "idle",
|
||||
confirmDialog: false // Show confirmation dialog
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Logout from profile failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// **TAMBAHAN: Full logout function dengan konfirmasi**
|
||||
const fullLogout = async () => {
|
||||
try {
|
||||
// Tampilkan konfirmasi sebelum full logout
|
||||
const confirmed = confirm(
|
||||
"Apakah Anda yakin ingin keluar dari semua sesi? Ini akan menghapus semua data lokal dan sesi Keycloak."
|
||||
);
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
console.log("Initiating full logout from ProfileDD...");
|
||||
|
||||
// Gunakan fullLogout dari useUserInfo composable
|
||||
await userInfo.fullLogout();
|
||||
} catch (error) {
|
||||
console.error("Full logout from profile failed:", error);
|
||||
|
||||
// Fallback jika fullLogout gagal
|
||||
try {
|
||||
console.log("Attempting fallback logout...");
|
||||
await userInfo.logout({
|
||||
reason: "manual",
|
||||
clearStorage: true
|
||||
});
|
||||
} catch (fallbackError) {
|
||||
console.error("Fallback logout also failed:", fallbackError);
|
||||
|
||||
// Last resort - force redirect
|
||||
if (process.client) {
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
window.location.href = "/auth/login?reason=force";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// **TAMBAHAN: Logout dengan konfirmasi untuk UX yang lebih baik**
|
||||
const logoutWithConfirmation = async () => {
|
||||
try {
|
||||
const confirmed = confirm("Apakah Anda yakin ingin keluar?");
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
await logout();
|
||||
} catch (error) {
|
||||
console.error("Logout with confirmation failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// Get user display info from session
|
||||
const getUserDisplayInfo = () => {
|
||||
if (!userInfo.user.value && !userInfo.data.value?.user)
|
||||
return {
|
||||
name: "Guest User",
|
||||
email: "guest@example.com",
|
||||
role: "Guest"
|
||||
};
|
||||
|
||||
const user = userInfo.user.value || userInfo.data.value?.user || {};
|
||||
return {
|
||||
name: user.name || user.given_name || user.preferred_username || "User",
|
||||
email: user.email || "No email",
|
||||
role: userInfo.userRoles.value[0] || "User"
|
||||
};
|
||||
};
|
||||
|
||||
const displayInfo = computed(() => getUserDisplayInfo());
|
||||
|
||||
// Computed properties for decodedToken and clientScopes
|
||||
// const decodedToken = computed(() => userInfo.decodedToken.value);
|
||||
// const clientScopes = computed(() => userInfo.clientScopes.value);
|
||||
|
||||
// **TAMBAHAN: Computed property untuk menampilkan status session**
|
||||
const sessionInfo = computed(() => {
|
||||
return {
|
||||
isAuthenticated: userInfo.isAuthenticated.value,
|
||||
sessionExpires: userInfo.sessionExpires.value,
|
||||
hasValidToken: !!userInfo.idToken.value
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-menu :close-on-content-click="false">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn class="custom-hover-primary" variant="text" v-bind="props" icon>
|
||||
<v-avatar size="35">
|
||||
<img
|
||||
src="~/assets/images/profile/user-1.jpg"
|
||||
width="35"
|
||||
alt="User Avatar"
|
||||
/>
|
||||
</v-avatar>
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
<v-sheet rounded="md" width="360" elevation="10">
|
||||
<div class="px-8 pt-6">
|
||||
<h6 class="text-h5 font-weight-medium">User Profile</h6>
|
||||
<div class="d-flex align-center mt-4 pb-6">
|
||||
<v-avatar size="80">
|
||||
<img src="~/assets/images/profile/user-1.jpg" width="80" />
|
||||
</v-avatar>
|
||||
<div class="ml-3">
|
||||
<h6 class="text-h6 mb-n1">{{ displayInfo.name }}</h6>
|
||||
<span class="text-subtitle-1 font-weight-regular textSecondary">
|
||||
{{ displayInfo.role }}
|
||||
</span>
|
||||
<div class="d-flex align-center mt-1">
|
||||
<MailIcon size="18" stroke-width="1.5" />
|
||||
<span
|
||||
class="text-subtitle-1 font-weight-regular textSecondary ml-2"
|
||||
>
|
||||
{{ displayInfo.email }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- **TAMBAHAN: Tampilkan status session** -->
|
||||
<div class="mt-2">
|
||||
<v-chip
|
||||
:color="sessionInfo.isAuthenticated ? 'success' : 'error'"
|
||||
size="small"
|
||||
variant="outlined"
|
||||
>
|
||||
{{ sessionInfo.isAuthenticated ? "Active" : "Inactive" }}
|
||||
</v-chip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<v-divider></v-divider>
|
||||
</div>
|
||||
|
||||
<PerfectScrollbar style="height: calc(100vh - 240px); max-height: 240px">
|
||||
<v-list class="py-0 theme-list" lines="two">
|
||||
<v-list-item
|
||||
v-for="item in profileDD"
|
||||
:key="item.title"
|
||||
class="py-4 px-8 custom-text-primary"
|
||||
:to="item.href"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<v-avatar
|
||||
size="48"
|
||||
color="lightprimary"
|
||||
class="mr-3"
|
||||
rounded="md"
|
||||
>
|
||||
<img
|
||||
:src="item.avatar"
|
||||
width="24"
|
||||
height="24"
|
||||
:alt="item.avatar"
|
||||
/>
|
||||
</v-avatar>
|
||||
</template>
|
||||
<div>
|
||||
<h6 class="text-subtitle-1 font-weight-bold mb-2 custom-title">
|
||||
{{ item.title }}
|
||||
</h6>
|
||||
</div>
|
||||
<p class="text-subtitle-1 font-weight-regular textSecondary">
|
||||
{{ item.subtitle }}
|
||||
</p>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</PerfectScrollbar>
|
||||
|
||||
<!-- **DIPERBAIKI: Logout buttons section dengan multiple options** -->
|
||||
<div class="pt-4 pb-6 px-8">
|
||||
<!-- Regular Logout Button -->
|
||||
<v-btn
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
block
|
||||
@click="logoutWithConfirmation"
|
||||
prepend-icon="mdi-logout"
|
||||
class="mb-2"
|
||||
>
|
||||
Logout
|
||||
</v-btn>
|
||||
|
||||
<!-- **TAMBAHAN: Full Logout Button** -->
|
||||
<v-btn
|
||||
color="error"
|
||||
variant="outlined"
|
||||
block
|
||||
@click="fullLogout"
|
||||
prepend-icon="mdi-logout-variant"
|
||||
class="mb-2"
|
||||
>
|
||||
Full Logout
|
||||
</v-btn>
|
||||
|
||||
<!-- **TAMBAHAN: Quick info text** -->
|
||||
<div class="text-center mt-2">
|
||||
<span class="text-caption textSecondary">
|
||||
Full logout akan menghapus semua sesi dan data lokal
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</v-sheet>
|
||||
</v-menu>
|
||||
</template>
|
||||
Reference in New Issue
Block a user