Add HeaderAdBanner component to ChatView, FeedbackView, and PartnersView

- Integrated HeaderAdBanner into ChatView.vue, FeedbackView.vue, and PartnersView.vue to enhance advertising capabilities.
- Updated PartnersView.vue to include a new app branding structure for improved visual hierarchy.

These changes collectively improve the user interface and advertising integration across multiple views.
This commit is contained in:
Torsten Schulz (local)
2026-03-19 15:25:42 +01:00
parent 47373a27af
commit 8319b43835
5 changed files with 223 additions and 2 deletions

View File

@@ -0,0 +1,80 @@
<template>
<div v-if="isEnabled" class="header-ad-banner">
<ins
ref="adElement"
class="adsbygoogle"
style="display:block"
:data-ad-client="adClient"
:data-ad-slot="adSlot"
data-ad-format="auto"
data-full-width-responsive="true"
></ins>
</div>
</template>
<script setup>
import { computed, nextTick, onMounted, ref } from 'vue';
const adElement = ref(null);
const adClient = import.meta.env.VITE_ADSENSE_CLIENT || '';
const adSlot = import.meta.env.VITE_ADSENSE_HEADER_SLOT || '';
const isEnabled = computed(() => Boolean(adClient && adSlot));
function ensureAdSenseScript() {
if (!isEnabled.value) return;
if (document.querySelector('script[data-adsense-loader="true"]')) return;
const script = document.createElement('script');
script.async = true;
script.src = `https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${adClient}`;
script.crossOrigin = 'anonymous';
script.dataset.adsenseLoader = 'true';
document.head.appendChild(script);
}
onMounted(async () => {
if (!isEnabled.value) return;
ensureAdSenseScript();
await nextTick();
try {
// Avoid duplicate initialization on remount.
if (adElement.value?.dataset.adsInitialized === 'true') return;
(window.adsbygoogle = window.adsbygoogle || []).push({});
if (adElement.value) {
adElement.value.dataset.adsInitialized = 'true';
}
} catch (error) {
console.warn('AdSense Banner konnte nicht initialisiert werden:', error);
}
});
</script>
<style scoped>
.header-ad-banner {
flex: 1;
min-width: 280px;
max-width: 728px;
margin: 0 16px;
padding: 4px 0;
}
.header-ad-banner :deep(ins) {
min-height: 50px;
}
@media (max-width: 960px) {
.header-ad-banner {
min-width: 220px;
max-width: 468px;
margin: 0 10px;
}
}
@media (max-width: 720px) {
.header-ad-banner {
display: none;
}
}
</style>

View File

@@ -8,6 +8,7 @@
<h1>Chat</h1>
</div>
</div>
<HeaderAdBanner />
<div v-if="chatStore.isLoggedIn" class="header-status">
<span class="header-status-chip">{{ chatStore.userName }}</span>
<span v-if="chatStore.isoCountryCode" class="header-status-chip">{{ chatStore.isoCountryCode }}</span>
@@ -89,6 +90,7 @@ import SearchView from '../components/SearchView.vue';
import InboxView from '../components/InboxView.vue';
import HistoryView from '../components/HistoryView.vue';
import ImprintContainer from '../components/ImprintContainer.vue';
import HeaderAdBanner from '../components/HeaderAdBanner.vue';
const chatStore = useChatStore();

View File

@@ -8,6 +8,7 @@
<h1>Feedback</h1>
</div>
</div>
<HeaderAdBanner />
</header>
<FeedbackPanel />
@@ -18,5 +19,6 @@
<script setup>
import FeedbackPanel from '../components/FeedbackPanel.vue';
import HeaderAdBanner from '../components/HeaderAdBanner.vue';
import ImprintContainer from '../components/ImprintContainer.vue';
</script>

View File

@@ -1,7 +1,14 @@
<template>
<div class="chat-container">
<header class="header">
<h1>SingleChat</h1>
<div class="app-brand">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<h1>Partner</h1>
</div>
</div>
<HeaderAdBanner />
</header>
<MenuBar />
@@ -36,6 +43,7 @@ import axios from 'axios';
import { useRouter } from 'vue-router';
import MenuBar from '../components/MenuBar.vue';
import UserList from '../components/UserList.vue';
import HeaderAdBanner from '../components/HeaderAdBanner.vue';
import ImprintContainer from '../components/ImprintContainer.vue';
import { useChatStore } from '../stores/chat';
@@ -52,4 +60,3 @@ onMounted(async () => {
}
});
</script>