Deploy HickLab3D Dashboard / Deploy to production (push) Successful in 28s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
107 lines
9.7 KiB
PHP
107 lines
9.7 KiB
PHP
@extends('layouts.app')
|
|
@section('title', 'Overview')
|
|
@section('content')
|
|
<div class="flex flex-wrap items-end justify-between gap-4">
|
|
<div>
|
|
<p class="text-xs font-bold uppercase tracking-[.2em] text-brand">Workshop overview</p>
|
|
<h2 class="mt-2 text-2xl font-bold tracking-tight sm:text-3xl">Good to see you, {{ auth()->user()->username }}.</h2>
|
|
<p class="mt-2 text-sm text-slate-400">What needs attention across the shop and workshop.</p>
|
|
</div>
|
|
<p class="rounded-full border border-slate-700 px-3 py-1.5 text-xs text-slate-400">Updated when you open this page</p>
|
|
</div>
|
|
|
|
<section @class(['grid gap-4 sm:grid-cols-2', 'xl:grid-cols-4' => $isAdmin]) aria-label="Key metrics">
|
|
@if($isAdmin)
|
|
<a href="{{ route('etsy.index') }}" class="group rounded-2xl border border-slate-800 bg-slate-900 p-5 transition hover:border-brand/50">
|
|
<div class="flex items-center justify-between"><p class="text-sm font-medium text-slate-400">Awaiting dispatch</p><span class="text-brand">↗</span></div>
|
|
<p class="mt-4 text-3xl font-bold tabular-nums">{{ $etsyConnected ? $awaitingDispatch : '—' }}</p>
|
|
<p class="mt-2 truncate text-xs text-slate-500">{{ $etsyStatus }} · Latest 20 Etsy receipts</p>
|
|
</a>
|
|
@endif
|
|
<a href="{{ route('printers.index') }}" class="group rounded-2xl border border-slate-800 bg-slate-900 p-5 transition hover:border-brand/50">
|
|
<div class="flex items-center justify-between"><p class="text-sm font-medium text-slate-400">Printing now</p><span class="text-brand">↗</span></div>
|
|
<p class="mt-4 text-3xl font-bold tabular-nums">{{ $printerStatus === 'Live from BamBuddy' ? $printingCount : '—' }}<span class="ml-2 text-base font-medium text-slate-500">/ {{ $printerStatus === 'Live from BamBuddy' ? count($printers) : '—' }}</span></p>
|
|
<p class="mt-2 text-xs text-slate-500">{{ $printerStatus }}</p>
|
|
</a>
|
|
@if($isAdmin)
|
|
<a href="{{ route('etsy.index') }}" class="group rounded-2xl border border-slate-800 bg-slate-900 p-5 transition hover:border-brand/50">
|
|
<div class="flex items-center justify-between"><p class="text-sm font-medium text-slate-400">Active listings</p><span class="text-brand">↗</span></div>
|
|
<p class="mt-4 text-3xl font-bold tabular-nums">{{ $listingCount ?? '—' }}</p>
|
|
<p class="mt-2 text-xs text-slate-500">{{ $etsyStatus }}</p>
|
|
</a>
|
|
@endif
|
|
<a href="{{ route('dryer') }}" class="group rounded-2xl border border-slate-800 bg-slate-900 p-5 transition hover:border-brand/50">
|
|
<div class="flex items-center justify-between"><p class="text-sm font-medium text-slate-400">Filament dryer</p><span class="text-brand">↗</span></div>
|
|
<p class="mt-4 text-2xl font-bold">{{ $dryerState }}</p>
|
|
<p class="mt-2 text-xs text-slate-500">Current workshop state</p>
|
|
</a>
|
|
</section>
|
|
|
|
<div class="grid gap-4 xl:grid-cols-3">
|
|
@if($isAdmin)
|
|
<section class="min-w-0 rounded-2xl border border-slate-800 bg-slate-900 xl:col-span-2">
|
|
<div class="flex flex-wrap items-start justify-between gap-3 border-b border-slate-800 px-5 py-5 sm:px-6">
|
|
<div><h3 class="font-semibold">Orders awaiting dispatch</h3><p class="mt-1 text-xs text-slate-400">Placed in the last 14 days among the latest 20 unshipped Etsy receipts</p></div>
|
|
<a href="{{ route('etsy.index') }}" class="text-sm font-semibold text-brand hover:underline">View Etsy →</a>
|
|
</div>
|
|
@if($etsyConnected && array_sum($orderChart['series']) > 0)
|
|
<div class="p-5 sm:p-6"><div class="h-64 w-full" data-dashboard-chart="orders" data-chart="{{ json_encode($orderChart) }}" role="img" aria-label="Etsy orders awaiting dispatch by placement date"></div></div>
|
|
@else
|
|
<div class="flex min-h-64 flex-col items-center justify-center gap-2 px-6 text-center"><p class="font-medium">No recent dispatch orders to chart</p><p class="max-w-sm text-sm text-slate-400">{{ $etsyStatus === 'Not connected' ? 'Connect Etsy to see the current dispatch queue.' : ($etsyStatus === 'Temporarily unavailable' ? 'Etsy data is temporarily unavailable.' : 'Paid orders awaiting dispatch will appear here.') }}</p></div>
|
|
@endif
|
|
</section>
|
|
@endif
|
|
<section class="min-w-0 rounded-2xl border border-slate-800 bg-slate-900 {{ $isAdmin ? '' : 'xl:col-span-2' }}">
|
|
<div class="border-b border-slate-800 px-5 py-5 sm:px-6"><h3 class="font-semibold">Print farm status</h3><p class="mt-1 text-xs text-slate-400">Live printer states from BamBuddy</p></div>
|
|
@if(count($printerChart))
|
|
<div class="p-5 sm:p-6"><div class="h-64 w-full" data-dashboard-chart="printers" data-chart="{{ json_encode($printerChart) }}" role="img" aria-label="Printers by current state"></div></div>
|
|
@else
|
|
<div class="flex min-h-64 flex-col items-center justify-center gap-2 px-6 text-center"><p class="font-medium">No printer status to chart</p><a href="{{ route('printers.index') }}" class="text-sm text-brand hover:underline">Open print farm →</a></div>
|
|
@endif
|
|
</section>
|
|
@unless($isAdmin)
|
|
<section class="rounded-2xl border border-slate-800 bg-slate-900 p-5 sm:p-6"><h3 class="font-semibold">Workshop status</h3><p class="mt-4 text-sm text-slate-400">Print farm: {{ $printerStatus }}</p><p class="mt-2 text-sm text-slate-400">Dryer: {{ $dryerState }}</p></section>
|
|
@endunless
|
|
</div>
|
|
|
|
<div class="grid gap-4 xl:grid-cols-2">
|
|
<section class="rounded-2xl border border-slate-800 bg-slate-900">
|
|
<div class="flex items-center justify-between gap-3 border-b border-slate-800 px-5 py-4 sm:px-6"><div><h3 class="font-semibold">Print farm</h3><p class="mt-1 text-xs text-slate-400">{{ $printerStatus }}</p></div><a href="{{ route('printers.index') }}" class="text-sm font-semibold text-brand hover:underline">View all →</a></div>
|
|
<div class="divide-y divide-slate-800 px-5 sm:px-6">
|
|
@forelse(array_slice($printers, 0, 4) as $printer)
|
|
@php $live = $printer['live'] ?? []; @endphp
|
|
<div class="flex items-center justify-between gap-4 py-4"><div class="min-w-0"><p class="truncate font-medium">{{ $printer['name'] ?? 'Printer' }}</p><p class="mt-1 truncate text-xs text-slate-400">{{ $live['current_print'] ?? $live['subtask_name'] ?? 'No active job' }}</p></div><div class="text-right"><p @class(['text-sm font-semibold', 'text-brand' => in_array(strtoupper((string) ($live['state'] ?? '')), ['RUNNING', 'PRINTING']), 'text-slate-400' => ! in_array(strtoupper((string) ($live['state'] ?? '')), ['RUNNING', 'PRINTING'])])>{{ $live['state'] ?? $printer['status'] ?? 'Unavailable' }}</p><p class="mt-1 text-xs text-slate-500">{{ isset($live['progress']) ? number_format((float) $live['progress'], 0).'%' : '—' }}</p></div></div>
|
|
@empty
|
|
<p class="py-8 text-sm text-slate-400">{{ $printerStatus === 'Live from BamBuddy' ? 'No printers returned by BamBuddy.' : $printerStatus }}</p>
|
|
@endforelse
|
|
</div>
|
|
</section>
|
|
@if($isAdmin)
|
|
<section class="rounded-2xl border border-slate-800 bg-slate-900">
|
|
<div class="flex items-center justify-between gap-3 border-b border-slate-800 px-5 py-4 sm:px-6"><div><h3 class="font-semibold">Orders to pack</h3><p class="mt-1 text-xs text-slate-400">Latest paid Etsy receipts awaiting dispatch</p></div><a href="{{ route('etsy.index') }}" class="text-sm font-semibold text-brand hover:underline">View all →</a></div>
|
|
<div class="divide-y divide-slate-800 px-5 sm:px-6">
|
|
@forelse($receipts as $receipt)
|
|
<div class="flex items-center justify-between gap-4 py-4"><div class="min-w-0"><p class="truncate font-medium">#{{ $receipt['receipt_id'] ?? '—' }} · {{ $receipt['name'] ?? 'Buyer' }}</p><p class="mt-1 text-xs text-slate-400">{{ isset($receipt['create_timestamp']) ? \Illuminate\Support\Carbon::createFromTimestamp((int) $receipt['create_timestamp'])->format('d M Y') : 'Date unavailable' }}</p></div><span class="shrink-0 rounded-full bg-amber-400/10 px-2.5 py-1 text-xs font-medium text-amber-200">Pack & send</span></div>
|
|
@empty
|
|
<p class="py-8 text-sm text-slate-400">{{ $etsyStatus === 'Not connected' ? 'Connect Etsy to see orders.' : ($etsyStatus === 'Temporarily unavailable' ? 'Etsy data is temporarily unavailable.' : 'No orders awaiting dispatch.') }}</p>
|
|
@endforelse
|
|
</div>
|
|
</section>
|
|
@endif
|
|
</div>
|
|
|
|
@if($isAdmin)
|
|
<div>
|
|
<section class="rounded-2xl border border-slate-800 bg-slate-900">
|
|
<div class="flex items-center justify-between gap-3 border-b border-slate-800 px-5 py-4 sm:px-6"><div><h3 class="font-semibold">Recent shipments</h3><p class="mt-1 text-xs text-slate-400">Parcel2Go · {{ $shippingStatus }}</p></div><a href="{{ route('shipping') }}" class="text-sm font-semibold text-brand hover:underline">Labels & collections →</a></div>
|
|
<div class="divide-y divide-slate-800 px-5 sm:px-6">
|
|
@forelse($shipments as $shipment)
|
|
<div class="flex items-center justify-between gap-4 py-4"><div class="min-w-0"><p class="truncate font-medium">#{{ $shipment['OrderLineId'] ?? '—' }} · {{ $shipment['Courier'] ?? 'Courier' }}</p><p class="mt-1 truncate text-xs text-slate-400"><span class="mr-2 inline-block align-middle">{{ app(\App\Services\Display::class)->flag($shipment['DeliveryAddress'] ?? []) }}</span>{{ $shipment['DeliveryAddress']['ContactName'] ?? 'Recipient unavailable' }}</p></div><span class="shrink-0 text-xs text-slate-400">{{ ($shipment['Tracking']['Delivered'] ?? false) ? 'Delivered' : 'In transit' }}</span></div>
|
|
@empty<p class="py-8 text-sm text-slate-400">{{ $shippingStatus === 'Live account' ? 'No recent shipments.' : $shippingStatus }}</p>@endforelse
|
|
</div>
|
|
</section>
|
|
</div>
|
|
@endif
|
|
|
|
@endsection
|