197 lines
5.7 KiB
Vue
197 lines
5.7 KiB
Vue
<template>
|
|
<header
|
|
class="py-1 flex items-center justify-between bg-white shadow-md shadow-gray-700 z-20"
|
|
@click.stop
|
|
>
|
|
<div class="flex items-center">
|
|
<v-app-bar-nav-icon @click.stop="toggleSidebar">
|
|
</v-app-bar-nav-icon>
|
|
|
|
<RouterLink to="/" class="hidden md:block">
|
|
<v-img
|
|
src="/medias/hutopy.png"
|
|
ref="popupButtonRef"
|
|
alt="Hutopy Logo"
|
|
class="mr-2 h-10 w-20"
|
|
></v-img>
|
|
</RouterLink>
|
|
|
|
<RouterLink to="/" class="block md:hidden">
|
|
<v-img
|
|
src="/images/hutopymedia/icons/logohutopy.png"
|
|
ref="popupButtonRef"
|
|
alt="Hutopy Logo"
|
|
class="mr-2 h-10 w-10"
|
|
></v-img>
|
|
</RouterLink>
|
|
</div>
|
|
|
|
<div class="flex items-center ml-auto space-x-4 search-container">
|
|
<template v-if="showSearch">
|
|
<v-text-field
|
|
density="compact"
|
|
rounded
|
|
variant="outlined"
|
|
v-model="searchQuery"
|
|
placeholder="Recherche"
|
|
hide-details
|
|
clearable
|
|
class="rounded-full w-32 md:w-64 lg:w-96 mx-2"
|
|
append-inner-icon="mdi-magnify"
|
|
@click.stop
|
|
@click:append-inner="onSearch"
|
|
@keyup.enter="onSearch"
|
|
>
|
|
</v-text-field>
|
|
</template>
|
|
<template v-else>
|
|
<v-icon class="mx-2 cursor-pointer" @click.stop="toggleSearch">mdi-magnify</v-icon>
|
|
</template>
|
|
|
|
<v-icon class="mx-2">mdi-bell-outline</v-icon>
|
|
|
|
<div class="text-center">
|
|
<v-menu open-on-hover>
|
|
<template v-slot:activator="{ props }">
|
|
<v-btn variant="plain" v-bind="props" class="d-flex align-center text-capital-none">
|
|
<span class="normal-case max-w-xs hidden md:block">
|
|
{{ currentUser.userName }}
|
|
</span>
|
|
<img
|
|
:src="currentUser.storedDataUrls.profilePictureUrl"
|
|
alt="Profile Image"
|
|
@error="handleProfilePictureError"
|
|
class="ml-2 rounded-full" style="width: 32px; height: 32px;">
|
|
</v-btn>
|
|
</template>
|
|
|
|
<v-list min-width="200px" class=" align-center mt-3 left-3">
|
|
|
|
<div v-if="currentUser.userName === 'Anonyme'">
|
|
<v-list-item class="nav-button">
|
|
<v-list-item-title>
|
|
<v-btn to="/login" class="w-100 " variant="plain">Connexion</v-btn>
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
</div>
|
|
|
|
<div v-if="currentUser.userName !== 'Anonyme'">
|
|
|
|
<v-list-item v-if="currentUser.creatorAlias !== null" class="nav-button">
|
|
<router-link :to="`/@${currentUser.creatorAlias}`">
|
|
<v-btn class="w-100 " variant="plain">@{{ currentUser.creatorAlias }}</v-btn>
|
|
</router-link>
|
|
</v-list-item>
|
|
|
|
<v-list-item class="nav-button">
|
|
<v-list-item-title>
|
|
<v-btn to="/profile" class="w-100 " variant="plain">Mon profil</v-btn>
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item class="nav-button">
|
|
<v-list-item-title>
|
|
<v-btn to="/wallet" class="w-100 " variant="plain"> Portefeuille</v-btn>
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item class="nav-button">
|
|
<v-list-item-title>
|
|
<v-btn @click="logout" to="/wallet" class="w-100 " variant="plain"> Déconnexion</v-btn>
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
</div>
|
|
</v-list>
|
|
</v-menu>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</header>
|
|
</template>
|
|
|
|
<script setup>
|
|
import {ref, onBeforeUnmount, onBeforeMount, watch, reactive} from "vue";
|
|
import {eventBus} from '@/eventBus.js';
|
|
import {useRouter} from 'vue-router';
|
|
import {useUserStore} from "@/stores/user.js";
|
|
import MyUserModel from "@/models/myUserModel.js";
|
|
|
|
const router = useRouter();
|
|
const searchQuery = ref("");
|
|
const showSearch = ref(false);
|
|
let currentUser = reactive(MyUserModel.getDefaultUser());
|
|
const userStore = useUserStore();
|
|
const backupProfilePictureUrl = "/images/usersmedia/anonyme/profilepictures/profileAnonymeSquare.png"
|
|
|
|
const handleProfilePictureError = (event) => {
|
|
event.target.src = backupProfilePictureUrl;
|
|
}
|
|
|
|
const toggleSidebar = () => {
|
|
eventBus.value.toggleSidebar();
|
|
};
|
|
|
|
const onSearch = () => {
|
|
const query = searchQuery.value.trim();
|
|
if (!query) {
|
|
router.push("/browse");
|
|
} else {
|
|
const words = query.split(" ");
|
|
if (words.length === 1) {
|
|
router.push(`/@${words[0]}`);
|
|
} else {
|
|
router.push({name: "browse", query: {q: query}});
|
|
}
|
|
}
|
|
};
|
|
|
|
const toggleSearch = () => {
|
|
showSearch.value = !showSearch.value;
|
|
};
|
|
|
|
const handleClickOutside = (event) => {
|
|
if (!event.target.closest('.search-container')) {
|
|
showSearch.value = false;
|
|
}
|
|
};
|
|
|
|
const navigateToMessages = () => {
|
|
router.push('/messages');
|
|
};
|
|
|
|
const logout = () => {
|
|
localStorage.removeItem('jwt');
|
|
window.location.reload();
|
|
};
|
|
|
|
onBeforeMount(() => {
|
|
currentUser = userStore.getCurrentUser();
|
|
document.addEventListener('click', handleClickOutside);
|
|
});
|
|
|
|
// Watch the user state to get it again if needed.
|
|
watch(
|
|
() => userStore.hasChanged,
|
|
() => {
|
|
currentUser = userStore.getCurrentUser();
|
|
const timestamp = new Date().getTime();
|
|
currentUser.storedDataUrls.profilePictureUrl = `${currentUser.storedDataUrls.profilePictureUrl}?t=${timestamp}`;
|
|
}
|
|
);
|
|
|
|
onBeforeUnmount(() => {
|
|
document.removeEventListener('click', handleClickOutside);
|
|
});
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
.search-container {
|
|
position: relative;
|
|
}
|
|
|
|
.nav-button:hover {
|
|
@apply bg-[#903175] text-gray-200;
|
|
}
|
|
|
|
</style>
|