12-05-2026 Frontend dev
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run

This commit is contained in:
Kevin Adametz 2026-05-12 18:32:33 +02:00
parent 405df0a122
commit 5b8bdf4182
779 changed files with 480564 additions and 6241 deletions

View file

@ -53,21 +53,21 @@ new class extends Component {
x-transition:leave="transition ease-in duration-200 transform"
x-transition:leave-start="translate-x-0"
x-transition:leave-end="-translate-x-full"
class="fixed left-0 top-0 h-full w-80 sm:w-96 bg-white dark:bg-gray-900 shadow-2xl z-[70] overflow-y-auto transition-colors duration-200"
class="fixed left-0 top-0 h-full w-80 sm:w-96 bg-white dark:bg-zinc-900 shadow-2xl z-[70] overflow-y-auto transition-colors duration-200"
x-cloak
>
<!-- Header -->
<div class="sticky top-0 bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800 p-4 flex items-center justify-between transition-colors duration-200">
<div class="sticky top-0 bg-white dark:bg-zinc-900 border-b border-zinc-200 dark:border-zinc-800 p-4 flex items-center justify-between transition-colors duration-200">
<div class="flex items-center gap-2">
<span class="w-1 h-6 bg-gradient-to-b from-[var(--color-primary)] to-[var(--color-secondary)] rounded-full"></span>
<h2 class="text-lg font-semibold text-gray-900 dark:text-gray-100">Navigation</h2>
<h2 class="text-lg font-semibold text-zinc-900 dark:text-zinc-100">Navigation</h2>
</div>
<button
@click="$wire.toggleMenu()"
class="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors"
class="p-2 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-lg transition-colors"
aria-label="Menü schließen"
>
<svg class="h-6 w-6 text-gray-600 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="h-6 w-6 text-zinc-600 dark:text-zinc-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
@ -77,15 +77,15 @@ new class extends Component {
<nav class="p-6 space-y-6">
<!-- Portal Section -->
<div>
<div class="py-2 text-sm font-semibold text-gray-900 dark:text-gray-100">Portal</div>
<div class="py-2 text-sm font-semibold text-zinc-900 dark:text-zinc-100">Portal</div>
<div class="space-y-1">
<a href="/" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Startseite
</a>
<a href="/kategorien" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/kategorien" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Kategorien
</a>
<a href="/suche" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/suche" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Suche
</a>
</div>
@ -95,7 +95,7 @@ new class extends Component {
<div>
<button
wire:click="toggleSection('services')"
class="flex items-center justify-between w-full py-2 text-sm font-semibold text-gray-900 dark:text-gray-100 hover:text-[var(--color-primary)] transition-colors"
class="flex items-center justify-between w-full py-2 text-sm font-semibold text-zinc-900 dark:text-zinc-100 hover:text-[var(--color-primary)] transition-colors"
>
<span class="flex items-center gap-2">
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@ -114,16 +114,16 @@ new class extends Component {
</button>
@if($this->isSectionOpen('services'))
<div class="mt-2 space-y-1 pl-6">
<a href="/veroeffentlichen" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/veroeffentlichen" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Pressemitteilung veröffentlichen
</a>
<a href="/newsrooms" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/newsrooms" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Newsrooms
</a>
<a href="/preise" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/preise" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Preise & Leistungen
</a>
<a href="/api" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/api" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
API & Integrationen
</a>
</div>
@ -134,7 +134,7 @@ new class extends Component {
<div>
<button
wire:click="toggleSection('about')"
class="flex items-center justify-between w-full py-2 text-sm font-semibold text-gray-900 dark:text-gray-100 hover:text-[var(--color-primary)] transition-colors"
class="flex items-center justify-between w-full py-2 text-sm font-semibold text-zinc-900 dark:text-zinc-100 hover:text-[var(--color-primary)] transition-colors"
>
<span class="flex items-center gap-2">
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@ -153,19 +153,19 @@ new class extends Component {
</button>
@if($this->isSectionOpen('about'))
<div class="mt-2 space-y-1 pl-6">
<a href="/ueber-uns" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/ueber-uns" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Über Business Portal
</a>
<a href="/team" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/team" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Team
</a>
<a href="/partner" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/partner" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Partner
</a>
<a href="/karriere" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/karriere" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Karriere
</a>
<a href="/presse" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/presse" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Presse
</a>
</div>
@ -176,7 +176,7 @@ new class extends Component {
<div>
<button
wire:click="toggleSection('support')"
class="flex items-center justify-between w-full py-2 text-sm font-semibold text-gray-900 dark:text-gray-100 hover:text-[var(--color-primary)] transition-colors"
class="flex items-center justify-between w-full py-2 text-sm font-semibold text-zinc-900 dark:text-zinc-100 hover:text-[var(--color-primary)] transition-colors"
>
<span class="flex items-center gap-2">
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@ -195,13 +195,13 @@ new class extends Component {
</button>
@if($this->isSectionOpen('support'))
<div class="mt-2 space-y-1 pl-6">
<a href="/faq" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/faq" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
FAQ
</a>
<a href="/hilfe" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/hilfe" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Hilfe-Center
</a>
<a href="/kontakt" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/kontakt" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Kontakt
</a>
</div>
@ -212,7 +212,7 @@ new class extends Component {
<div>
<button
wire:click="toggleSection('legal')"
class="flex items-center justify-between w-full py-2 text-sm font-semibold text-gray-900 dark:text-gray-100 hover:text-[var(--color-primary)] transition-colors"
class="flex items-center justify-between w-full py-2 text-sm font-semibold text-zinc-900 dark:text-zinc-100 hover:text-[var(--color-primary)] transition-colors"
>
<span class="flex items-center gap-2">
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@ -231,16 +231,16 @@ new class extends Component {
</button>
@if($this->isSectionOpen('legal'))
<div class="mt-2 space-y-1 pl-6">
<a href="/impressum" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/impressum" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Impressum
</a>
<a href="/datenschutz" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/datenschutz" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Datenschutz
</a>
<a href="/agb" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/agb" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
AGB
</a>
<a href="/cookies" class="block py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:translate-x-1 transition-all">
<a href="/cookies" class="block py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:translate-x-1 transition-all">
Cookie-Richtlinien
</a>
</div>
@ -249,7 +249,7 @@ new class extends Component {
</nav>
<!-- Footer Actions -->
<div class="sticky bottom-0 bg-white dark:bg-gray-900 border-t border-gray-200 dark:border-gray-800 p-6 space-y-3 transition-colors duration-200">
<div class="sticky bottom-0 bg-white dark:bg-zinc-900 border-t border-zinc-200 dark:border-zinc-800 p-6 space-y-3 transition-colors duration-200">
<a
href="/veroeffentlichen"
class="block w-full text-center px-4 py-3 text-sm font-medium text-white bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-secondary)] hover:from-[var(--color-primary)]/90 hover:to-[var(--color-secondary)]/90 rounded-lg shadow-md hover:shadow-lg transition-all"
@ -259,13 +259,13 @@ new class extends Component {
<div class="flex gap-2">
<a
href="/login"
class="flex-1 text-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800 rounded-lg transition-all"
class="flex-1 text-center px-4 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-300 border border-zinc-300 dark:border-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800 rounded-lg transition-all"
>
Anmelden
</a>
<a
href="/register"
class="flex-1 text-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800 rounded-lg transition-all"
class="flex-1 text-center px-4 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-300 border border-zinc-300 dark:border-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800 rounded-lg transition-all"
>
Registrieren
</a>
@ -274,14 +274,14 @@ new class extends Component {
<!-- Contact Info -->
<div class="px-6 pb-6">
<div class="p-4 bg-gray-50 dark:bg-gray-800 rounded-lg transition-colors duration-200">
<div class="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400 mb-2">
<div class="p-4 bg-zinc-50 dark:bg-zinc-800 rounded-lg transition-colors duration-200">
<div class="flex items-center gap-2 text-sm text-zinc-600 dark:text-zinc-400 mb-2">
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
</svg>
<span>Kontakt</span>
</div>
<a href="mailto:info@businessportal.de" class="text-sm text-gray-900 dark:text-gray-100 hover:text-[var(--color-primary)] transition-colors">
<a href="mailto:info@businessportal.de" class="text-sm text-zinc-900 dark:text-zinc-100 hover:text-[var(--color-primary)] transition-colors">
info@businessportal.de
</a>
</div>

View file

@ -60,140 +60,167 @@ new class extends Component {
private function getTimeframeLabel()
{
return match($this->timeframe) {
return match ($this->timeframe) {
'today' => 'Heute',
'7' => '7 Tage',
'30' => '30 Tage',
default => 'Zeitraum'
default => 'Zeitraum',
};
}
private function getIndustryLabel()
{
return match($this->industry) {
'it' => 'IT & Software',
'finance' => 'Finanzen',
'health' => 'Gesundheit',
'auto' => 'Automobil',
'energy' => 'Energie',
default => 'Alle Branchen'
return match ($this->industry) {
'it-digital' => 'IT & Digitalisierung',
'industry-tech' => 'Industrie & Technik',
'finance-insurance' => 'Finanzen & Versicherungen',
'retail-ecommerce' => 'Handel & E-Commerce',
'construction-realestate' => 'Bauen & Immobilien',
'mobility-logistics' => 'Mobilität & Logistik',
'energy-environment' => 'Energie & Umwelt',
'medicine-health' => 'Medizin & Gesundheit',
'hr-personnel' => 'Personal & HR',
'marketing-pr-media' => 'Marketing, PR & Medien',
'law-tax' => 'Recht & Steuern',
'politics-ngo' => 'Politik, Verbände & NGOs',
'science-research' => 'Wissenschaft & Forschung',
'lifestyle' => 'Lifestyle',
'tourism-culture' => 'Tourismus & Kultur',
default => 'Alle Branchen',
};
}
private function getRegionLabel()
{
return match($this->region) {
return match ($this->region) {
'de' => 'Deutschland',
'at' => 'Österreich',
'ch' => 'Schweiz',
default => 'Alle Regionen'
default => 'Alle Regionen',
};
}
}; ?>
<div>
<div class="sticky top-16 z-40 bg-white/95 dark:bg-gray-900/95 backdrop-blur-sm border-b border-gray-200 dark:border-gray-800 shadow-sm transition-colors duration-200">
<div
class="sticky top-16 z-40 bg-white/95 dark:bg-zinc-800 backdrop-blur-sm border-b border-zinc-200 dark:border-zinc-800 shadow-sm transition-colors duration-200">
<div class="container mx-auto px-4 py-4">
<div class="flex flex-wrap items-center gap-3">
<!-- Zeitraum -->
<div class="relative">
<select
wire:model.live="timeframe"
class="appearance-none pl-10 pr-8 py-2 text-sm border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-all hover:border-gray-400 dark:hover:border-gray-600 cursor-pointer"
>
<select wire:model.live="timeframe"
class="appearance-none pl-10 pr-8 py-2 text-sm border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-all hover:border-zinc-400 dark:hover:border-zinc-600 cursor-pointer">
<option value="today">Heute</option>
<option value="7">7 Tage</option>
<option value="30">30 Tage</option>
<option value="custom">Zeitraum</option>
</select>
<svg class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 dark:text-gray-400 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
<svg class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-500 dark:text-zinc-400 pointer-events-none"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z">
</path>
</svg>
<svg class="absolute right-2 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 dark:text-gray-400 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="absolute right-2 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-500 dark:text-zinc-400 pointer-events-none"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</div>
<!-- Branche -->
<div class="relative">
<select
wire:model.live="industry"
class="appearance-none pl-10 pr-8 py-2 text-sm border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-all hover:border-gray-400 dark:hover:border-gray-600 cursor-pointer"
>
<select wire:model.live="industry"
class="appearance-none pl-10 pr-8 py-2 text-sm border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-all hover:border-zinc-400 dark:hover:border-zinc-600 cursor-pointer">
<option value="all">Alle Branchen</option>
<option value="it">IT & Software</option>
<option value="finance">Finanzen</option>
<option value="health">Gesundheit</option>
<option value="auto">Automobil</option>
<option value="energy">Energie</option>
<option value="it-digital">IT & Digitalisierung</option>
<option value="industry-tech">Industrie & Technik</option>
<option value="finance-insurance">Finanzen & Versicherungen</option>
<option value="retail-ecommerce">Handel & E-Commerce</option>
<option value="construction-realestate">Bauen & Immobilien</option>
<option value="mobility-logistics">Mobilität & Logistik</option>
<option value="energy-environment">Energie & Umwelt</option>
<option value="medicine-health">Medizin & Gesundheit</option>
<option value="hr-personnel">Personal & HR</option>
<option value="marketing-pr-media">Marketing, PR & Medien</option>
<option value="law-tax">Recht & Steuern</option>
<option value="politics-ngo">Politik, Verbände & NGOs</option>
<option value="science-research">Wissenschaft & Forschung</option>
<option value="lifestyle">Lifestyle</option>
<option value="tourism-culture">Tourismus & Kultur</option>
</select>
<svg class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 dark:text-gray-400 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"></path>
<svg class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-500 dark:text-zinc-400 pointer-events-none"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4">
</path>
</svg>
<svg class="absolute right-2 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 dark:text-gray-400 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="absolute right-2 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-500 dark:text-zinc-400 pointer-events-none"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</div>
<!-- Region -->
<div class="relative">
<select
wire:model.live="region"
class="appearance-none pl-10 pr-8 py-2 text-sm border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-all hover:border-gray-400 dark:hover:border-gray-600 cursor-pointer"
>
<select wire:model.live="region"
class="appearance-none pl-10 pr-8 py-2 text-sm border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-all hover:border-zinc-400 dark:hover:border-zinc-600 cursor-pointer">
<option value="all">Alle Regionen</option>
<option value="de">Deutschland</option>
<option value="at">Österreich</option>
<option value="ch">Schweiz</option>
</select>
<svg class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 dark:text-gray-400 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path>
<svg class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-500 dark:text-zinc-400 pointer-events-none"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z">
</path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
<svg class="absolute right-2 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 dark:text-gray-400 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="absolute right-2 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-500 dark:text-zinc-400 pointer-events-none"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</div>
<!-- Sortierung -->
<div class="relative">
<select
wire:model.live="sortBy"
class="appearance-none pl-10 pr-8 py-2 text-sm border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-all hover:border-gray-400 dark:hover:border-gray-600 cursor-pointer"
>
<select wire:model.live="sortBy"
class="appearance-none pl-10 pr-8 py-2 text-sm border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-all hover:border-zinc-400 dark:hover:border-zinc-600 cursor-pointer">
<option value="newest">Neueste</option>
<option value="relevance">Relevanz</option>
</select>
<svg class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 dark:text-gray-400 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4"></path>
<svg class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-500 dark:text-zinc-400 pointer-events-none"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4"></path>
</svg>
<svg class="absolute right-2 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 dark:text-gray-400 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="absolute right-2 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-500 dark:text-zinc-400 pointer-events-none"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</div>
<!-- Active Filters Display -->
@if(count($activeFilters) > 0)
@if (count($activeFilters) > 0)
<div class="flex items-center gap-2 flex-wrap ml-auto">
@foreach($activeFilters as $filter)
<span class="inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-xs font-medium bg-[var(--color-primary)]/10 dark:bg-[var(--color-primary)]/20 text-[var(--color-primary)] border border-[var(--color-primary)]/20 dark:border-[var(--color-primary)]/30 transition-all hover:bg-[var(--color-primary)]/20 dark:hover:bg-[var(--color-primary)]/30">
@foreach ($activeFilters as $filter)
<span
class="inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-xs font-medium bg-[var(--color-primary)]/10 dark:bg-[var(--color-primary)]/20 text-[var(--color-primary)] border border-[var(--color-primary)]/20 dark:border-[var(--color-primary)]/30 transition-all hover:bg-[var(--color-primary)]/20 dark:hover:bg-[var(--color-primary)]/30">
{{ $filter['label'] }}
<button
wire:click="removeFilter('{{ $filter['key'] }}')"
class="hover:text-[var(--color-primary)]/70 transition-colors"
>
<button wire:click="removeFilter('{{ $filter['key'] }}')"
class="hover:text-[var(--color-primary)]/70 transition-colors">
<svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</span>
@endforeach
<!-- Reset Button -->
<button
wire:click="resetFilters"
class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors"
>
<button wire:click="resetFilters"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 transition-colors">
Alle zurücksetzen
</button>
</div>

View file

@ -18,54 +18,77 @@ new class extends Component {
}
}; ?>
<div x-data="{ darkMode: $wire.entangle('darkMode') }" x-init="
darkMode = localStorage.getItem('theme') === 'dark';
$watch('darkMode', value => {
localStorage.setItem('theme', value ? 'dark' : 'light');
if (value) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
});
// Initialize theme on load
if (darkMode) {
<div x-data="{ darkMode: $wire.entangle('darkMode') }" x-init="darkMode = localStorage.getItem('theme') === 'dark';
$watch('darkMode', value => {
localStorage.setItem('theme', value ? 'dark' : 'light');
if (value) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
">
<footer class="bg-white dark:bg-gray-900 border-t border-gray-200 dark:border-gray-800 py-8 mt-auto transition-colors duration-200">
});
// Initialize theme on load
if (darkMode) {
document.documentElement.classList.add('dark');
}">
<footer
class="bg-zinc-100 glow-soft dark:bg-zinc-900 border-t border-zinc-200 dark:border-zinc-800 py-8 mt-auto transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="grid grid-cols-2 md:grid-cols-4 gap-8 mb-8">
<div>
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3">Unternehmen</h3>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">Unternehmen</h3>
<ul class="space-y-2">
<li><a href="/ueber-uns" class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">Über uns</a></li>
<li><a href="/kontakt" class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">Kontakt</a></li>
<li><a href="/presse" class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">Presse</a></li>
<li><a href="/ueber-uns"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-200 transition-colors">Über
uns</a></li>
<li><a href="/kontakt"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-200 transition-colors">Kontakt</a>
</li>
<li><a href="/presse"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-200 transition-colors">Presse</a>
</li>
</ul>
</div>
<div>
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3">Services</h3>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">Services</h3>
<ul class="space-y-2">
<li><a href="/preise" class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">Preise</a></li>
<li><a href="/newsrooms" class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">Newsrooms</a></li>
<li><a href="/api" class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">API</a></li>
<li><a href="/preise"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-200 transition-colors">Preise</a>
</li>
<li><a href="/newsrooms"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-200 transition-colors">Newsrooms</a>
</li>
<li><a href="/api"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-200 transition-colors">API</a>
</li>
</ul>
</div>
<div>
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3">Rechtliches</h3>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">Rechtliches</h3>
<ul class="space-y-2">
<li><a href="/impressum" class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">Impressum</a></li>
<li><a href="/datenschutz" class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">Datenschutz</a></li>
<li><a href="/agb" class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">AGB</a></li>
<li><a href="/impressum"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-200 transition-colors">Impressum</a>
</li>
<li><a href="/datenschutz"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-200 transition-colors">Datenschutz</a>
</li>
<li><a href="/agb"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-200 transition-colors">AGB</a>
</li>
</ul>
</div>
<div>
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3">Folgen Sie uns</h3>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">Folgen Sie uns</h3>
<ul class="space-y-2">
<li><a href="https://linkedin.com" target="_blank" rel="noopener" class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">LinkedIn</a></li>
<li><a href="https://twitter.com" target="_blank" rel="noopener" class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">Twitter</a></li>
<li><a href="/rss" class="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">RSS</a></li>
<li><a href="https://linkedin.com" target="_blank" rel="noopener"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-200 transition-colors">LinkedIn</a>
</li>
<li><a href="https://twitter.com" target="_blank" rel="noopener"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-200 transition-colors">Twitter</a>
</li>
<li><a href="/rss"
class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-200 transition-colors">RSS</a>
</li>
</ul>
</div>
</div>
@ -73,50 +96,84 @@ new class extends Component {
@php
$theme = config('app.theme', 'businessportal24');
$isPresseecho = $theme === 'presseecho';
$isBusinessportal24 = $theme === 'businessportal24';
$currentYear = date('Y');
$siteName = $isPresseecho ? 'Presseecho' : 'Business Portal';
@endphp
<!-- Cross-Link für Presseecho -->
@if($isPresseecho)
<div class="mb-6 p-5 bg-gradient-to-r from-[var(--color-primary)]/5 to-[var(--color-secondary)]/5 dark:from-[var(--color-primary)]/10 dark:to-[var(--color-secondary)]/10 rounded-lg border border-[var(--color-primary)]/10">
@if ($isPresseecho)
<div
class="mb-6 p-5 bg-gradient-to-r from-[var(--color-primary)]/5 to-[var(--color-secondary)]/5 dark:from-[var(--color-primary)]/10 dark:to-[var(--color-secondary)]/10 rounded-lg border border-[var(--color-primary)]/10">
<div class="flex items-center justify-between gap-4 flex-wrap">
<div>
<p class="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-1">
<p class="text-sm font-semibold text-zinc-900 dark:text-zinc-100 mb-1">
Für maximale Reichweite?
</p>
<p class="text-sm text-gray-600 dark:text-gray-400">
Besuchen Sie unser reichweitenstarkes Portal <strong class="text-gray-900 dark:text-gray-100">Businessportal24</strong>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Besuchen Sie unser reichweitenstarkes Portal <strong
class="text-zinc-900 dark:text-zinc-100">Businessportal24</strong>
</p>
</div>
<a href="https://businessportal24.test"
class="inline-flex items-center gap-2 px-5 py-2.5 text-sm font-medium text-white bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-secondary)] hover:from-[var(--color-primary)]/90 hover:to-[var(--color-secondary)]/90 rounded-lg shadow-md hover:shadow-lg transition-all whitespace-nowrap">
Zu Businessportal24
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
</svg>
</a>
</div>
</div>
@endif
<div class="pt-6 border-t border-gray-200 dark:border-gray-700">
@if ($isBusinessportal24)
<div
class="mb-6 p-5 bg-gradient-to-r from-[var(--color-primary)]/5 to-[var(--color-secondary)]/5 dark:from-[var(--color-primary)]/10 dark:to-[var(--color-secondary)]/10 rounded-lg border border-[var(--color-primary)]/10">
<div class="flex items-center justify-between gap-4 flex-wrap">
<div>
<p class="text-sm font-semibold text-zinc-900 dark:text-zinc-100 mb-1">
Für maximale Reichweite?
</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Besuchen Sie unser reichweitenstarkes Portal <strong
class="text-zinc-900 dark:text-zinc-100">presseecho</strong>
</p>
</div>
<a href="https://presseecho.test"
class="inline-flex items-center gap-2 px-5 py-2.5 text-sm font-medium text-white bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-secondary)] hover:from-[var(--color-primary)]/90 hover:to-[var(--color-secondary)]/90 rounded-lg shadow-md hover:shadow-lg transition-all whitespace-nowrap">
Zu Presseecho
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
</svg>
</a>
</div>
</div>
@endif
<div class="pt-6 border-t border-zinc-200 dark:border-zinc-700">
<div class="flex flex-col md:flex-row items-center justify-between gap-4">
<p class="text-sm text-gray-600 dark:text-gray-400">© {{ $currentYear }} {{ $siteName }}. Alle Rechte vorbehalten.</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400">© {{ $currentYear }} {{ $siteName }}. Alle
Rechte vorbehalten.</p>
<!-- Theme Toggle -->
<button
@click="darkMode = !darkMode"
class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-all"
aria-label="Theme wechseln"
>
<button @click="darkMode = !darkMode"
class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800 border border-zinc-200 dark:border-zinc-600 rounded-lg transition-all"
aria-label="Theme wechseln">
<!-- Sun Icon (zeigt in Dark Mode) -->
<svg x-show="darkMode" class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" x-cloak>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path>
<svg x-show="darkMode" class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
x-cloak>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z">
</path>
</svg>
<!-- Moon Icon (zeigt in Light Mode) -->
<svg x-show="!darkMode" class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path>
<svg x-show="!darkMode" class="h-5 w-5" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z">
</path>
</svg>
<span x-text="darkMode ? 'Hell' : 'Dunkel'"></span>
</button>

View file

@ -15,7 +15,7 @@ new class extends Component {
<div>
<header
class="sticky top-0 z-50 bg-white dark:bg-gray-900 border-b border-gray-200/50 dark:border-gray-800/50 shadow-sm backdrop-blur-sm transition-colors duration-200">
class="sticky top-0 z-50 bg-white dark:bg-zinc-900 border-b border-zinc-200/50 dark:border-zinc-800/50 shadow-sm backdrop-blur-sm transition-colors duration-200">
<!-- Brand Accent Bar -->
<div
class="h-1 bg-gradient-to-r from-[var(--color-primary)] via-[var(--color-secondary)] to-[var(--color-primary)]">
@ -26,9 +26,9 @@ new class extends Component {
<div class="flex items-center gap-3">
<!-- Burger Menu Button (immer sichtbar) -->
<button @click="$dispatch('toggle-mobile-menu')"
class="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors"
class="p-2 hover:bg-zinc-100 dark:hover:bg-zinc-800 border border-zinc-200 dark:border-zinc-600 rounded-lg transition-colors"
aria-label="Menü öffnen">
<svg class="h-6 w-6 text-gray-900 dark:text-gray-100" fill="none" stroke="currentColor"
<svg class="h-6 w-6 text-zinc-900 dark:text-zinc-100" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4 6h16M4 12h16M4 18h16"></path>
@ -42,7 +42,7 @@ new class extends Component {
// Versuche verschiedene Logo-Namenskonventionen
$logoVariants = [
"images/{$theme}-logo.svg",
"images/" . str_replace('24', '', $theme) . "-logo.svg", // businessportal-logo.svg
'images/' . str_replace('24', '', $theme) . '-logo.svg', // businessportal-logo.svg
];
$logoPath = null;
@ -71,20 +71,20 @@ new class extends Component {
<!-- Search - Desktop -->
<div class="hidden md:flex flex-1 max-w-xl">
<form wire:submit.prevent="search" class="relative w-full">
<svg class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" fill="none"
<svg class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-400" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
<input type="search" wire:model="searchQuery" placeholder="Pressemitteilungen durchsuchen..."
class="pl-10 w-full rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-all" />
class="pl-10 w-full rounded-lg border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-all" />
</form>
</div>
<!-- Search Icon - Mobile -->
<button @click="$wire.showMobileSearch = !$wire.showMobileSearch"
class="md:hidden p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors">
<svg class="h-5 w-5 text-gray-900 dark:text-gray-100" fill="none" stroke="currentColor"
class="md:hidden p-2 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-lg transition-colors">
<svg class="h-5 w-5 text-zinc-900 dark:text-zinc-100" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
@ -101,17 +101,17 @@ new class extends Component {
@if ($isPresseecho)
<!-- Presseecho: Dezente Navigation -->
<a href="/login"
class="hidden sm:inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors">
class="hidden sm:inline-flex items-center px-4 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-300 hover:text-zinc-900 dark:hover:text-zinc-100 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-lg transition-colors">
Anmelden
</a>
<a href="/beitrag-einreichen"
class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors border border-gray-300 dark:border-gray-700">
class="inline-flex items-center px-4 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-300 hover:text-zinc-900 dark:hover:text-zinc-100 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-lg transition-colors border border-zinc-300 dark:border-zinc-700">
Beitrag einreichen
</a>
@else
<!-- Businessportal24: Prominenter CTA -->
<a href="/login"
class="hidden sm:inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors">
class="hidden sm:inline-flex items-center px-4 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-300 hover:text-zinc-900 dark:hover:text-zinc-100 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-lg transition-colors">
Anmelden
</a>
<a href="/veroeffentlichen"
@ -127,15 +127,15 @@ new class extends Component {
x-transition:enter-start="opacity-0 -translate-y-2" x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-in duration-150" x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 -translate-y-2"
class="md:hidden border-t border-gray-200 dark:border-gray-800 px-4 py-3 bg-white dark:bg-gray-900" x-cloak>
class="md:hidden border-t border-zinc-200 dark:border-zinc-800 px-4 py-3 bg-white dark:bg-zinc-900" x-cloak>
<form wire:submit.prevent="search" class="relative">
<svg class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400 dark:text-gray-500"
<svg class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-400 dark:text-zinc-500"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
<input type="search" wire:model="searchQuery" placeholder="Pressemitteilungen durchsuchen..."
class="pl-10 w-full rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-all" />
class="pl-10 w-full rounded-lg border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-all" />
</form>
</div>
</header>

View file

@ -0,0 +1,159 @@
<?php
use App\Enums\Portal;
use App\Enums\PressReleaseStatus;
use App\Models\PressRelease;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Pagination\LengthAwarePaginator;
use Livewire\Attributes\Locked;
use Livewire\Volt\Component;
use Livewire\WithPagination;
new class extends Component {
use WithPagination;
public string $timeframe = 'all';
#[Locked]
public ?string $portal = null;
protected array $queryString = [
'timeframe' => ['except' => 'all'],
];
public function setTimeframe(string $timeframe): void
{
$this->timeframe = $timeframe;
$this->resetPage();
}
public function with(): array
{
return [
'releases' => $this->pressReleases(),
'totalCount' => $this->totalCount(),
];
}
private function pressReleases(): LengthAwarePaginator
{
return $this->baseQuery()
->when($this->timeframe === 'today', fn (Builder $query) => $query->whereDate('published_at', today()))
->when($this->timeframe === 'week', fn (Builder $query) => $query->where('published_at', '>=', now()->subDays(7)))
->orderByDesc('published_at')
->paginate(8);
}
private function totalCount(): int
{
return $this->baseQuery()->count();
}
private function baseQuery(): Builder
{
return PressRelease::query()
->with([
'company',
'category.translations' => fn ($query) => $query->where('locale', 'de'),
'images' => fn ($query) => $query
->orderByDesc('is_preview')
->orderBy('sort_order')
->limit(1),
])
->whereIn('portal', $this->portalValues())
->where('status', PressReleaseStatus::Published)
->where('language', 'de')
->whereNotNull('published_at')
->where('published_at', '<=', now());
}
/**
* @return array<int, string>
*/
private function portalValues(): array
{
$primary = $this->portal ?? Portal::Businessportal24->value;
return [$primary, Portal::Both->value];
}
}; ?>
<div wire:loading.class="opacity-60">
<header class="flex items-baseline justify-between mb-4 min-h-[34px] flex-wrap gap-3">
<h2 class="font-serif text-[28px] font-semibold m-0 tracking-[-0.3px] leading-[1.2] text-ink">
Aktuelle Meldungen
</h2>
<div class="flex gap-[18px] text-[12.5px] text-ink-3">
<button type="button" wire:click="setTimeframe('all')"
class="cursor-pointer transition-colors @if ($timeframe === 'all') text-ink border-b-[1.5px] border-brand pb-0.5 @else hover:text-ink @endif">
Alle
</button>
<button type="button" wire:click="setTimeframe('today')"
class="cursor-pointer transition-colors @if ($timeframe === 'today') text-ink border-b-[1.5px] border-brand pb-0.5 @else hover:text-ink @endif">
Heute
</button>
<button type="button" wire:click="setTimeframe('week')"
class="cursor-pointer transition-colors @if ($timeframe === 'week') text-ink border-b-[1.5px] border-brand pb-0.5 @else hover:text-ink @endif">
Diese Woche
</button>
</div>
</header>
<hr class="rule-strong">
@php
$items = $releases->items();
$top = $items[0] ?? null;
$rest = array_slice($items, 1);
$mockFeedItems = [
['time' => '13:42', 'date' => '12. Mai', 'category' => 'Tourismus', 'title' => 'Nachhaltiger Tourismus auf Erfolgskurs: Buchungen steigen um 45 %', 'company' => 'GreenTravel Consulting', 'city' => 'Berlin', 'recommended' => true],
['time' => '12:55', 'date' => '12. Mai', 'category' => 'Bildung', 'title' => 'Digitalisierung im Bildungssektor: Schulen erhalten 2 Mrd. Euro Förderung', 'company' => 'EduTech Initiative', 'city' => 'Frankfurt'],
['time' => '11:20', 'date' => '12. Mai', 'category' => 'Medien', 'title' => 'Medienbranche im Umbruch: Streaming-Dienste überholen klassisches TV', 'company' => 'MediaWatch Analytics', 'city' => 'Hamburg'],
['time' => '10:48', 'date' => '12. Mai', 'category' => 'Handel', 'title' => 'Einzelhandel setzt auf KI: Personalisierte Shopping-Erlebnisse werden Standard', 'company' => 'RetailTech Innovations', 'city' => 'Köln', 'recommended' => true],
['time' => '09:33', 'date' => '12. Mai', 'category' => 'Gesundheit', 'title' => 'Telemedizin-Boom: 3 Millionen Online-Sprechstunden im letzten Quartal', 'company' => 'HealthConnect Digital', 'city' => 'Stuttgart'],
['time' => '08:15', 'date' => '12. Mai', 'category' => 'Mobilität', 'title' => 'E-Mobilität: Ladeinfrastruktur wächst um 38 % gegenüber Vorjahr', 'company' => 'eMobility Verband', 'city' => 'Düsseldorf'],
];
$inFeedAd = [
'time' => '12:14',
'date' => now()->translatedFormat('j. MMM'),
'category' => 'Cloud · Software',
'title' => 'Microsoft Azure: Neue EU-Region Frankfurt mit DSGVO-zertifizierter KI-Infrastruktur',
'company' => 'Microsoft Deutschland GmbH',
];
@endphp
@if ($top)
<x-web.feed-top-item :release="$top" />
@else
<x-web.feed-top-item />
@endif
@if (! empty($rest))
@foreach ($rest as $i => $release)
<x-web.feed-item :release="$release" :recommended="in_array($i, [0, 3], true)" />
@endforeach
@else
@foreach ($mockFeedItems as $mock)
<x-web.feed-item :mock="$mock" />
@endforeach
@endif
<x-web.feed-ad :ad="$inFeedAd" />
@if ($releases->hasMorePages())
<div class="flex justify-center mt-7">
<a href="{{ $releases->nextPageUrl() }}"
class="inline-flex items-center gap-2 px-[18px] py-2.5 text-[13px] font-semibold text-ink bg-transparent border border-bg-rule-strong rounded-[2px] cursor-pointer hover:bg-ink hover:text-bg transition-colors">
Weitere {{ number_format(max(0, $totalCount - $releases->currentPage() * $releases->perPage()), 0, ',', '.') }} Meldungen anzeigen
</a>
</div>
@elseif (! $top)
<div class="flex justify-center mt-7">
<a href="{{ route('kategorien') }}"
class="inline-flex items-center gap-2 px-[18px] py-2.5 text-[13px] font-semibold text-ink bg-transparent border border-bg-rule-strong rounded-[2px] cursor-pointer hover:bg-ink hover:text-bg transition-colors">
Alle Rubriken entdecken
</a>
</div>
@endif
</div>

View file

@ -13,7 +13,7 @@ new class extends Component {
'title' => 'KI-Revolution: Deutsche Unternehmen investieren Milliarden in Automatisierung',
'teaser' => 'Eine neue Studie zeigt: Unternehmen im DACH-Raum planen für 2025 Investitionen in Höhe von über 15 Milliarden Euro in KI-gestützte Automatisierungslösungen.',
'company' => 'TechVision Analytics',
'industry' => 'IT & Software',
'industry' => 'IT & Digitalisierung',
'region' => 'Deutschland',
'date' => '17. Okt 2024',
'contentType' => 'ANALYSE',
@ -27,7 +27,7 @@ new class extends Component {
'title' => 'Energiewende beschleunigt sich: Neue Rekorde bei erneuerbaren Energien',
'teaser' => 'Im ersten Quartal 2025 erreicht der Anteil erneuerbarer Energien am Strommix einen historischen Höchststand von 58%.',
'company' => 'GreenPower Deutschland',
'industry' => 'Energie',
'industry' => 'Energie & Umwelt',
'region' => 'Deutschland',
'date' => '16. Okt 2024',
'contentType' => 'FACHMELDUNG',
@ -39,7 +39,7 @@ new class extends Component {
'title' => 'FinTech-Startup sichert sich 45 Millionen Euro in Series-B-Runde',
'teaser' => 'Das Berliner FinTech-Startup PaymentFlow konnte in einer Series-B-Finanzierungsrunde 45 Millionen Euro einsammeln.',
'company' => 'PaymentFlow GmbH',
'industry' => 'Finanzen',
'industry' => 'Finanzen & Versicherungen',
'region' => 'Berlin',
'date' => '15. Okt 2024',
'contentType' => 'FACHMELDUNG',
@ -51,7 +51,7 @@ new class extends Component {
'title' => 'Gesundheitsbranche setzt verstärkt auf digitale Lösungen',
'teaser' => 'Telemedizin und KI-gestützte Diagnostik werden zum Standard: 78% der Krankenhäuser in Deutschland planen Investitionen.',
'company' => 'MediTech Solutions',
'industry' => 'Gesundheit',
'industry' => 'Medizin & Gesundheit',
'region' => 'München',
'date' => '14. Okt 2024',
'contentType' => 'INTERVIEW',
@ -63,7 +63,7 @@ new class extends Component {
'title' => 'Automobilindustrie: Transformation zur E-Mobilität nimmt Fahrt auf',
'teaser' => 'Führende Automobilhersteller kündigen massive Investitionen in E-Mobilität an. Bis 2030 sollen 80% der Neufahrzeuge elektrisch sein.',
'company' => 'Auto Industry Report',
'industry' => 'Automobil',
'industry' => 'Mobilität & Logistik',
'region' => 'Stuttgart',
'date' => '13. Okt 2024',
'contentType' => 'ANALYSE',
@ -76,14 +76,90 @@ new class extends Component {
'title' => 'Cybersecurity: Unternehmen verstärken Schutzmaßnahmen gegen Hackerangriffe',
'teaser' => 'Nach einer Serie von Cyberattacken erhöhen deutsche Unternehmen ihre Investitionen in IT-Sicherheit um durchschnittlich 35%.',
'company' => 'CyberSafe Europe',
'industry' => 'IT & Software',
'industry' => 'IT & Digitalisierung',
'region' => 'Frankfurt',
'date' => '12. Okt 2024',
'contentType' => 'FACHMELDUNG',
'hasImage' => true,
'imageUrl' => 'https://images.unsplash.com/photo-1550751827-4bd374c3f58b?w=800&h=600&fit=crop',
],
]
// Neue Artikel ohne Bild für verschiedene Branchen
[
'slug' => 'immobilienmarkt-trendwende',
'title' => 'Immobilienmarkt 2025: Experten prognostizieren Trendwende bei Kaufpreisen',
'teaser' => 'Nach Jahren steigender Preise zeigen aktuelle Analysen eine Stabilisierung des Immobilienmarktes. Besonders Metropolregionen verzeichnen erstmals rückläufige Tendenzen.',
'company' => 'ImmoConsult Deutschland',
'industry' => 'Bauen & Immobilien',
'region' => 'Hamburg',
'date' => '11. Okt 2024',
'contentType' => 'ANALYSE',
'hasImage' => false,
'hasPdf' => true,
'imageUrl' => null,
],
[
'slug' => 'tourismus-nachhaltigkeit',
'title' => 'Nachhaltiger Tourismus auf Erfolgskurs: Buchungen steigen um 45%',
'teaser' => 'Öko-Hotels und klimaneutrales Reisen liegen im Trend. Die Reisebranche verzeichnet einen deutlichen Wandel im Buchungsverhalten deutscher Urlauber.',
'company' => 'GreenTravel Consulting',
'industry' => 'Tourismus & Kultur',
'region' => 'Österreich',
'date' => '10. Okt 2024',
'contentType' => 'FACHMELDUNG',
'hasImage' => false,
'imageUrl' => null,
],
[
'slug' => 'bildungssektor-digitalisierung',
'title' => 'Digitalisierung im Bildungssektor: Schulen erhalten 2 Milliarden Euro Förderung',
'teaser' => 'Bundesweites Digitalpakt-Programm wird ausgeweitet. Schwerpunkt liegt auf KI-gestützten Lernplattformen und moderner IT-Infrastruktur für Schulen.',
'company' => 'EduTech Initiative',
'industry' => 'Wissenschaft & Forschung',
'region' => 'Berlin',
'date' => '09. Okt 2024',
'contentType' => 'FACHMELDUNG',
'hasImage' => false,
'hasPdf' => true,
'imageUrl' => null,
],
[
'slug' => 'medienbranche-streaming',
'title' => 'Medienbranche im Umbruch: Streaming-Dienste überholen klassisches TV',
'teaser' => 'Erstmals nutzen mehr Deutsche regelmäßig Streaming-Plattformen als lineares Fernsehen. Die Werbebudgets verschieben sich entsprechend.',
'company' => 'MediaWatch Analytics',
'industry' => 'Marketing, PR & Medien',
'region' => 'Köln',
'date' => '08. Okt 2024',
'contentType' => 'ANALYSE',
'hasImage' => false,
'imageUrl' => null,
],
[
'slug' => 'einzelhandel-ki-revolution',
'title' => 'Einzelhandel setzt auf KI: Personalisierte Shopping-Erlebnisse werden Standard',
'teaser' => 'Künstliche Intelligenz revolutioniert den Handel. Von virtuellen Anproben bis zu KI-gestützter Beratung der Einzelhandel wird digital.',
'company' => 'RetailTech Innovations',
'industry' => 'Handel & E-Commerce',
'region' => 'Düsseldorf',
'date' => '07. Okt 2024',
'contentType' => 'INTERVIEW',
'hasImage' => false,
'hasPdf' => true,
'imageUrl' => null,
],
[
'slug' => 'gesundheit-telemedizin-boom',
'title' => 'Telemedizin-Boom: 3 Millionen Online-Sprechstunden im letzten Quartal',
'teaser' => 'Die Akzeptanz von Videosprechstunden erreicht neue Höchststände. Besonders ländliche Regionen profitieren von der digitalen Gesundheitsversorgung.',
'company' => 'HealthConnect Digital',
'industry' => 'Medizin & Gesundheit',
'region' => 'Schweiz',
'date' => '06. Okt 2024',
'contentType' => 'FACHMELDUNG',
'hasImage' => false,
'imageUrl' => null,
],
],
];
}
}; ?>
@ -95,35 +171,16 @@ new class extends Component {
@endphp
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
@foreach($releases as $release)
@if($isPresseecho)
@foreach ($releases as $release)
@if ($isPresseecho)
{{-- Presseecho: Hochwertige Magazine-Card --}}
<x-web.presseecho-release-card
:title="$release['title']"
:teaser="$release['teaser']"
:company="$release['company']"
:industry="$release['industry']"
:region="$release['region']"
:date="$release['date']"
:contentType="$release['contentType'] ?? 'FACHMELDUNG'"
:slug="$release['slug']"
:imageUrl="$release['imageUrl'] ?? null"
/>
<x-web.press-release-card :title="$release['title']" :teaser="$release['teaser']" :company="$release['company']" :industry="$release['industry']"
:region="$release['region']" :date="$release['date']" :contentType="$release['contentType'] ?? 'FACHMELDUNG'" :slug="$release['slug']" :imageUrl="$release['imageUrl'] ?? null" />
@else
{{-- Businessportal24: Standard-Card --}}
<x-web.press-release-card
:title="$release['title']"
:teaser="$release['teaser']"
:company="$release['company']"
:industry="$release['industry']"
:region="$release['region']"
:date="$release['date']"
:hasImage="$release['hasImage'] ?? false"
:hasPdf="$release['hasPdf'] ?? false"
:slug="$release['slug']"
:imageUrl="$release['imageUrl'] ?? null"
:companyLogo="$release['companyLogo'] ?? null"
/>
<x-web.press-release-card :title="$release['title']" :teaser="$release['teaser']" :company="$release['company']" :industry="$release['industry']"
:region="$release['region']" :date="$release['date']" :hasImage="$release['hasImage'] ?? false" :hasPdf="$release['hasPdf'] ?? false" :slug="$release['slug']"
:imageUrl="$release['imageUrl'] ?? null" :companyLogo="$release['companyLogo'] ?? null" />
@endif
@endforeach
</div>