Files
ChatbotAI/resources/views/admin/dashboard.blade.php
2026-05-18 08:56:23 +08:00

222 lines
10 KiB
PHP

@extends('layouts.admin')
@section('title', 'Dashboard')
@section('breadcrumb')
<li class="breadcrumb-item active">Dashboard</li>
@endsection
@section('content')
<div class="d-flex align-items-center justify-content-between mb-4">
<h4 class="mb-0 fw-bold">Dashboard</h4>
<span class="text-muted small">{{ now()->format('d M Y, H:i') }}</span>
</div>
{{-- Status Perkhidmatan --}}
<div class="row g-3 mb-4">
<div class="col-md-6">
<div class="card border-0 shadow-sm">
<div class="card-body py-2 px-3">
<div class="d-flex align-items-center justify-content-between">
<span class="small fw-semibold text-muted">Ollama</span>
@if($health['ollama']['online'])
<span class="badge bg-success"><i class="bi bi-circle-fill me-1" style="font-size:.5rem"></i>Online</span>
@else
<span class="badge bg-danger"><i class="bi bi-circle-fill me-1" style="font-size:.5rem"></i>Offline</span>
@endif
</div>
@if($health['ollama']['online'])
<div class="d-flex gap-2 mt-1">
<span class="badge {{ $health['ollama']['chat_model'] ? 'bg-success-subtle text-success' : 'bg-warning-subtle text-warning' }} small">
Chat: {{ config('ollama.chat_model') }}
</span>
<span class="badge {{ $health['ollama']['embed_model'] ? 'bg-success-subtle text-success' : 'bg-warning-subtle text-warning' }} small">
Embed: {{ config('ollama.embedding_model') }}
</span>
</div>
@elseif($health['ollama']['error'])
<small class="text-danger">{{ $health['ollama']['error'] }}</small>
@endif
</div>
</div>
</div>
<div class="col-md-6">
<div class="card border-0 shadow-sm">
<div class="card-body py-2 px-3">
<div class="d-flex align-items-center justify-content-between">
<span class="small fw-semibold text-muted">Qdrant</span>
@if($health['qdrant']['online'])
<span class="badge bg-success"><i class="bi bi-circle-fill me-1" style="font-size:.5rem"></i>Online</span>
@else
<span class="badge bg-danger"><i class="bi bi-circle-fill me-1" style="font-size:.5rem"></i>Offline</span>
@endif
</div>
@if($health['qdrant']['online'])
<div class="mt-1">
<span class="badge bg-info-subtle text-info small">
{{ number_format($health['qdrant']['points_count'] ?? 0) }} vectors
</span>
</div>
@elseif($health['qdrant']['error'])
<small class="text-danger">{{ $health['qdrant']['error'] }}</small>
@endif
</div>
</div>
</div>
</div>
{{-- Stats Cards --}}
<div class="row g-3 mb-4">
<div class="col-sm-6 col-xl-3">
<div class="card border-0 shadow-sm">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between">
<div>
<div class="text-muted small">Dokumen Aktif</div>
<div class="fs-3 fw-bold text-primary">{{ $stats['active_documents'] }}</div>
<div class="text-muted small">dari {{ $stats['total_documents'] }} dokumen</div>
</div>
<i class="bi bi-file-pdf fs-1 text-primary opacity-25"></i>
</div>
</div>
</div>
</div>
<div class="col-sm-6 col-xl-3">
<div class="card border-0 shadow-sm">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between">
<div>
<div class="text-muted small">FAQ & Pengetahuan</div>
<div class="fs-3 fw-bold text-success">{{ $stats['total_knowledge_items'] }}</div>
<div class="text-muted small">item aktif</div>
</div>
<i class="bi bi-lightbulb fs-1 text-success opacity-25"></i>
</div>
</div>
</div>
</div>
<div class="col-sm-6 col-xl-3">
<div class="card border-0 shadow-sm">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between">
<div>
<div class="text-muted small">Chat Hari Ini</div>
<div class="fs-3 fw-bold text-info">{{ $stats['total_chats_today'] }}</div>
<div class="text-muted small">pertanyaan</div>
</div>
<i class="bi bi-chat-dots fs-1 text-info opacity-25"></i>
</div>
</div>
</div>
</div>
<div class="col-sm-6 col-xl-3">
<div class="card border-0 shadow-sm {{ $stats['flagged_chats'] > 0 ? 'border-warning' : '' }}">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between">
<div>
<div class="text-muted small">Perlu Semakan</div>
<div class="fs-3 fw-bold {{ $stats['flagged_chats'] > 0 ? 'text-warning' : 'text-muted' }}">
{{ $stats['flagged_chats'] }}
</div>
<div class="text-muted small">log ditanda</div>
</div>
<i class="bi bi-flag fs-1 text-warning opacity-25"></i>
</div>
</div>
</div>
</div>
</div>
{{-- Processing Status & Recent Activity --}}
<div class="row g-3">
<div class="col-lg-4">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom">
<h6 class="mb-0 fw-semibold">Status Pemprosesan</h6>
</div>
<div class="card-body">
@if($stats['processing_documents'] > 0)
<div class="d-flex align-items-center justify-content-between mb-2">
<span class="small">Sedang diproses</span>
<span class="badge bg-warning">{{ $stats['processing_documents'] }}</span>
</div>
@endif
@if($stats['failed_documents'] > 0)
<div class="d-flex align-items-center justify-content-between mb-2">
<span class="small text-danger">Gagal diproses</span>
<a href="{{ route('admin.documents.index', ['status' => 'failed']) }}"
class="badge bg-danger text-decoration-none">{{ $stats['failed_documents'] }}</a>
</div>
@endif
@if($stats['unanswered_chats'] > 0)
<div class="d-flex align-items-center justify-content-between mb-2">
<span class="small">Soalan tidak terjawab</span>
<a href="{{ route('admin.chat-feedback.index', ['has_answer' => 0]) }}"
class="badge bg-secondary text-decoration-none">{{ $stats['unanswered_chats'] }}</a>
</div>
@endif
@if($stats['processing_documents'] == 0 && $stats['failed_documents'] == 0)
<p class="text-muted small mb-0"><i class="bi bi-check-circle text-success me-1"></i>Semua dokumen diproses.</p>
@endif
</div>
</div>
<div class="card border-0 shadow-sm mt-3">
<div class="card-header bg-white border-bottom">
<h6 class="mb-0 fw-semibold">Chat Terkini</h6>
</div>
<ul class="list-group list-group-flush">
@forelse($recentChats as $chat)
<li class="list-group-item py-2 px-3">
<div class="text-truncate small fw-semibold">{{ $chat->question }}</div>
<div class="d-flex align-items-center gap-2 mt-1">
@if($chat->category)
<span class="badge bg-light text-dark border" style="font-size:.65rem">{{ $chat->category->name }}</span>
@endif
@if(!$chat->has_answer)
<span class="badge bg-warning-subtle text-warning border border-warning" style="font-size:.65rem">Tidak Terjawab</span>
@endif
<span class="text-muted ms-auto" style="font-size:.65rem">{{ $chat->created_at->diffForHumans() }}</span>
</div>
</li>
@empty
<li class="list-group-item py-3 text-center text-muted small">Tiada chat lagi.</li>
@endforelse
</ul>
</div>
</div>
<div class="col-lg-8">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom d-flex align-items-center justify-content-between">
<h6 class="mb-0 fw-semibold">Aktiviti Terkini</h6>
<a href="{{ route('admin.audit-logs.index') }}" class="btn btn-sm btn-link p-0 text-muted">
Lihat semua
</a>
</div>
<div class="table-responsive">
<table class="table table-sm table-hover mb-0">
<tbody>
@forelse($recentActivity as $log)
<tr>
<td class="ps-3 py-2">
<div class="small fw-semibold">{{ $log->description ?? $log->event }}</div>
@if($log->user)
<small class="text-muted">{{ $log->user->name }}</small>
@endif
</td>
<td class="text-end pe-3 py-2 text-muted small" style="white-space:nowrap">
{{ $log->created_at->diffForHumans() }}
</td>
</tr>
@empty
<tr><td colspan="2" class="text-center text-muted py-4 small">Tiada aktiviti.</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
@endsection