Incentive (E1): Bilder je Incentive, Teaser mit Call to Action oben, Praemie je Teampartner statt Punkte

Titelbild und Galerie liegen jetzt in public/img/incentive/<slug>/, der
Hauptordner ist nur noch Fallback fuers Titelbild. Damit erscheinen die
Montenegro-Impressionen nicht mehr unter der Challenge; die Fotos sind in
montenegro-incentive-2026/ verschoben.

Teaser: Call to Action "Bist du bereit fuer die Challenge?" mit Button ganz
oben. Bei Geldpraemie zeigen die Kacheln "Deine Praemie" (50 EUR je neuem
Teampartner) und "Top 3 Bonus" statt Incentive-Punkte, darunter der Abschnitt
"So funktioniert die Challenge". Rangliste: Button "Jetzt teilnehmen" wieder
in der Sekundaerfarbe.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Kevin 2026-09-22 12:37:58 +00:00
parent 9879e6798e
commit 186398a476
20 changed files with 278 additions and 135 deletions

View file

@ -199,7 +199,7 @@ return [
'payout_incl_bonus' => 'inkl. :amount Rang-Bonus',
'payout_so_far' => 'Deine Prämie bisher',
'payout_tile_title' => 'Deine Prämie',
'payout_per_partner_label' => 'je direkt gesponsertem Neupartner mit Starterpaket',
'payout_per_partner_label' => 'je neuem Teampartner mit Starterpaket',
'payout_per_partner_text' => 'Prämie: :amount je direkt gesponsertem Neupartner mit Starterpaket.',
'payout_rank_bonus_label' => 'Zusatz-Bonus für Platz :n',
'payout_top_bonus_title' => 'Zusatz-Bonus für die Top :n',
@ -222,4 +222,6 @@ return [
'join_highlight_points' => ':points Punkte je neuem Partner',
'join_highlight_abo' => ':points Punkte je Kundenabo',
'section_info' => 'Alles zur Challenge',
'section_how_it_works' => 'So funktioniert die Challenge',
'payout_bonus_tile_title' => 'Top :n Bonus',
];

View file

@ -199,7 +199,7 @@ return [
'payout_incl_bonus' => 'incl. :amount rank bonus',
'payout_so_far' => 'Your reward so far',
'payout_tile_title' => 'Your reward',
'payout_per_partner_label' => 'per directly sponsored new partner with a starter kit',
'payout_per_partner_label' => 'per new team partner with a starter kit',
'payout_per_partner_text' => 'Reward: :amount per directly sponsored new partner with a starter kit.',
'payout_rank_bonus_label' => 'Extra bonus for rank :n',
'payout_top_bonus_title' => 'Extra bonus for the top :n',
@ -222,4 +222,6 @@ return [
'join_highlight_points' => ':points points per new partner',
'join_highlight_abo' => ':points points per customer subscription',
'section_info' => 'All about the challenge',
'section_how_it_works' => 'How the challenge works',
'payout_bonus_tile_title' => 'Top :n bonus',
];

View file

@ -199,7 +199,7 @@ return [
'payout_incl_bonus' => 'incl. :amount bono por puesto',
'payout_so_far' => 'Tu prima hasta ahora',
'payout_tile_title' => 'Tu prima',
'payout_per_partner_label' => 'por nuevo socio patrocinado directamente con paquete de inicio',
'payout_per_partner_label' => 'por nuevo socio de equipo con paquete de inicio',
'payout_per_partner_text' => 'Prima: :amount por nuevo socio patrocinado directamente con paquete de inicio.',
'payout_rank_bonus_label' => 'Bono adicional para el puesto :n',
'payout_top_bonus_title' => 'Bono adicional para el top :n',
@ -222,4 +222,6 @@ return [
'join_highlight_points' => ':points puntos por nuevo socio',
'join_highlight_abo' => ':points puntos por suscripción de cliente',
'section_info' => 'Todo sobre el reto',
'section_how_it_works' => 'Así funciona el reto',
'payout_bonus_tile_title' => 'Bono top :n',
];

View file

@ -174,7 +174,7 @@ return [
'payout_incl_bonus' => 'dont :amount de bonus de classement',
'payout_so_far' => 'Ta prime jusqu’ici',
'payout_tile_title' => 'Ta prime',
'payout_per_partner_label' => 'par nouveau partenaire parrainé directement avec kit de démarrage',
'payout_per_partner_label' => 'par nouveau partenaire d’équipe avec kit de démarrage',
'payout_per_partner_text' => 'Prime : :amount par nouveau partenaire parrainé directement avec kit de démarrage.',
'payout_rank_bonus_label' => 'Bonus supplémentaire pour la place :n',
'payout_top_bonus_title' => 'Bonus supplémentaire pour le top :n',
@ -197,4 +197,6 @@ return [
'join_highlight_points' => ':points points par nouveau partenaire',
'join_highlight_abo' => ':points points par abonnement client',
'section_info' => 'Tout sur le challenge',
'section_how_it_works' => 'Comment fonctionne le challenge',
'payout_bonus_tile_title' => 'Bonus top :n',
];

View file

@ -21,7 +21,7 @@
{{-- Hero-Bild mit Overlay --}}
@if ($activeIncentive->image)
<div class="inc-dash-hero">
<img src="{{ asset('img/incentive/' . $activeIncentive->image) }}" alt="{{ $activeIncentive->name }}">
<img src="{{ asset($activeIncentive->heroImagePath()) }}" alt="{{ $activeIncentive->name }}">
<div class="inc-dash-hero-overlay"></div>
<div class="inc-dash-hero-content">
<span class="inc-dash-badge">
@ -110,22 +110,7 @@
@endif
{{-- Bilder-Leiste --}}
@php
$dashGallery = [];
$galleryDir = public_path('img/incentive');
if (is_dir($galleryDir)) {
$galleryFiles = glob($galleryDir . '/*.{jpg,jpeg,png,webp}', GLOB_BRACE) ?: [];
$heroImg = $activeIncentive->image;
foreach ($galleryFiles as $gf) {
$bn = basename($gf);
if ($bn !== $heroImg) {
$dashGallery[] = 'img/incentive/' . $bn;
}
}
sort($dashGallery);
$dashGallery = array_slice($dashGallery, 0, 4);
}
@endphp
@php $dashGallery = array_slice($activeIncentive->galleryImages(), 0, 4); @endphp
@if (count($dashGallery) > 0)
<div class="inc-dash-gallery">
@foreach ($dashGallery as $gi)

View file

@ -169,8 +169,21 @@
}
.inc-join-form .btn-participate {
background: #d7d700;
color: #333;
border: none;
border-radius: 50px;
font-size: 1.05rem;
font-weight: 800;
padding: .7rem 1.5rem;
transition: transform .2s, box-shadow .2s;
}
.inc-join-form .btn-participate:hover {
background: #e8e800;
color: #333;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
}
.inc-join-hint {
@ -719,7 +732,7 @@
@if ($incentive->image)
<div class="inc-hero-img mb-4">
<img src="{{ asset('img/incentive/' . $incentive->image) }}" alt="{{ $incentive->name }}">
<img src="{{ asset($incentive->heroImagePath()) }}" alt="{{ $incentive->name }}">
<div class="hero-gradient"></div>
</div>
@endif
@ -998,7 +1011,7 @@
@if ($incentive->image)
<div class="inc-hero-img mb-4">
<img src="{{ asset('img/incentive/' . $incentive->image) }}" alt="{{ $incentive->name }}"
<img src="{{ asset($incentive->heroImagePath()) }}" alt="{{ $incentive->name }}"
style="max-height: 450px;">
<div class="hero-gradient"></div>
</div>

View file

@ -3,7 +3,7 @@
@section('styles')
<style>
.incentive-hero {
margin: -1.5rem -1.5rem 0 -1.5rem;
margin: 0 -1.5rem 0 -1.5rem;
position: relative;
overflow: hidden;
min-height: 520px;
@ -442,10 +442,51 @@
@section('content')
{{-- ===== CTA-BEREICH ===== --}}
<div class="cta-banner mb-4" id="incentive-teaser-cta">
@if ($participant && $participant->accepted_terms_at)
<div class="cta-status-icon cta-status-icon-success">
<i class="ion ion-md-checkmark-circle"></i>
</div>
<h3>{{ __('incentive.you_participate') }}</h3>
<p class="mb-4">{{ __('incentive.teaser_cta_already_in') }}</p>
<a href="{{ route('user_incentive_show', [$incentive->slug]) }}" class="btn btn-secondary btn-lg mr-2">
<i class="ion ion-md-list mr-1"></i>{{ __('incentive.teaser_cta_to_ranking') }}
</a>
<a href="{{ route('user_incentive_details', [$incentive->slug]) }}" class="btn btn-outline-secondary btn-lg">
<i class="ion ion-md-stats mr-1"></i>{{ __('incentive.my_details') }}
</a>
@elseif ($participant)
<div class="cta-status-icon cta-status-icon-warning">
<i class="ion ion-md-trophy"></i>
</div>
<h3>{{ __('incentive.teaser_pending_title') }}</h3>
<p class="mb-4">{{ __('incentive.teaser_pending_text') }}</p>
<a href="{{ route('user_incentive_show', [$incentive->slug]) }}" class="btn btn-secondary btn-lg">
<i class="ion ion-md-checkmark mr-1"></i>{{ __('incentive.teaser_cta_confirm') }}
</a>
@elseif($incentive->isActive())
<div class="cta-status-icon cta-status-icon-warning">
<i class="ion ion-md-trophy"></i>
</div>
<h3>{{ __('incentive.teaser_cta_ready') }}</h3>
<p class="mb-4">{{ __('incentive.teaser_cta_text', ['n' => $incentive->max_winners]) }}</p>
<a href="{{ route('user_incentive_show', [$incentive->slug]) }}" class="btn btn-secondary btn-lg">
<i class="ion ion-md-checkmark mr-1"></i>{{ __('incentive.teaser_cta_button') }}
</a>
@else
<div class="cta-status-icon cta-status-icon-muted">
<i class="ion ion-md-time"></i>
</div>
<h3>{{ __('incentive.teaser_cta_coming_soon') }}</h3>
<p class="mb-0">{{ __('incentive.not_active') }}</p>
@endif
</div>
{{-- ===== HERO ===== --}}
@if ($incentive->image)
<div class="incentive-hero mb-5">
<img src="{{ asset('img/incentive/' . $incentive->image) }}" alt="{{ $incentive->name }}">
<img src="{{ asset($incentive->heroImagePath()) }}" alt="{{ $incentive->name }}">
<div class="hero-overlay"></div>
<div class="hero-content">
<span class="hero-badge">
@ -530,7 +571,7 @@
<span class="tile-label">{{ __('incentive.payout_per_partner_label') }}</span>
</div>
@endif
@if ($incentive->rankBonuses() !== [])
@if ($incentive->rankBonuses() !== [] && !$incentive->ranksByPartnerCount())
<div>
<span class="tile-label d-block mb-1">{{ __('incentive.payout_top_bonus_title', ['n' => count($incentive->rankBonuses())]) }}</span>
@foreach ($incentive->rankBonuses() as $bonusRank => $bonusAmount)
@ -564,6 +605,27 @@
</div>
@endif
@if ($incentive->hasCashPayout() && $incentive->ranksByPartnerCount())
{{-- Top 3 Bonus (Recruiting-Challenge) --}}
<div class="col-md-4">
<div class="card info-tile h-100 shadow-sm" id="incentive-bonus-tile">
<div class="card-body text-center py-4">
<div class="tile-icon tile-icon-star">
<i class="ion ion-md-trophy"></i>
</div>
<h5 class="font-weight-bold mb-3">{{ __('incentive.payout_bonus_tile_title', ['n' => max(count($incentive->rankBonuses()), $incentive->max_winners)]) }}</h5>
@forelse ($incentive->rankBonuses() as $bonusRank => $bonusAmount)
<div class="mb-2">
<span class="tile-value" style="color: #6b7758;">{{ \App\Services\Incentive\IncentivePayoutService::formatAmount($bonusAmount) }}</span>
<span class="tile-label d-block">{{ __('incentive.payout_rank_label', ['n' => $bonusRank]) }}</span>
</div>
@empty
<span class="tile-label d-block">{{ __('incentive.ranking_winners_hint', ['n' => $incentive->max_winners]) }}</span>
@endforelse
</div>
</div>
</div>
@else
{{-- Punkte-System --}}
<div class="col-md-4">
<div class="card info-tile h-100 shadow-sm">
@ -593,57 +655,89 @@
</div>
</div>
@endif
{{-- ===== PUNKTE-DETAIL ===== --}}
<div class="points-section mb-5">
<h4 class="points-heading">
<i class="ion ion-md-star text-warning mr-1"></i>
{{ __('incentive.section_points') }}
</h4>
<div class="row">
<div class="{{ $incentive->usesAbos() ? 'col-md-6 mb-3 mb-md-0' : 'col-md-12' }}">
<div class="point-card point-card-partner">
<h6 class="font-weight-bold mb-2">
<i class="ion ion-md-person-add mr-1"></i>
{{ __('incentive.points_partners_title') }}
</h6>
<div class="point-value">
{{ number_format($incentive->points_partner_onetime, 0, ',', '.') }}
<span class="small font-weight-normal">{{ __('incentive.points_short') }}</span>
{{-- ===== SO FUNKTIONIERT DIE CHALLENGE (Geldpraemie) / PUNKTE-DETAIL ===== --}}
@if ($incentive->hasCashPayout() && $incentive->ranksByPartnerCount())
<div class="points-section mb-5" id="incentive-how-it-works">
<h4 class="points-heading">
<i class="ion ion-md-cash text-warning mr-1"></i>
{{ __('incentive.section_how_it_works') }}
</h4>
<div class="row">
<div class="col-md-12">
<div class="point-card point-card-partner">
<h6 class="font-weight-bold mb-2">
<i class="ion ion-md-person-add mr-1"></i>
{{ __('incentive.payout_tile_title') }}
</h6>
<div class="point-value">
{{ \App\Services\Incentive\IncentivePayoutService::formatAmount((float) $incentive->amount_per_partner) }}
<span class="small font-weight-normal">{{ __('incentive.payout_per_partner_label') }}</span>
</div>
<ul>
<li>{{ __('incentive.points_starter_package_label') }}</li>
@if ($incentive->rankBonuses() !== [])
<li>{{ __('incentive.payout_top_bonus_text', ['n' => count($incentive->rankBonuses()), 'list' => collect($incentive->rankBonuses())->map(fn ($amount, $rank) => __('incentive.payout_rank_label', ['n' => $rank]).' '.\App\Services\Incentive\IncentivePayoutService::formatAmount($amount))->implode(', ')]) }}</li>
@endif
<li>{{ __('incentive.payout_ranking_hint') }}</li>
</ul>
</div>
<ul>
<li>{{ __('incentive.teaser_partner_onetime_text') }}</li>
<li>{{ __('incentive.points_starter_package_label') }}</li>
@if ($incentive->includesSalesPoints())
<li>{{ __('incentive.points_partner_boost') }}</li>
@endif
@include('user.incentive._payout_bullets', ['incentive' => $incentive])
</ul>
</div>
</div>
@if ($incentive->usesAbos())
<div class="col-md-6">
<div class="point-card point-card-abo">
<h6 class="font-weight-bold mb-2">
<i class="ion ion-md-ribbon mr-1"></i>
{{ __('incentive.points_abos_title') }}
</h6>
<div class="point-value">
{{ number_format($incentive->points_abo_onetime, 0, ',', '.') }}
<span class="small font-weight-normal">{{ __('incentive.points_short') }}</span>
</div>
<ul>
<li>{{ __('incentive.teaser_abo_onetime_text') }}</li>
<li>{{ __('incentive.points_abo_direct') }}</li>
@if ($incentive->includesSalesPoints())
<li>{{ __('incentive.points_abo_boost') }}</li>
@endif
</ul>
</div>
</div>
@endif
</div>
</div>
@else
{{-- ===== PUNKTE-DETAIL ===== --}}
<div class="points-section mb-5">
<h4 class="points-heading">
<i class="ion ion-md-star text-warning mr-1"></i>
{{ __('incentive.section_points') }}
</h4>
<div class="row">
<div class="{{ $incentive->usesAbos() ? 'col-md-6 mb-3 mb-md-0' : 'col-md-12' }}">
<div class="point-card point-card-partner">
<h6 class="font-weight-bold mb-2">
<i class="ion ion-md-person-add mr-1"></i>
{{ __('incentive.points_partners_title') }}
</h6>
<div class="point-value">
{{ number_format($incentive->points_partner_onetime, 0, ',', '.') }}
<span class="small font-weight-normal">{{ __('incentive.points_short') }}</span>
</div>
<ul>
<li>{{ __('incentive.teaser_partner_onetime_text') }}</li>
<li>{{ __('incentive.points_starter_package_label') }}</li>
@if ($incentive->includesSalesPoints())
<li>{{ __('incentive.points_partner_boost') }}</li>
@endif
@include('user.incentive._payout_bullets', ['incentive' => $incentive])
</ul>
</div>
</div>
@if ($incentive->usesAbos())
<div class="col-md-6">
<div class="point-card point-card-abo">
<h6 class="font-weight-bold mb-2">
<i class="ion ion-md-ribbon mr-1"></i>
{{ __('incentive.points_abos_title') }}
</h6>
<div class="point-value">
{{ number_format($incentive->points_abo_onetime, 0, ',', '.') }}
<span class="small font-weight-normal">{{ __('incentive.points_short') }}</span>
</div>
<ul>
<li>{{ __('incentive.teaser_abo_onetime_text') }}</li>
<li>{{ __('incentive.points_abo_direct') }}</li>
@if ($incentive->includesSalesPoints())
<li>{{ __('incentive.points_abo_boost') }}</li>
@endif
</ul>
</div>
</div>
@endif
</div>
</div>
@endif
{{-- ===== BILDERGALERIE ===== --}}
@if (count($galleryImages) > 0)
@ -670,47 +764,6 @@
</div>
@endif
{{-- ===== CTA-BEREICH ===== --}}
<div class="cta-banner mb-5">
@if ($participant && $participant->accepted_terms_at)
<div class="cta-status-icon cta-status-icon-success">
<i class="ion ion-md-checkmark-circle"></i>
</div>
<h3>{{ __('incentive.you_participate') }}</h3>
<p class="mb-4">{{ __('incentive.teaser_cta_already_in') }}</p>
<a href="{{ route('user_incentive_show', [$incentive->slug]) }}" class="btn btn-secondary btn-lg mr-2">
<i class="ion ion-md-list mr-1"></i>{{ __('incentive.teaser_cta_to_ranking') }}
</a>
<a href="{{ route('user_incentive_details', [$incentive->slug]) }}" class="btn btn-outline-secondary btn-lg">
<i class="ion ion-md-stats mr-1"></i>{{ __('incentive.my_details') }}
</a>
@elseif ($participant)
<div class="cta-status-icon cta-status-icon-warning">
<i class="ion ion-md-trophy"></i>
</div>
<h3>{{ __('incentive.teaser_pending_title') }}</h3>
<p class="mb-4">{{ __('incentive.teaser_pending_text') }}</p>
<a href="{{ route('user_incentive_show', [$incentive->slug]) }}" class="btn btn-secondary btn-lg">
<i class="ion ion-md-checkmark mr-1"></i>{{ __('incentive.teaser_cta_confirm') }}
</a>
@elseif($incentive->isActive())
<div class="cta-status-icon cta-status-icon-warning">
<i class="ion ion-md-trophy"></i>
</div>
<h3>{{ __('incentive.teaser_cta_ready') }}</h3>
<p class="mb-4">{{ __('incentive.teaser_cta_text', ['n' => $incentive->max_winners]) }}</p>
<a href="{{ route('user_incentive_show', [$incentive->slug]) }}" class="btn btn-secondary btn-lg">
<i class="ion ion-md-checkmark mr-1"></i>{{ __('incentive.teaser_cta_button') }}
</a>
@else
<div class="cta-status-icon cta-status-icon-muted">
<i class="ion ion-md-time"></i>
</div>
<h3>{{ __('incentive.teaser_cta_coming_soon') }}</h3>
<p class="mb-0">{{ __('incentive.not_active') }}</p>
@endif
</div>
{{-- ===== TEILNAHMEBEDINGUNGEN (Collapse) ===== --}}
@if ($incentive->getLang('terms'))
<div class="card terms-toggle mb-4">