Files
star-cloud/resources/views/admin/dashboard.blade.php
sky121113 682a9e7ac3
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 58s
[FEAT] 儀表板 UI 大改造、中文化與項目開發規範同步 (含深色模式修復)
2026-03-09 11:30:06 +08:00

131 lines
7.4 KiB
PHP

@extends('layouts.admin')
@section('content')
<div class="space-y-4 sm:space-y-6">
<!-- Grid -->
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-6">
<!-- Card -->
<div class="luxury-card rounded-2xl p-5 animate-luxury-in">
<div class="flex items-center gap-x-2">
<p class="text-xs font-semibold uppercase tracking-wider text-slate-400">
總營收 (餘額)
</p>
</div>
<div class="mt-2 flex items-baseline gap-x-2">
<h3 class="text-3xl font-bold text-slate-800 dark:text-white">${{ number_format($totalRevenue, 2) }}</h3>
<span class="text-xs font-medium text-cyan-500 bg-cyan-500/10 px-1.5 py-0.5 rounded">實時</span>
</div>
</div>
<!-- Card -->
<div class="luxury-card rounded-2xl p-5 animate-luxury-in" style="animation-delay: 100ms">
<div class="flex items-center gap-x-2">
<p class="text-xs font-semibold uppercase tracking-wider text-slate-400">
運作中機台
</p>
</div>
<div class="mt-2">
<h3 class="text-3xl font-bold text-slate-800 dark:text-white">{{ $activeMachines }} </h3>
</div>
</div>
<!-- Card -->
<div class="luxury-card rounded-2xl p-5 animate-luxury-in" style="animation-delay: 200ms">
<div class="flex items-center gap-x-2">
<p class="text-xs font-semibold uppercase tracking-wider text-slate-400">
待處理告警
</p>
</div>
<div class="mt-2">
<h3 class="text-3xl font-bold text-rose-500">{{ $alertsPending }} 則訊號</h3>
</div>
</div>
<!-- Card -->
<div class="luxury-card rounded-2xl p-5 animate-luxury-in" style="animation-delay: 300ms">
<div class="flex items-center gap-x-2">
<p class="text-xs font-semibold uppercase tracking-wider text-slate-400">
會員總數
</p>
</div>
<div class="mt-2 flex items-baseline gap-x-2">
<h3 class="text-3xl font-bold text-slate-800 dark:text-white">{{ number_format($memberCount) }}</h3>
<span class="text-xs font-medium text-emerald-500"></span>
</div>
</div>
</div>
<div class="grid lg:grid-cols-3 gap-6">
<!-- Chart Column -->
<div class="lg:col-span-2 luxury-card rounded-3xl p-6 animate-luxury-in" style="animation-delay: 400ms">
<div class="flex justify-between items-center mb-8">
<div>
<h2 class="text-lg font-bold text-slate-800 dark:text-white">營收績效分析</h2>
<p class="text-sm text-slate-400">各地區每日營收洞察</p>
</div>
<div x-data="{ open: false, selected: '最近 7 天' }" class="relative inline-block text-left">
<button @click="open = !open" type="button" class="btn-luxury-secondary">
<span x-text="selected"></span>
<svg class="shrink-0 w-4 h-4 transition-transform" :class="open ? 'rotate-180' : ''" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
</button>
<div x-show="open"
@click.away="open = false"
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
class="absolute right-0 mt-2 w-40 z-10 origin-top-right bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-xl shadow-xl p-1 focus:outline-none"
x-cloak>
<button @click="selected = '最近 7 天'; open = false" class="w-full text-left px-3 py-2 text-sm rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700/50 text-slate-700 dark:text-slate-300 transition-colors">最近 7 </button>
<button @click="selected = '最近 30 天'; open = false" class="w-full text-left px-3 py-2 text-sm rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700/50 text-slate-700 dark:text-slate-300 transition-colors">最近 30 </button>
<button @click="selected = '最近 90 天'; open = false" class="w-full text-left px-3 py-2 text-sm rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700/50 text-slate-700 dark:text-slate-300 transition-colors">最近 90 </button>
</div>
</div>
</div>
<div class="h-[300px] relative group overflow-hidden rounded-2xl bg-slate-50/50 dark:bg-slate-900/50 border border-slate-100 dark:border-slate-800 flex items-center justify-center transition-all">
<div class="absolute inset-0 bg-gradient-to-br from-cyan-500/5 to-transparent pointer-events-none"></div>
<div class="text-center">
<div class="inline-flex items-center justify-center w-12 h-12 rounded-full bg-white dark:bg-slate-800 shadow-sm border border-slate-200 dark:border-slate-700 mb-4">
<svg class="w-6 h-6 text-cyan-500" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><path d="m19 9-5 5-4-4-3 3"/></svg>
</div>
<p class="text-sm font-semibold text-slate-600 dark:text-slate-400">營收圖表數據載入中</p>
<p class="text-xs text-slate-400 mt-1">即時數據串流將在此顯示</p>
</div>
</div>
</div>
<!-- 即時動態 -->
<div class="luxury-card rounded-3xl p-6 animate-luxury-in" style="animation-delay: 500ms">
<h2 class="text-lg font-bold text-slate-800 dark:text-white mb-6">即時動態</h2>
<div class="space-y-6">
@forelse($latestActivities as $activity)
<div class="relative pl-6 before:absolute before:left-0 before:top-1 before:bottom-0 before:w-0.5 before:bg-slate-100 dark:before:bg-slate-800">
<div class="absolute left-[-4px] top-0 w-2.5 h-2.5 rounded-full {{ $activity->level === 'error' ? 'bg-rose-500' : 'bg-cyan-500' }} border-2 border-white dark:border-[#1e293b]"></div>
<p class="text-sm font-bold text-slate-700 dark:text-slate-200">#{{ $activity->machine->code ?? 'N/A' }} {{ $activity->content }}</p>
<p class="text-xs text-slate-400">{{ $activity->created_at->diffForHumans() }} {{ $activity->machine->location ?? '未知區域' }}</p>
</div>
@empty
<div class="text-center py-10">
<p class="text-sm text-slate-400">目前尚無動態資料</p>
</div>
@endforelse
</div>
<button class="btn-luxury-ghost w-full mt-8 py-3 font-bold uppercase tracking-wider">查看所有日誌 </button>
</div>
</div>
</div>
@endsection
@section('scripts')
<script>
window.addEventListener('load', () => {
// Here you would initialize charts using ApexCharts or similar,
// as Preline examples often use ApexCharts.
// For now, placeholders are sufficient.
});
</script>
@endsection