134 lines
6.3 KiB
PHP
134 lines
6.3 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire;
|
|
|
|
use App\Livewire\Concerns\ResolvesCustomer;
|
|
use App\Services\Traffic\TrafficMeter;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Number;
|
|
use Livewire\Attributes\Layout;
|
|
use Livewire\Component;
|
|
|
|
#[Layout('layouts.portal-app')]
|
|
class Dashboard extends Component
|
|
{
|
|
use ResolvesCustomer;
|
|
|
|
public function render()
|
|
{
|
|
// Real numbers where they exist: traffic is metered, unlike the
|
|
// fixtures below, and a customer needs to see it before it runs out.
|
|
$instance = $this->customer()?->instances()->latest('id')->first();
|
|
$traffic = $instance !== null ? TrafficMeter::for($instance) : null;
|
|
|
|
// Locale-aware date / number formatting for the fixture values below.
|
|
$locale = app()->getLocale();
|
|
$date = fn (string $iso, string $fmt) => Carbon::parse($iso)->locale($locale)->isoFormat($fmt);
|
|
$gb = fn (float $v) => Number::format($v, precision: 1, locale: $locale).' GB';
|
|
// Fixture data until the provisioning engine (separate handoff) supplies
|
|
// real instances / metrics. Tenant-specific values stand in for DB rows.
|
|
$storageUsed = 235;
|
|
$storageQuota = 500;
|
|
$storagePercent = (int) round($storageUsed / max(1, $storageQuota) * 100);
|
|
|
|
// ~30 days of availability, gently trending near 100%.
|
|
$availability = [99.95, 99.97, 99.96, 99.98, 99.99, 99.97, 99.98, 99.99, 99.99, 99.98,
|
|
99.97, 99.99, 100, 99.98, 99.99, 99.99, 99.97, 99.98, 99.99, 100,
|
|
99.98, 99.99, 99.99, 99.98, 100, 99.99, 99.98, 99.99, 100, 99.98];
|
|
|
|
return view('livewire.dashboard', [
|
|
'traffic' => $traffic,
|
|
'storageUsed' => $storageUsed,
|
|
'storageQuota' => $storageQuota,
|
|
'storagePercent' => $storagePercent,
|
|
'usersActive' => 8,
|
|
'usersQuota' => 20,
|
|
'lastBackup' => '03:12',
|
|
'availability' => Number::format(99.98, precision: 2, locale: $locale),
|
|
|
|
'storageChart' => [
|
|
'type' => 'doughnut',
|
|
'data' => [
|
|
'datasets' => [[
|
|
'data' => [$storagePercent, 100 - $storagePercent],
|
|
'backgroundColor' => ['token:accent', 'token:surface-2'],
|
|
'borderWidth' => 0,
|
|
]],
|
|
],
|
|
'options' => [
|
|
'cutout' => '76%',
|
|
'plugins' => [
|
|
'legend' => ['display' => false],
|
|
'tooltip' => ['enabled' => false],
|
|
],
|
|
],
|
|
],
|
|
|
|
'availabilityChart' => [
|
|
'type' => 'line',
|
|
'data' => [
|
|
'labels' => array_fill(0, count($availability), ''),
|
|
'datasets' => [[
|
|
'data' => $availability,
|
|
'borderColor' => 'token:success-bright',
|
|
'backgroundColor' => 'token:success-bright/0.12',
|
|
'fill' => true,
|
|
'tension' => 0.4,
|
|
'pointRadius' => 0,
|
|
'borderWidth' => 2,
|
|
]],
|
|
],
|
|
'options' => [
|
|
'scales' => [
|
|
'x' => ['display' => false],
|
|
'y' => ['display' => false, 'min' => 99.9, 'max' => 100],
|
|
],
|
|
'plugins' => [
|
|
'legend' => ['display' => false],
|
|
'tooltip' => ['enabled' => false],
|
|
],
|
|
],
|
|
],
|
|
|
|
'cloud' => [
|
|
'name' => 'Cloud der Kanzlei Berger',
|
|
'domain' => 'cloud.kanzlei-berger.at',
|
|
'package' => __('dashboard.cloud.plan_line', ['plan' => 'CluPilot Cloud Team', 'price' => 179]),
|
|
'since' => $date('2026-03-14', 'LL'),
|
|
'location' => __('dashboard.cloud.datacenter'),
|
|
'version' => 'Nextcloud 31.0.4',
|
|
],
|
|
|
|
'onboarding' => [
|
|
['label' => __('dashboard.onboarding.instance'), 'done' => true, 'date' => $date('2026-03-14', 'D. MMMM')],
|
|
['label' => __('dashboard.onboarding.domain'), 'done' => true, 'date' => $date('2026-03-15', 'D. MMMM')],
|
|
['label' => __('dashboard.onboarding.branding'), 'done' => true, 'date' => $date('2026-03-15', 'D. MMMM')],
|
|
['label' => __('dashboard.onboarding.users'), 'done' => true, 'date' => $date('2026-03-16', 'D. MMMM')],
|
|
['label' => __('dashboard.onboarding.migration'), 'done' => false, 'date' => null],
|
|
['label' => __('dashboard.onboarding.training'), 'done' => false, 'date' => null],
|
|
['label' => __('dashboard.onboarding.docs'), 'done' => false, 'date' => null],
|
|
],
|
|
|
|
'backups' => [
|
|
['when' => __('dashboard.today').', 03:12', 'size' => $gb(18.4)],
|
|
['when' => __('dashboard.yesterday').', 03:09', 'size' => $gb(18.4)],
|
|
['when' => $date('2026-07-21', 'D. MMMM').', 03:11', 'size' => $gb(18.3)],
|
|
],
|
|
|
|
'modules' => [
|
|
['icon' => 'cloud', 'name' => 'Nextcloud + Collabora', 'desc' => __('dashboard.modules.nextcloud'), 'status' => 'active'],
|
|
['icon' => 'shield-check', 'name' => 'Vaultwarden', 'desc' => __('dashboard.modules.vaultwarden'), 'status' => 'active'],
|
|
['icon' => 'receipt', 'name' => 'Paperless-ngx', 'desc' => __('dashboard.modules.paperless'), 'status' => 'available'],
|
|
['icon' => 'pen', 'name' => __('dashboard.modules.signature_name'), 'desc' => __('dashboard.modules.signature'), 'status' => 'soon'],
|
|
],
|
|
|
|
'activity' => [
|
|
['icon' => 'download', 'text' => __('dashboard.activity_items.backup_ok'), 'time' => '03:12'],
|
|
['icon' => 'shield-check', 'text' => __('dashboard.activity_items.security'), 'time' => '04:01'],
|
|
['icon' => 'users', 'text' => __('dashboard.activity_items.upload'), 'time' => '07:56'],
|
|
['icon' => 'shield-check', 'text' => __('dashboard.activity_items.cert'), 'time' => __('dashboard.yesterday').' 22:10'],
|
|
],
|
|
]);
|
|
}
|
|
}
|