mivita/resources/views/admin/payment-dashboard/index.blade.php
Kevin 8e09aaefe8 Stripe-Integration (S7.4): Payment-Dashboard für Stripe
- Provider-Status/Uptime: Stripe-Kachel aktiviert; payment:check-uptime prüft
  zusätzlich api.stripe.com/v1/ (401 ohne Key = erreichbar) inkl. Auto-Incident
- Zahlungen: Anbieter-Filter, Provider-Badges, Umsatz je Provider,
  Stripe-Dashboard-Deep-Links (ShoppingPayment/PaymentTransaction::
  stripeDashboardUrl, pi_-Guard, testmodus-bewusst)
- Rohe Transaktionen: Anbieter-Filter/-Spalte, Erfolgsraten je Anbieter;
  Bugfix: Stringable-Vergleich ließ den txaction-Filter immer mit leerem Wert
  greifen — Liste war dauerhaft leer
- Neue Kachel „Abos je Anbieter" (Index + GF-Ansicht) mit Fehlerzählern und
  Stripe-Anteil-Fortschrittsbalken (Auslaufmodell PAYONE → Stripe ablesbar)
- Incident-Kachel weist Stripe/PAYONE getrennt aus; Log-Viewer mit
  Kanal-Umschalter stripe/payone
- Plan-Doku: S7.4-Umsetzungsstatus, Abo-Go-Live 2026-07-10 vermerkt

Tests: PaymentDashboardProviderTest (9 neu), Dashboard-Suite 49 grün.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 16:57:50 +00:00

146 lines
6.2 KiB
PHP

@extends('layouts.layout-2')
@section('content')
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show">
{{ session('success') }}
<button type="button" class="close" data-dismiss="alert">&times;</button>
</div>
@endif
<div class="d-flex justify-content-between align-items-center mb-3">
<div>
<h4 class="mb-0">
<i class="ion ion-md-alert text-danger"></i> Payment Monitor
</h4>
<small class="text-muted">Entwickler-Ansicht &mdash; {{ now()->format('d.m.Y H:i') }}</small>
</div>
<div>
<button type="button" class="btn btn-danger btn-sm" data-toggle="modal" data-target="#createIncidentModal">
<i class="ion ion-md-add"></i> Neuer Incident
</button>
</div>
</div>
{{-- Stat-Karten --}}
@include('admin.payment-dashboard._partials.stats-cards')
{{-- Anbieter-Status --}}
<div class="row mb-4">
@foreach($providerStats as $key => $provider)
@php $uptime = $uptimeStats[$key] ?? null; @endphp
<div class="col-sm-6 col-xl-3">
<div class="card {{ $provider['open_incidents'] > 0 ? 'border-danger' : '' }}">
<div class="card-body py-2 px-3">
<div class="d-flex justify-content-between align-items-center">
<strong>{{ $provider['label'] }}</strong>
<div>
@if($uptime && $uptime['last_check'])
@if($uptime['last_check']->is_up)
<span class="badge badge-success mr-1" title="Letzte Prüfung: {{ $uptime['last_check']->checked_at->diffForHumans() }}">
<i class="ion ion-md-checkmark"></i> Online
</span>
@else
<span class="badge badge-danger mr-1" title="{{ $uptime['last_check']->error_message }}">
<i class="ion ion-md-close"></i> Offline
</span>
@endif
@endif
@if($provider['open_incidents'] > 0)
<span class="badge badge-warning">{{ $provider['open_incidents'] }} Incident</span>
@endif
</div>
</div>
<div class="text-muted small mt-1">{{ $provider['total_30d'] }} Incidents (30 Tage)</div>
@if($uptime && $uptime['checks_24h'] > 0)
<div class="text-muted" style="font-size:0.7rem">
Uptime 24h: {{ $uptime['uptime_24h'] }}%
@if($uptime['failures_24h'] > 0)
&mdash; <span class="text-danger">{{ $uptime['failures_24h'] }} Ausfälle</span>
@endif
</div>
@elseif($uptime)
<div class="text-muted" style="font-size:0.7rem">Noch keine Uptime-Daten</div>
@endif
</div>
</div>
</div>
@endforeach
</div>
{{-- Abos je Provider (Auslauf-Fortschritt) --}}
@include('admin.payment-dashboard._partials.abo-provider-stats')
{{-- Tabs --}}
<ul class="nav nav-tabs" id="dashboardTabs">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" href="#tab-open">
Offene Incidents
@if($openIncidents->count() > 0)
<span class="badge badge-danger ml-1">{{ $openIncidents->count() }}</span>
@endif
</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#tab-all">Alle Incidents</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('admin.payment-dashboard.payments') }}">
<i class="ion ion-md-card"></i> Zahlungen &amp; Transaktionen
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('admin.payment-dashboard.transactions') }}">
<i class="ion ion-md-swap"></i> Rohe Transaktionen
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('admin.payment-dashboard.funnel') }}">
<i class="ion ion-md-funnel"></i> Funnel-Tracking
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('admin.payment-dashboard.abandoned') }}">
<i class="ion ion-md-alert"></i> Abbruch-Analyse
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('admin.payment-dashboard.logs') }}">
<i class="ion ion-md-list"></i> Provider-Logs
</a>
</li>
</ul>
<div class="tab-content">
{{-- Tab: Offene Incidents --}}
<div class="tab-pane fade show active pt-3" id="tab-open">
<div class="card">
<div class="card-body p-0">
@include('admin.payment-dashboard._partials.incident-table', [
'incidents' => $openIncidents,
'showActions' => true,
])
</div>
</div>
</div>
{{-- Tab: Alle Incidents --}}
<div class="tab-pane fade pt-3" id="tab-all">
<div class="card">
<div class="card-body p-0">
@include('admin.payment-dashboard._partials.incident-table', [
'incidents' => $allIncidents,
'showActions' => true,
])
</div>
</div>
<div class="mt-3">
{{ $allIncidents->links() }}
</div>
</div>
</div>
@include('admin.payment-dashboard._partials.create-incident-modal')
@endsection