Files
dewemoji/app/resources/views/dashboard/index.blade.php
2026-02-12 00:52:40 +07:00

183 lines
8.1 KiB
PHP

@extends('dashboard.app')
@section('title', 'Dashboard')
@section('page_title', 'Dashboard Overview')
@section('page_subtitle', 'A shared layout with role-based navigation.')
@section('dashboard_content')
@php
$isAdmin = Gate::allows('admin');
$metrics = $overviewMetrics ?? [
'users_total' => 0,
'users_personal' => 0,
'subscriptions_active' => 0,
'subscriptions_total' => 0,
'webhook_total' => 0,
'webhook_errors' => 0,
];
$personalPct = $metrics['users_total'] > 0
? round(($metrics['users_personal'] / $metrics['users_total']) * 100)
: 0;
@endphp
<div class="grid gap-6 lg:grid-cols-3">
<div class="rounded-3xl glass-card p-6">
<div class="text-xs uppercase tracking-[0.25em] text-gray-400">Total users</div>
<div class="mt-3 text-3xl font-semibold text-white">{{ number_format($metrics['users_total']) }}</div>
<div class="mt-2 text-sm text-gray-400">{{ number_format($metrics['users_personal']) }} personal users</div>
<div class="mt-4 h-2 w-full overflow-hidden rounded-full bg-white/10">
<div class="h-full rounded-full bg-brand-ocean" style="width: {{ $personalPct }}%"></div>
</div>
</div>
<div class="rounded-3xl glass-card p-6">
<div class="text-xs uppercase tracking-[0.25em] text-gray-400">Active subscriptions</div>
<div class="mt-3 text-3xl font-semibold text-white">{{ number_format($metrics['subscriptions_active']) }}</div>
<div class="mt-2 text-sm text-gray-400">{{ number_format($metrics['subscriptions_total']) }} total subscriptions</div>
<div class="mt-4 flex items-center gap-2 text-sm text-brand-sun">
<span class="inline-flex h-2 w-2 rounded-full bg-brand-sun"></span>
{{ $metrics['subscriptions_active'] > 0 ? 'Live access enabled' : 'No active subs' }}
</div>
</div>
<div class="rounded-3xl glass-card p-6">
<div class="text-xs uppercase tracking-[0.25em] text-gray-400">Webhook events</div>
<div class="mt-3 text-3xl font-semibold text-white">{{ number_format($metrics['webhook_total']) }}</div>
<div class="mt-2 text-sm text-gray-400">{{ number_format($metrics['webhook_errors']) }} failures</div>
<div class="mt-4 flex items-center gap-2 text-sm text-gray-400">
<span class="inline-flex h-2 w-2 rounded-full {{ $metrics['webhook_errors'] > 0 ? 'bg-amber-400' : 'bg-emerald-400' }}"></span>
{{ $metrics['webhook_errors'] > 0 ? 'Needs review' : 'All clear' }}
</div>
</div>
</div>
<div class="mt-8">
<div class="rounded-3xl glass-card p-6">
<div class="flex items-center justify-between">
<div>
<div class="text-xs uppercase tracking-[0.25em] text-gray-400">Insights</div>
<div class="mt-2 text-xl font-semibold text-white">Usage highlights</div>
</div>
<span class="rounded-full border border-white/10 px-3 py-1 text-xs text-gray-300 theme-surface">Last 7 days</span>
</div>
<div class="mt-6 grid gap-4 md:grid-cols-2">
<div class="rounded-2xl theme-surface border border-white/10 p-4 shadow-sm">
<div class="text-sm font-semibold text-gray-200">Top search</div>
<div class="mt-2 text-2xl font-semibold text-white">"smile"</div>
<div class="mt-1 text-xs text-gray-400">14% of queries</div>
</div>
<div class="rounded-2xl theme-surface border border-white/10 p-4 shadow-sm">
<div class="text-sm font-semibold text-gray-200">Most used category</div>
<div class="mt-2 text-2xl font-semibold text-white">Smileys</div>
<div class="mt-1 text-xs text-gray-400">8,214 views</div>
</div>
</div>
<div class="mt-6 rounded-2xl border border-white/10 theme-surface p-4 shadow-sm">
<div class="text-xs uppercase tracking-[0.2em] text-gray-400">New users</div>
<div class="mt-2 text-sm text-gray-300">Last 7 days</div>
<div class="mt-4">
<div id="overview-users-chart" class="h-36"></div>
</div>
</div>
<div class="mt-4 grid gap-4 md:grid-cols-2">
<div class="rounded-2xl border border-white/10 theme-surface p-4 shadow-sm">
<div class="text-xs uppercase tracking-[0.2em] text-gray-400">Subscriptions</div>
<div class="mt-2 text-sm text-gray-300">Created last 7 days</div>
<div class="mt-3">
<div id="overview-subs-chart" class="h-28"></div>
</div>
</div>
<div class="rounded-2xl border border-white/10 theme-surface p-4 shadow-sm">
<div class="text-xs uppercase tracking-[0.2em] text-gray-400">Webhooks</div>
<div class="mt-2 text-sm text-gray-300">Events last 7 days</div>
<div class="mt-3">
<div id="overview-webhooks-chart" class="h-28"></div>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('scripts')
<script>
(() => {
const waitForApex = (cb) => {
if (window.ApexCharts) return cb();
let tries = 0;
const t = setInterval(() => {
if (window.ApexCharts) {
clearInterval(t);
cb();
return;
}
tries += 1;
if (tries > 50) {
clearInterval(t);
console.warn('ApexCharts not loaded.');
}
}, 100);
};
const root = document.documentElement;
const isDark = () => root.classList.contains('dark');
const palette = () => ({
text: isDark() ? '#e2e8f0' : '#334155',
grid: isDark() ? 'rgba(148,163,184,0.15)' : 'rgba(15,23,42,0.08)',
blue: isDark() ? '#60a5fa' : '#2563eb',
amber: isDark() ? '#f59e0b' : '#d97706',
mint: isDark() ? '#34d399' : '#10b981',
});
const labels = @json($chartLabels ?? []);
const users = @json($chartValues ?? []);
const subs = @json($chartSubs ?? []);
const webhooks = @json($chartWebhooks ?? []);
waitForApex(() => {
const colors = palette();
const base = {
chart: {
type: 'area',
sparkline: { enabled: true },
toolbar: { show: false },
animations: { enabled: true }
},
stroke: { curve: 'smooth', width: 2 },
fill: { opacity: 0.25 },
grid: { show: false },
tooltip: { theme: isDark() ? 'dark' : 'light' },
xaxis: { categories: labels },
yaxis: { show: false }
};
const usersEl = document.getElementById('overview-users-chart');
if (usersEl) {
new ApexCharts(usersEl, {
...base,
colors: [colors.blue],
series: [{ name: 'New users', data: users }]
}).render();
}
const subsEl = document.getElementById('overview-subs-chart');
if (subsEl) {
new ApexCharts(subsEl, {
...base,
colors: [colors.amber],
series: [{ name: 'Subscriptions', data: subs }]
}).render();
}
const webhooksEl = document.getElementById('overview-webhooks-chart');
if (webhooksEl) {
new ApexCharts(webhooksEl, {
...base,
colors: [colors.mint],
series: [{ name: 'Webhooks', data: webhooks }]
}).render();
}
});
})();
</script>
@endpush