Files
social-media/src/App.vue
2024-06-30 15:47:43 -04:00

112 lines
2.9 KiB
Vue

<template>
<v-app v-if="isUserLoaded">
<div class="m-0 flex flex-column h-screen">
<Header @toggle-sidebar="toggleSidebar" class="fixed w-full z-50 top-0 p-2"></Header>
<div class="flex flex-row relative">
<div
@mouseenter="openSidebar"
class="fixed h-full w-2 z-20"
style="background: transparent;"
></div>
<transition name="slide-fade">
<div v-show="!hideSideBar"
@mouseleave="startCloseSidebarTimer"
@mouseenter="clearCloseSidebarTimer"
class=" fixed h-full min-w-60 border-r-2 bg-white z-30 transition-transform duration-700">
<SideBar></SideBar>
</div>
</transition>
<div class="flex flex-col w-full md:ml-1 mt-16" style="background-color: #f4f4f4">
<RouterView></RouterView>
<Footer></Footer>
</div>
</div>
</div>
</v-app>
</template>
<script async setup>
import Header from "@/views/main/Header.vue";
import Footer from "@/views/main/Footer.vue";
import SideBar from "@/views/main/SideBar.vue";
import {ref, onMounted, onUnmounted, onBeforeMount} from 'vue';
import {eventBus} from '@/eventBus.js';
import {useUserStore} from "@/stores/user.js";
import {useClient} from "@/plugins/api.js";
const hideSideBar = ref(false);
const isUserLoaded = ref(false);
const showPopup = ref(false);
const popup = ref(null);
const popupButton = ref(null);
let closeSidebarTimer = null;
let client = useClient();
let userStore = useUserStore();
onBeforeMount(async () => {
await userStore.setCurrentUser(client);
isUserLoaded.value = true;
});
const toggleSidebar = () => {
hideSideBar.value = !hideSideBar.value;
};
const openSidebar = () => {
clearCloseSidebarTimer();
hideSideBar.value = false;
};
const startCloseSidebarTimer = () => {
closeSidebarTimer = setTimeout(() => {
hideSideBar.value = true;
}, 500);
};
const clearCloseSidebarTimer = () => {
clearTimeout(closeSidebarTimer);
};
const handleClickOutside = (event) => {
if (
popup.value &&
!popup.value.contains(event.target) &&
!popupButton.value.contains(event.target) &&
!event.target.closest('.bg-purple')
) {
showPopup.value = false;
}
if (
!event.target.closest('.w-48') &&
!event.target.closest('.v-app-bar-nav-icon')
) {
hideSideBar.value = true;
}
};
onMounted(() => {
document.addEventListener('click', handleClickOutside);
eventBus.value.toggleSidebar = toggleSidebar;
});
onUnmounted(() => {
document.removeEventListener('click', handleClickOutside);
eventBus.value.toggleSidebar = null;
});
</script>
<style scoped>
/* Do not remove. Used for animation */
.slide-fade-enter-active, .slide-fade-leave-active {
transition: transform 0.7s ease, opacity 0.7s ease;
}
.slide-fade-enter, .slide-fade-leave-to {
transform: translateX(-100%);
opacity: 0;
}
</style>