presseportale/resources/views/components/web/live-ticker.blade.php
Kevin Adametz bfad13af7d Spoke-Frontend-Audit: Fake-Inhalte raus, Newsletter-Rueckbau, echte Boersendaten, EN-Lokalisierung
Frontend-Umbau (Kevin, 06.07.2026), Ergebnis des businessportal24-Audits:

- Fake-Anzeigen und Mock-/Fallback-Daten entfernt (focus-ad, feed-ad,
  highlight-card, press-release-card, featured-releases, press-releases-grid);
  Sektionen rendern nur noch mit echten Daten oder gar nicht
- Newsletter-Strip und Newsletter-Box zurueckgebaut (Feature nachgelagert,
  vor Reaktivierung DOI-Flow noetig)
- Echte Boersendaten: MarketDataService (Yahoo-Finance-Quotes, config/market.php,
  Cache) + market:refresh alle 15 Min. im Scheduler; live-ticker blendet sich
  ohne Daten aus
- EN-Lokalisierung der Kern-Seiten via lang/de/web.php + lang/en/web.php;
  Carbon-Locale folgt app()->getLocale()
- Web-Tests auf den neuen Frontend-Stand nachgezogen (Suite: 993 gruen)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 13:36:23 +00:00

93 lines
5.2 KiB
PHP

@php
// Selbstversorgend, damit der Ticker auf jeder Unterseite gefüllt ist
// (nicht nur auf der Startseite): jüngste PMs des Portals, kurz gecacht.
$items = app(\App\Services\Web\TickerData::class)
->items(\App\Support\WebPortalContext::portalFromHost(), app()->getLocale());
// Echte Kursdaten aus dem Cache (market:refresh); leer = Slot ausblenden.
$marketSlides = app(\App\Services\Web\MarketDataService::class)->slides();
@endphp
@if (! empty($items) || ! empty($marketSlides))
<div class="bg-topbar-grad text-ink-on-dark" aria-label="{{ __('web.ticker.aria_label') }}">
<div class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 py-2.5 flex items-center gap-3 sm:gap-5 text-[12.5px]">
@if (! empty($items))
<div class="flex items-center gap-3 sm:gap-4 overflow-hidden min-w-0 flex-1">
<span class="flex items-center gap-1.5 text-accent-warm font-bold text-[10.5px] sm:text-[11px] tracking-[0.15em] flex-shrink-0">
<span class="w-[7px] h-[7px] rounded-full bg-accent-warm pulse-dot"></span>
AD-HOC
</span>
<span class="sr-only">
{{ __('web.ticker.sr_intro') }}
@foreach ($items as $item)
{{ $item['time'] }} {{ $item['text'] }}.
@endforeach
</span>
<div class="overflow-hidden min-w-0 flex-1" aria-hidden="true">
<div class="ticker-marquee-track text-[12px] sm:text-[12.5px] whitespace-nowrap">
@foreach (array_merge($items, $items) as $item)
<span class="inline-flex shrink-0 gap-2 items-baseline">
<span class="font-mono text-[11px] text-ink-on-dark-muted">{{ $item['time'] }}</span>
<span class="text-ink-on-dark">{{ $item['text'] }}</span>
</span>
@endforeach
</div>
</div>
</div>
@else
<span class="flex-1"></span>
@endif
@if (! empty($marketSlides))
<span class="hidden sm:inline-block w-px h-[18px] bg-ink-on-dark-rule flex-shrink-0"></span>
{{-- Kein position:absolute: sonst null Breite im Fluss, bis Layout kollabiert --}}
<div class="shrink-0 flex justify-end items-center min-w-0 max-w-[min(92vw,280px)] sm:max-w-[min(42vw,280px)]"
x-data="{
slides: @js($marketSlides),
i: 0,
init() {
if (this.slides.length < 2) {
return;
}
window.setInterval(() => {
this.i = (this.i + 1) % this.slides.length;
}, 5200);
},
}"
aria-live="polite">
<div class="grid min-h-[22px] justify-items-end overflow-hidden [grid-template-columns:minmax(0,max-content)]">
<template x-for="(slide, idx) in slides" :key="idx">
<div x-show="i === idx"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 -translate-y-full"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-in duration-280"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 translate-y-full"
class="col-start-1 row-start-1 flex items-center gap-2 whitespace-nowrap">
<span class="text-ink-on-dark-muted font-semibold text-[10.5px] tracking-wider" x-text="slide.label"></span>
<span class="text-ink-on-dark font-mono text-[12.5px]" x-text="slide.value"></span>
<span class="font-semibold text-[11.5px] font-mono"
:class="(slide.positive ?? true) ? 'text-gain' : 'text-loss'"
x-text="slide.delta"></span>
{{-- Dekorativer Richtungspfeil (auf/ab je Vorzeichen, keine echte Kurve) --}}
<svg width="26" height="10" viewBox="0 0 26 10"
class="hidden sm:inline-block shrink-0"
:class="(slide.positive ?? true) ? 'text-gain' : 'text-loss'"
aria-hidden="true">
<path x-show="slide.positive ?? true" d="M0,8 L4,7 L8,5 L12,6 L16,4 L20,3 L24,2"
fill="none" stroke="currentColor" stroke-width="1.2" />
<path x-show="!(slide.positive ?? true)" d="M0,2 L4,3 L8,5 L12,4 L16,6 L20,7 L24,8"
fill="none" stroke="currentColor" stroke-width="1.2" />
</svg>
</div>
</template>
</div>
</div>
@endif
</div>
</div>
@endif