Files
ismysiteup.online/resources/views/dashboard/show.blade.php
T

231 lines
7.9 KiB
PHP
Raw Normal View History

2026-01-17 13:46:20 +02:00
@extends('layouts.app')
@section('title', $site->name . ' Dashboard')
@section('content')
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h1><i class="bi bi-bar-chart"></i> {{ $site->name }}</h1>
<p class="text-muted mb-0">
<i class="bi bi-link-45deg"></i> <a href="{{ $site->url }}" target="_blank">{{ $site->url }}</a>
</p>
</div>
<a href="{{ route('sites.index') }}" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left"></i> Back to Sites
</a>
</div>
<!-- Stats Cards -->
<div class="row mb-4">
<div class="col-md-4">
<div class="card text-white bg-primary">
<div class="card-body">
<h6 class="card-title">Uptime</h6>
<h2 class="mb-0">{{ $uptimePercentage }}%</h2>
<small>Last 30 days</small>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-white bg-success">
<div class="card-body">
<h6 class="card-title">Avg Response Time</h6>
<h2 class="mb-0">{{ $avgResponseTime ? round($avgResponseTime) : 'N/A' }}</h2>
<small>{{ $avgResponseTime ? 'milliseconds' : 'No data' }}</small>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-white {{ $brokenLinks->total() > 0 ? 'bg-danger' : 'bg-success' }}">
<div class="card-body">
<h6 class="card-title">Broken Links</h6>
<h2 class="mb-0">{{ $brokenLinks->total() }}</h2>
<small>{{ $brokenLinks->total() == 1 ? 'link' : 'links' }} detected</small>
</div>
</div>
</div>
</div>
<!-- Uptime Chart -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0"><i class="bi bi-graph-up"></i> Response Time History (Last 30 Days)</h5>
</div>
<div class="card-body">
@if($uptimeChecks->isNotEmpty())
<canvas id="uptimeChart" height="80"></canvas>
@else
<div class="alert alert-info">
<i class="bi bi-info-circle"></i> No uptime data available yet. The site will be checked automatically.
</div>
@endif
</div>
</div>
<!-- SSL Certificate -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0"><i class="bi bi-shield-lock"></i> SSL Certificate</h5>
</div>
<div class="card-body">
@if($latestSslCert)
@php
$daysUntilExpiry = now()->diffInDays($latestSslCert->expires_at, false);
$isExpired = $daysUntilExpiry < 0;
$isExpiringSoon = $daysUntilExpiry < 30 && !$isExpired;
@endphp
<div class="row">
<div class="col-md-3">
<strong>Issuer:</strong><br>
{{ $latestSslCert->issuer }}
</div>
<div class="col-md-3">
<strong>Expires:</strong><br>
{{ $latestSslCert->expires_at->format('M d, Y') }}
</div>
<div class="col-md-3">
<strong>Days Remaining:</strong><br>
<span class="badge bg-{{ $isExpired ? 'danger' : ($isExpiringSoon ? 'warning' : 'success') }}">
{{ $isExpired ? 'EXPIRED' : $daysUntilExpiry . ' days' }}
</span>
</div>
<div class="col-md-3">
<strong>Last Checked:</strong><br>
{{ $latestSslCert->checked_at->diffForHumans() }}
</div>
</div>
@else
<div class="alert alert-info mb-0">
<i class="bi bi-info-circle"></i> No SSL certificate data available yet.
</div>
@endif
</div>
</div>
<!-- Broken Links -->
<div class="card">
<div class="card-header">
<h5 class="mb-0"><i class="bi bi-link-45deg"></i> Broken Links</h5>
</div>
<div class="card-body">
@if($brokenLinks->isNotEmpty())
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>URL</th>
<th>Status Code</th>
<th>Last Checked</th>
</tr>
</thead>
<tbody>
@foreach($brokenLinks as $link)
<tr>
<td>
<a href="{{ $link->url }}" target="_blank" class="text-decoration-none">
{{ $link->url }}
</a>
</td>
<td>
<span class="badge bg-danger">{{ $link->status_code ?? 'Failed' }}</span>
</td>
<td>{{ $link->last_checked_at->diffForHumans() }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-3">
{{ $brokenLinks->links() }}
</div>
@else
<div class="alert alert-success mb-0">
<i class="bi bi-check-circle"></i> No broken links detected! Your site is looking good.
</div>
@endif
</div>
</div>
@endsection
@push('scripts')
@if($uptimeChecks->isNotEmpty())
<script>
document.addEventListener('DOMContentLoaded', function() {
const ctx = document.getElementById('uptimeChart').getContext('2d');
const labels = @json($chartLabels);
const responseData = @json($chartData);
const statusCodes = @json($chartStatusCodes);
// Create background colors based on status codes
const backgroundColors = statusCodes.map(code => {
if (!code) return 'rgba(220, 53, 69, 0.5)'; // Red for null/failed
if (code >= 200 && code < 400) return 'rgba(25, 135, 84, 0.5)'; // Green for success
return 'rgba(220, 53, 69, 0.5)'; // Red for errors
});
const borderColors = statusCodes.map(code => {
if (!code) return 'rgb(220, 53, 69)';
if (code >= 200 && code < 400) return 'rgb(25, 135, 84)';
return 'rgb(220, 53, 69)';
});
new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Response Time (ms)',
data: responseData,
2026-03-28 22:07:06 +02:00
borderColor: 'rgb(14, 165, 233)',
2026-01-17 13:46:20 +02:00
backgroundColor: backgroundColors,
borderWidth: 2,
fill: false,
tension: 0.1,
pointBackgroundColor: backgroundColors,
pointBorderColor: borderColors,
pointRadius: 4,
pointHoverRadius: 6
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
display: true,
position: 'top'
},
tooltip: {
callbacks: {
afterLabel: function(context) {
const statusCode = statusCodes[context.dataIndex];
return statusCode ? 'HTTP ' + statusCode : 'Connection Failed';
}
}
}
},
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: 'Response Time (ms)'
}
},
x: {
title: {
display: true,
text: 'Check Time'
}
}
}
}
});
});
</script>
@endif
@endpush