Oeffentliche Strecke durchgaengig auf das Editorial-Design umgestellt und
datengetrieben gemacht:
- Newsrooms-Verzeichnis + Newsroom-Detailseiten (Suche, Pagination)
- Preise-Seite neu (Abos via Plan, Einzel-PM via config/billing, Add-ons via
config/credits); Texte ausgelagert nach lang/{de,en}/pricing.php
- Pricing-Teaser-Komponente auf den Startseiten + Preise-Link in Header/Footer
- Statische Seiten im Editorial-Design ueber neue Komponente x-web.static-page:
impressum, datenschutz, agb, cookies, faq (Akkordeon), hilfe, kontakt,
ueber-uns, api (altes Theme/gradient-hero entfernt)
- Header/Footer-Linkpflege: tote #-Anker raus, FAQ/Hilfe/Cookies verlinkt,
"Anmelden" fuehrt in den Hub
- Legacy-URL-Redirects (.html, presskit->newsroom, Regionen)
- Datums-Bugfix in Feed-Komponenten
Tests: NewsroomPage, PreisePage, PricingTeaser, StaticPages, NavigationLinks,
LegacyRedirect. Doku in docs/frontend aktualisiert.
Co-authored-by: Cursor <cursoragent@cursor.com>
104 lines
5.5 KiB
PHP
104 lines
5.5 KiB
PHP
@props([
|
|
'plans' => null,
|
|
'popular' => 'business',
|
|
'pricingHref' => null,
|
|
'submitHref' => null,
|
|
])
|
|
|
|
@php
|
|
// Datengetrieben aus dem Tarif-Katalog (plans). Fällt die Tabelle leer aus,
|
|
// wird die Sektion komplett ausgeblendet.
|
|
$plans = $plans ?? \App\Models\Plan::active()->get();
|
|
$pricingHref ??= route('preise');
|
|
$submitHref ??= route('veroeffentlichen');
|
|
|
|
$fmtPrice = static fn (int $cents): string => number_format($cents / 100, $cents % 100 === 0 ? 0 : 2, ',', '.');
|
|
@endphp
|
|
|
|
@if ($plans->isNotEmpty())
|
|
<section class="max-w-layout mx-auto px-8 mt-16">
|
|
<header class="flex items-baseline justify-between mb-4 flex-wrap gap-3">
|
|
<h2 class="font-serif text-[28px] font-semibold m-0 tracking-[-0.3px] text-ink">Tarife & Pakete</h2>
|
|
<a href="{{ $pricingHref }}" class="eyebrow muted hover:text-ink transition-colors inline-flex items-center gap-1.5 cursor-pointer">
|
|
Alle Details
|
|
<svg width="10" height="10" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
|
<path d="M2 6h8M6 2l4 4-4 4" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
</a>
|
|
</header>
|
|
<hr class="rule-strong">
|
|
|
|
<div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-1 sm:grid-cols-2 lg:grid-cols-4">
|
|
@foreach ($plans as $plan)
|
|
@php
|
|
$isPopular = $plan->slug === $popular;
|
|
$hasMonthly = (int) $plan->monthly_price_cents > 0;
|
|
@endphp
|
|
<div class="relative flex flex-col p-6 bg-bg {{ $isPopular ? 'ring-1 ring-inset ring-brand' : '' }}">
|
|
@if ($isPopular)
|
|
<span class="absolute top-0 right-0 inline-flex items-center px-2.5 py-1 text-[9.5px] font-bold uppercase tracking-[0.14em] text-white bg-brand">
|
|
Beliebt
|
|
</span>
|
|
@endif
|
|
|
|
<div class="eyebrow muted mb-2">{{ $plan->name }}</div>
|
|
|
|
<div class="flex items-baseline gap-1.5 mb-1">
|
|
<span class="font-serif text-[34px] font-semibold leading-none tracking-[-0.6px] text-ink">{{ $fmtPrice((int) $plan->monthly_price_cents) }} €</span>
|
|
@if ($hasMonthly)
|
|
<span class="text-[12px] text-ink-3">/ Monat</span>
|
|
@endif
|
|
</div>
|
|
|
|
@if ($hasMonthly && (int) $plan->yearly_price_cents > 0)
|
|
<div class="text-[11.5px] text-ink-3 mb-4">
|
|
{{ $fmtPrice((int) $plan->yearly_price_cents) }} € / Jahr
|
|
<span class="text-gain font-medium">· 2 Monate gratis</span>
|
|
</div>
|
|
@else
|
|
<div class="mb-4"></div>
|
|
@endif
|
|
|
|
<ul class="space-y-2 mb-6 flex-1 list-none p-0 m-0 text-[12.5px] text-ink-2">
|
|
<li class="flex items-baseline gap-2">
|
|
<span class="font-mono text-[12px] font-semibold text-ink">{{ $plan->press_release_quota }}</span>
|
|
<span>Pressemitteilungen / Monat</span>
|
|
</li>
|
|
@if ($plan->daily_limit !== null)
|
|
<li class="flex items-baseline gap-2">
|
|
<span class="font-mono text-[12px] font-semibold text-ink">{{ $plan->daily_limit }}</span>
|
|
<span>max. pro Tag</span>
|
|
</li>
|
|
@else
|
|
<li class="flex items-baseline gap-2 text-ink-3">
|
|
<span class="font-mono text-[12px]">∞</span>
|
|
<span>kein Tageslimit</span>
|
|
</li>
|
|
@endif
|
|
</ul>
|
|
|
|
<a href="{{ $pricingHref }}"
|
|
class="inline-flex items-center justify-center gap-1.5 w-full px-4 py-2.5 text-[12.5px] font-semibold rounded-[2px] transition-colors cursor-pointer
|
|
{{ $isPopular ? 'bg-brand text-white hover:bg-brand-deep' : 'border border-bg-rule-strong text-ink hover:bg-bg-elev' }}">
|
|
Auswählen
|
|
<svg width="11" height="11" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
|
<path d="M2 6h8M6 2l4 4-4 4" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
|
|
<div class="flex items-center justify-between gap-4 flex-wrap mt-5">
|
|
<p class="text-[12px] text-ink-3 m-0">
|
|
Alle Preise zzgl. MwSt. · Jederzeit kündbar · Auch ohne Abo als Einzelveröffentlichung möglich.
|
|
</p>
|
|
<a href="{{ $submitHref }}" class="inline-flex items-center gap-1.5 text-[12.5px] font-semibold text-brand hover:text-brand-deep transition-colors cursor-pointer whitespace-nowrap">
|
|
Direkt veröffentlichen
|
|
<svg width="11" height="11" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
|
<path d="M2 6h8M6 2l4 4-4 4" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
</section>
|
|
@endif
|