228 lines
5.3 KiB
Vue
228 lines
5.3 KiB
Vue
<script setup>
|
|
import { onMounted, onUnmounted, h, ref, watch, nextTick } from 'vue'
|
|
import { useUIStore } from '../../../stores/ui'
|
|
import { useUserStore } from '../../../stores/user'
|
|
import { useUserNotes } from '../../../composables/useUserNotes'
|
|
import { useModal } from '../../../composables/Core/useModal'
|
|
|
|
import SystemBroadcast from '../../../Components/SystemBroadcast.vue'
|
|
|
|
const uiStore = useUIStore()
|
|
const userStore = useUserStore()
|
|
const { notes, fetchNotes, dismissNotes, hasNotes } = useUserNotes()
|
|
const modal = useModal()
|
|
|
|
const headerRef = ref(null)
|
|
let resizeObserver = null
|
|
|
|
const updateHeaderHeight = () => {
|
|
if (headerRef.value) {
|
|
const height = headerRef.value.offsetHeight
|
|
document.documentElement.style.setProperty('--header-height', `${height}px`)
|
|
}
|
|
}
|
|
|
|
const goBack = () => {
|
|
window.history.back()
|
|
}
|
|
|
|
const reloadPage = () => {
|
|
window.location.reload()
|
|
}
|
|
|
|
const openAccountSettings = () => {
|
|
if (window.$navigateHelper) {
|
|
window.$navigateHelper({ page: 'AccountSettings' })
|
|
} else {
|
|
console.warn('Global $navigate function not found.')
|
|
}
|
|
}
|
|
|
|
const openNotesModal = () => {
|
|
if (!hasNotes()) return
|
|
|
|
modal.continueCancelModal({
|
|
title: 'Notes',
|
|
body: h('div', {
|
|
style: 'white-space: pre-wrap; font-size: 16px; line-height: 1.5; color: #333;'
|
|
}, notes.value),
|
|
continueText: 'Dismiss Note',
|
|
cancelText: 'Close',
|
|
continueClass: 'btn btn-danger w-50 py-2 rounded-3 shadow-sm fw-bold',
|
|
cancelClass: 'btn btn-light w-50 py-2 rounded-3 border fw-bold text-muted',
|
|
onContinue: async () => {
|
|
const success = await dismissNotes()
|
|
if (success) {
|
|
await fetchNotes()
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (userStore.isLoggedIn) {
|
|
fetchNotes()
|
|
}
|
|
updateHeaderHeight()
|
|
|
|
// Create a ResizeObserver to handle height changes (e.g., SystemBroadcast showing/hiding)
|
|
if (window.ResizeObserver && headerRef.value) {
|
|
resizeObserver = new ResizeObserver(() => {
|
|
updateHeaderHeight()
|
|
})
|
|
resizeObserver.observe(headerRef.value)
|
|
}
|
|
|
|
// Fallback: update on window resize
|
|
window.addEventListener('resize', updateHeaderHeight)
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
if (resizeObserver) {
|
|
resizeObserver.disconnect()
|
|
}
|
|
window.removeEventListener('resize', updateHeaderHeight)
|
|
})
|
|
|
|
// Update height when notes status changes
|
|
watch(() => hasNotes(), () => {
|
|
nextTick(() => updateHeaderHeight())
|
|
})
|
|
|
|
// Update height when page title changes (might wrap)
|
|
watch(() => uiStore.pageTitle, () => {
|
|
nextTick(() => updateHeaderHeight())
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="header is-fixed" id="maintopbarheader" ref="headerRef">
|
|
<SystemBroadcast />
|
|
<div class="tf-container">
|
|
<div class="tf-statusbar d-flex justify-content-center align-items-center">
|
|
<a href="javascript:void(0);" class="back-btn" @click="goBack" id="backbutton-top">
|
|
<i class="fas fa-chevron-left"></i>
|
|
</a>
|
|
<h3 id="topbar-title" @click="reloadPage" class="header-title">{{ uiStore.pageTitle }}</h3>
|
|
<div class="action-right-group">
|
|
<a
|
|
v-if="hasNotes()"
|
|
href="javascript:void(0);"
|
|
class="action-right-btn notes-btn"
|
|
@click="openNotesModal"
|
|
id="btn-notes-top"
|
|
title="You have notes"
|
|
>
|
|
<i class="fas fa-copy"></i>
|
|
<span class="notes-badge"></span>
|
|
</a>
|
|
<a href="javascript:void(0);" class="action-right-btn" @click="openAccountSettings" id="btn-popup-up">
|
|
<i class="fas fa-sliders-h"></i>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
|
|
<style scoped>
|
|
.header {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 100%;
|
|
max-width: var(--layout-max-width, 1440px);
|
|
z-index: 9999;
|
|
background-color: rgba(255, 255, 255, 0.85);
|
|
backdrop-filter: blur(15px);
|
|
-webkit-backdrop-filter: blur(15px);
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
:global(body.is-full-width) .header {
|
|
max-width: none !important;
|
|
}
|
|
|
|
:global(.dark-mode) .header {
|
|
background-color: var(--header-bg);
|
|
border-bottom-color: var(--border-color);
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.header-title {
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
color: #1e1e1e;
|
|
margin: 0;
|
|
cursor: pointer;
|
|
}
|
|
|
|
:global(.dark-mode) .header-title {
|
|
color: #e0e0e0;
|
|
}
|
|
|
|
.tf-statusbar {
|
|
height: 56px;
|
|
position: relative;
|
|
}
|
|
|
|
.back-btn {
|
|
position: absolute;
|
|
left: 16px;
|
|
color: #1e1e1e;
|
|
font-size: 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.action-right-group {
|
|
position: absolute;
|
|
right: 16px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
}
|
|
|
|
.action-right-btn {
|
|
color: #1e1e1e;
|
|
font-size: 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
position: relative;
|
|
}
|
|
|
|
.notes-btn {
|
|
color: #f2c71c;
|
|
}
|
|
|
|
.notes-badge {
|
|
position: absolute;
|
|
top: -2px;
|
|
right: -4px;
|
|
width: 8px;
|
|
height: 8px;
|
|
background-color: #ea3434;
|
|
border-radius: 50%;
|
|
border: 1.5px solid #fff;
|
|
}
|
|
|
|
:global(.dark-mode) .back-btn,
|
|
:global(.dark-mode) .action-right-btn {
|
|
color: #e0e0e0;
|
|
}
|
|
|
|
:global(.dark-mode) .notes-btn {
|
|
color: #f2c71c;
|
|
}
|
|
|
|
:global(.dark-mode) .notes-badge {
|
|
border-color: rgba(28, 30, 34, 0.85);
|
|
}
|
|
</style>
|