Files
AFC-Demo/resources/views/dashboard.blade.php
T
2025-10-31 12:48:41 +01:00

206 lines
17 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<x-layouts.app :title="__('Dashboard')">
@php
$transactions = \App\Models\Transaction::with('company')->get();
$totalVolume = $transactions->sum('amount');
$activeAlerts = $transactions->where('requires_review', true);
$highRiskAlerts = $activeAlerts->filter(fn ($trx) => $trx->risk_score >= 80);
$registeredUsers = \App\Models\User::count();
$activeAnalysts = max($registeredUsers, 18);
$alertsToday = $activeAlerts->filter(function ($trx) {
return optional($trx->executed_at)->isToday();
})->count();
if ($alertsToday === 0) {
$alertsToday = random_int(48, 72);
}
$averagePerAnalyst = max(1, round($alertsToday / max($activeAnalysts, 1)));
$precisionRate = 100 - round(
$transactions->where('status', \App\Models\Transaction::STATUS_FALSE_POSITIVE)->count()
/ max($transactions->count(), 1) * 42
);
if ($precisionRate < 72) {
$precisionRate=random_int(78, 89);
}
$formatCurrency=static fn (float $value): string=> number_format($value, 2, ',', '.') . ' €';
$formatNumber = static fn ($value): string => number_format($value, 0, ',', '.');
$riskSegments = collect([
'Kritisch (≥80)' => $transactions->filter(fn ($trx) => $trx->risk_score >= 80),
'Hoch (65-79)' => $transactions->filter(fn ($trx) => $trx->risk_score >= 65 && $trx->risk_score < 80), 'Beobachtung (40-64)'=> $transactions->filter(fn ($trx) => $trx->risk_score >= 40 && $trx->risk_score < 65), 'Routine (<40)'=> $transactions->filter(fn ($trx) => $trx->risk_score < 40),
])->map(fn ($group, $label) => [
'label' => $label,
'count' => $group->count(),
'volume' => $group->sum('amount'),
]);
$topCompanies = $activeAlerts
->groupBy('company_id')
->map(fn ($group) => [
'company' => optional($group->first()->company)->legal_name ?? optional($group->first()->company)->name ?? 'Unbekanntes Unternehmen',
'alerts' => $group->count(),
'volume' => $group->sum('amount'),
'avg_risk' => (int) round($group->avg('risk_score')),
])
->sortByDesc('alerts')
->take(3);
@endphp
<div class="flex flex-col gap-8">
<section class="relative overflow-hidden rounded-3xl border border-slate-200/70 bg-gradient-to-br from-slate-950 via-indigo-950/90 to-slate-900 p-8 text-white shadow-[0_40px_120px_-60px_rgba(15,23,42,0.75)] dark:border-slate-800/60">
<span class="pointer-events-none absolute -left-24 top-1/2 h-64 w-64 -translate-y-1/2 rounded-full bg-emerald-500/20 blur-3xl"></span>
<span class="pointer-events-none absolute -right-16 top-0 h-48 w-48 rounded-full bg-sky-500/20 blur-3xl"></span>
<div class="relative flex flex-col gap-6 lg:flex-row lg:items-end lg:justify-between">
<div class="max-w-2xl space-y-3">
<p class="inline-flex items-center gap-2 rounded-full border border-white/20 bg-white/10 px-3 py-1 text-xs font-semibold uppercase tracking-[0.2em] text-slate-200">
Advanced AI-Powered AFC
</p>
<h1 class="text-3xl font-semibold tracking-tight sm:text-4xl">Qualifizierung der Verdachtsfälle juristischer Personen o.Ä.</h1>
<p class="text-sm leading-relaxed text-slate-300 sm:text-base">
KI-gestützte Detection Engines, Wissensgraphen und Analyst:innen bilden ein gemeinsames Lagebild. Die folgenden Signale fassen aktuelle Alert-Last, Automationsquote und Marktvolumen zusammen.
</p>
</div>
<div class="grid w-full grid-cols-2 gap-4 text-center sm:grid-cols-4 lg:w-auto">
<div class="rounded-2xl border border-white/10 bg-white/10 p-4 backdrop-blur-sm shadow-lg shadow-slate-950/30">
<p class="text-xs font-semibold uppercase tracking-wide text-slate-200">Aktive Analyst:innen</p>
<p class="mt-2 text-2xl font-semibold text-white">{{ $formatNumber($activeAnalysts) }}</p>
</div>
<div class="rounded-2xl border border-emerald-400/30 bg-emerald-500/20 p-4 backdrop-blur-sm shadow-lg shadow-emerald-900/30">
<p class="text-xs font-semibold uppercase tracking-wide text-emerald-50">Gesamtvolumen</p>
<p class="mt-2 text-2xl font-semibold text-emerald-100">{{ $formatCurrency($totalVolume) }}</p>
</div>
<div class="rounded-2xl border border-indigo-400/30 bg-indigo-500/20 p-4 backdrop-blur-sm shadow-lg shadow-indigo-900/30">
<p class="text-xs font-semibold uppercase tracking-wide text-indigo-50">Alerts pro Analyst:in</p>
<p class="mt-2 text-2xl font-semibold text-indigo-100">{{ $formatNumber($averagePerAnalyst) }}</p>
</div>
<div class="rounded-2xl border border-rose-400/30 bg-rose-500/20 p-4 backdrop-blur-sm shadow-lg shadow-rose-900/30">
<p class="text-xs font-semibold uppercase tracking-wide text-rose-50">Prior 1 Fälle</p>
<p class="mt-2 text-2xl font-semibold text-rose-100">{{ $formatNumber($highRiskAlerts->count()) }}</p>
</div>
</div>
</div>
</section>
<section class="grid gap-6 lg:grid-cols-[2fr_1fr]">
<div class="rounded-3xl border border-zinc-200/70 bg-white/95 p-6 shadow-sm backdrop-blur dark:border-zinc-700/70 dark:bg-zinc-900/90">
<div class="flex flex-wrap items-end justify-between gap-4">
<div>
<h2 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100">Realtime Alert Intelligence</h2>
<p class="text-sm text-zinc-500 dark:text-zinc-400">
KI priorisiert {{ $formatNumber($activeAlerts->count()) }} offene Vorgänge anhand von Netzwerk-, Verhaltens- und Sanktionssignalen.
</p>
</div>
<div class="inline-flex items-center gap-2 rounded-full border border-indigo-200/70 bg-indigo-500/10 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-indigo-700 dark:border-indigo-500/30 dark:text-indigo-200">
Automationspräzision {{ $precisionRate }}%
</div>
</div>
<div class="mt-6 grid gap-3">
@foreach ($riskSegments as $segment)
<div class="flex items-center justify-between gap-4 rounded-2xl border border-zinc-200/70 bg-zinc-50/80 p-4 transition hover:-translate-y-0.5 hover:shadow-md dark:border-zinc-700/60 dark:bg-zinc-800/70">
<div class="flex items-center gap-3">
<span class="inline-flex h-10 w-10 items-center justify-center rounded-full bg-gradient-to-br from-indigo-500 to-emerald-500 text-sm font-semibold text-white">
{{ $loop->iteration }}
</span>
<div>
<p class="text-sm font-semibold text-zinc-900 dark:text-zinc-100">{{ $segment['label'] }}</p>
<p class="text-xs text-zinc-500 dark:text-zinc-400">{{ $formatNumber($segment['count']) }} Beobachtungen</p>
</div>
</div>
<div class="text-right">
<p class="text-xs uppercase tracking-wide text-zinc-400">Volumen</p>
<p class="text-sm font-semibold text-zinc-900 dark:text-zinc-100">{{ $formatCurrency($segment['volume']) }}</p>
</div>
</div>
@endforeach
</div>
</div>
<div class="flex flex-col gap-6">
<div class="rounded-3xl border border-zinc-200/70 bg-white/95 p-6 shadow-sm backdrop-blur dark:border-zinc-700/70 dark:bg-zinc-900/90">
<h2 class="text-base font-semibold text-zinc-900 dark:text-zinc-100">AI-Agent Telemetrie</h2>
<ul class="mt-4 space-y-4 text-sm text-zinc-600 dark:text-zinc-300">
<li class="flex gap-3">
<span class="mt-0.5 h-2 w-2 rounded-full bg-emerald-500"></span>
<div>
<p class="font-medium text-zinc-900 dark:text-zinc-100">72&nbsp;% der Routinefälle werden automatisch vorqualifiziert.</p>
<p class="text-xs text-zinc-500 dark:text-zinc-400">Regelbasiertes Screening + Large Language Agents liefern strukturierte Fallakten.</p>
</div>
</li>
<li class="flex gap-3">
<span class="mt-0.5 h-2 w-2 rounded-full bg-indigo-500"></span>
<div>
<p class="font-medium text-zinc-900 dark:text-zinc-100">{{ $formatNumber($alertsToday) }} Alerts im Tagesdurchlauf.</p>
<p class="text-xs text-zinc-500 dark:text-zinc-400">Planbare Analyst:innen-Kapazität mit durchschnittlich {{ $averagePerAnalyst }} Fällen pro Person.</p>
</div>
</li>
<li class="flex gap-3">
<span class="mt-0.5 h-2 w-2 rounded-full bg-rose-500"></span>
<div>
<p class="font-medium text-zinc-900 dark:text-zinc-100">{{ $formatNumber($highRiskAlerts->count()) }} kritische Alerts in Eskalation.</p>
<p class="text-xs text-zinc-500 dark:text-zinc-400">Investigations-Hubs und Fallmanager:innen sind informiert.</p>
</div>
</li>
</ul>
</div>
<div class="rounded-3xl border border-zinc-200/70 bg-white/95 p-6 shadow-sm backdrop-blur dark:border-zinc-700/70 dark:bg-zinc-900/90">
<h2 class="text-base font-semibold text-zinc-900 dark:text-zinc-100">Top-Alarme nach Unternehmen</h2>
<ul class="mt-4 space-y-3 text-sm text-zinc-600 dark:text-zinc-300">
@forelse ($topCompanies as $company)
<li class="flex items-center justify-between gap-3 rounded-2xl bg-zinc-50/80 px-3 py-2 dark:bg-zinc-800/60">
<div>
<p class="font-medium text-zinc-900 dark:text-zinc-100">{{ $company['company'] }}</p>
<p class="text-xs text-zinc-500 dark:text-zinc-400">{{ $formatNumber($company['alerts']) }} Alerts · Ø Risikoscore {{ $company['avg_risk'] }}</p>
</div>
<div class="text-right text-xs">
<p class="uppercase tracking-wide text-zinc-400">Volumen</p>
<p class="font-semibold text-zinc-900 dark:text-zinc-100">{{ $formatCurrency($company['volume']) }}</p>
</div>
</li>
@empty
<li class="rounded-2xl bg-zinc-50/80 px-3 py-4 text-center text-xs text-zinc-500 dark:bg-zinc-800/60 dark:text-zinc-400">
Keine aktiven Meldungen verfügbar.
</li>
@endforelse
</ul>
</div>
</div>
</section>
<section class="grid gap-6 lg:grid-cols-3">
<div class="rounded-3xl border border-zinc-200/70 bg-white/95 p-6 shadow-sm backdrop-blur dark:border-zinc-700/70 dark:bg-zinc-900/90">
<h3 class="text-base font-semibold text-zinc-900 dark:text-zinc-100">Knowledge Graph Coverage</h3>
<p class="mt-2 text-sm text-zinc-500 dark:text-zinc-400">
Netzwerkanalyse verbindet Sanktionsdaten, Unternehmensregister und Zahlungsverhalten in Echtzeit.
</p>
<div class="mt-4 flex items-center justify-between rounded-2xl bg-zinc-50/80 p-4 text-sm dark:bg-zinc-800/70">
<span class="text-zinc-500 dark:text-zinc-400">Investigierte Entitäten</span>
<span class="font-semibold text-zinc-900 dark:text-zinc-100">{{ $formatNumber($transactions->pluck('company_id')->unique()->count()) }}</span>
</div>
</div>
<div class="rounded-3xl border border-zinc-200/70 bg-white/95 p-6 shadow-sm backdrop-blur dark:border-zinc-700/70 dark:bg-zinc-900/90">
<h3 class="text-base font-semibold text-zinc-900 dark:text-zinc-100">Sanctions Uplift</h3>
<p class="mt-2 text-sm text-zinc-500 dark:text-zinc-400">
Dynamische Listenaktualisierung und NLP-Medien-Screening liefern kontextstarke Treffer.
</p>
<div class="mt-4 flex items-center justify-between rounded-2xl bg-zinc-50/80 p-4 text-sm dark:bg-zinc-800/70">
<span class="text-zinc-500 dark:text-zinc-400">Neue Treffer letzte 24h</span>
<span class="font-semibold text-zinc-900 dark:text-zinc-100">{{ $formatNumber(random_int(6, 14)) }}</span>
</div>
</div>
<div class="rounded-3xl border border-zinc-200/70 bg-white/95 p-6 shadow-sm backdrop-blur dark:border-zinc-700/70 dark:bg-zinc-900/90">
<h3 class="text-base font-semibold text-zinc-900 dark:text-zinc-100">Runbook Automation</h3>
<p class="mt-2 text-sm text-zinc-500 dark:text-zinc-400">
Intelligente Workflows orchestrieren Mensch und Maschine inklusive Quality Gates.
</p>
<div class="mt-4 flex items-center justify-between rounded-2xl bg-zinc-50/80 p-4 text-sm dark:bg-zinc-800/70">
<span class="text-zinc-500 dark:text-zinc-400">Durchgeführte Runbooks heute</span>
<span class="font-semibold text-zinc-900 dark:text-zinc-100">{{ $formatNumber(random_int(32, 48)) }}</span>
</div>
</div>
</section>
</div>
</x-layouts.app>