247 lines
5.2 KiB
Svelte
247 lines
5.2 KiB
Svelte
<script>
|
|
import { createEventDispatcher, onMount, onDestroy } from "svelte";
|
|
import { navigate } from "svelte-routing";
|
|
import {
|
|
activePlaceholder,
|
|
activeSearchTerm,
|
|
updateSearchTerm
|
|
} from "../stores/searchStore.js";
|
|
import { avatarUrlStore } from "../stores/avatarStore.js";
|
|
|
|
import { clearTokens } from "../utils/api.js";
|
|
|
|
const dispatch = createEventDispatcher();
|
|
export let placeholder = "";
|
|
// Avatar opsiyonel; yoksa placeholder ikon gösterilir
|
|
export let avatarUrl = null;
|
|
let showAvatarMenu = false;
|
|
let avatarWrap;
|
|
$: resolvedAvatar = avatarUrl || $avatarUrlStore;
|
|
|
|
const onToggle = () => dispatch("toggleMenu");
|
|
|
|
function handleInput(event) {
|
|
updateSearchTerm(event.target.value);
|
|
}
|
|
|
|
function toggleAvatarMenu() {
|
|
showAvatarMenu = !showAvatarMenu;
|
|
}
|
|
|
|
function goProfile() {
|
|
showAvatarMenu = false;
|
|
navigate("/profile");
|
|
}
|
|
|
|
function goSettings() {
|
|
showAvatarMenu = false;
|
|
navigate("/settings");
|
|
}
|
|
|
|
function logout() {
|
|
clearTokens();
|
|
showAvatarMenu = false;
|
|
window.location.replace("/login");
|
|
}
|
|
|
|
function handleDocumentClick(event) {
|
|
if (!showAvatarMenu) return;
|
|
if (avatarWrap && !avatarWrap.contains(event.target)) {
|
|
showAvatarMenu = false;
|
|
}
|
|
}
|
|
|
|
onMount(() => {
|
|
document.addEventListener("click", handleDocumentClick);
|
|
});
|
|
|
|
onDestroy(() => {
|
|
document.removeEventListener("click", handleDocumentClick);
|
|
});
|
|
|
|
$: resolvedPlaceholder = placeholder || $activePlaceholder;
|
|
</script>
|
|
|
|
<div class="topbar">
|
|
<!-- 🔹 Hamburger butonu sadece küçük ekranlarda gösterilir -->
|
|
<button
|
|
class="menu-toggle"
|
|
on:click={onToggle}
|
|
aria-label="Toggle menu"
|
|
>
|
|
<i class="fa-solid fa-bars"></i>
|
|
</button>
|
|
|
|
<div class="search">
|
|
<i class="fa-solid fa-magnifying-glass"></i>
|
|
<input
|
|
type="search"
|
|
placeholder={resolvedPlaceholder}
|
|
value={$activeSearchTerm}
|
|
on:input={handleInput}
|
|
/>
|
|
</div>
|
|
|
|
<div class="avatar-wrap" bind:this={avatarWrap}>
|
|
<button class="avatar" type="button" aria-label="Profil" on:click={toggleAvatarMenu}>
|
|
{#if resolvedAvatar}
|
|
<img src={resolvedAvatar} alt="Avatar" loading="lazy" on:error={() => (resolvedAvatar = null)} />
|
|
{:else}
|
|
<div class="placeholder">
|
|
<i class="fa-regular fa-user"></i>
|
|
</div>
|
|
{/if}
|
|
</button>
|
|
|
|
{#if showAvatarMenu}
|
|
<div class="avatar-menu">
|
|
<button type="button" on:click={goProfile}>
|
|
<i class="fa-solid fa-user"></i>
|
|
Profile
|
|
</button>
|
|
<button type="button" on:click={goSettings}>
|
|
<i class="fa-solid fa-gear"></i>
|
|
Settings
|
|
</button>
|
|
<button type="button" class="logout" on:click={logout}>
|
|
<i class="fa-solid fa-right-from-bracket"></i>
|
|
Logout
|
|
</button>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.topbar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
padding: 12px 16px;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.search {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
background: #f8f8f8;
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
padding: 8px 12px;
|
|
}
|
|
|
|
.search input {
|
|
border: none;
|
|
outline: none;
|
|
background: transparent;
|
|
flex: 1;
|
|
}
|
|
|
|
/* 🟡 Hamburger sadece küçük ekranlarda görünsün */
|
|
.menu-toggle {
|
|
display: none;
|
|
background: none;
|
|
border: none;
|
|
font-size: 20px;
|
|
color: #333;
|
|
cursor: pointer;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.menu-toggle {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 36px;
|
|
height: 36px;
|
|
}
|
|
}
|
|
|
|
.avatar {
|
|
border: 0.5px solid var(--border, #dcdcdc);
|
|
background: #f7f8fa;
|
|
border-radius: 10px;
|
|
width: 42px;
|
|
height: 42px;
|
|
padding: 0;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.avatar img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.avatar .placeholder {
|
|
width: 100%;
|
|
height: 100%;
|
|
background: #eef1f6;
|
|
border: 0.5px solid var(--border, #dcdcdc);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 10px;
|
|
color: #2c3e50;
|
|
font-size: 18px;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.avatar {
|
|
width: 38px;
|
|
height: 38px;
|
|
}
|
|
}
|
|
|
|
.avatar-wrap {
|
|
position: relative;
|
|
}
|
|
|
|
.avatar-menu {
|
|
position: absolute;
|
|
right: 0;
|
|
top: calc(100% + 8px);
|
|
background: #fff;
|
|
border: 1px solid var(--border);
|
|
border-radius: 10px;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12);
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-width: 170px;
|
|
overflow: hidden;
|
|
z-index: 20;
|
|
}
|
|
|
|
.avatar-menu button {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 10px 12px;
|
|
background: #fff;
|
|
border: none;
|
|
text-align: left;
|
|
cursor: pointer;
|
|
color: #1c2440;
|
|
}
|
|
|
|
.avatar-menu button:hover {
|
|
background: #f3f4f7;
|
|
}
|
|
|
|
.avatar-menu i {
|
|
width: 18px;
|
|
text-align: center;
|
|
}
|
|
|
|
.avatar-menu .logout {
|
|
color: #c0392b;
|
|
}
|
|
</style>
|