Add HL3D branding, Etsy Live/Draft paging and Projects lifecycle
Deploy HickLab3D Dashboard / Deploy to production (push) Failing after 23s
Deploy HickLab3D Dashboard / Deploy to production (push) Failing after 23s
Replace the old touchmark/PNG identity with the supplied lockup and monogram, segmented role-aware navigation, Live/Draft listing filters with generation-based cache invalidation, and admin Projects covering immutable file revisions, listing live pointers, and exact-decimal filament/packaging/shipping costing. Additive schema only; no Etsy publication. Isolated clone tests: 301 tests, 1162 assertions.
This commit is contained in:
@@ -3,39 +3,48 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#0b0c0d">
|
||||
<meta name="theme-color" content="#111316">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<link rel="icon" type="image/svg+xml" href="{{ asset('favicon.svg') }}">
|
||||
<title>@yield('title', 'Dashboard') · HickLab3D</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<link rel="icon" type="image/svg+xml" href="{{ asset('branding/hl3d-monogram-dark-background.svg') }}">
|
||||
<title>@yield('title', 'Dashboard') · HL3D</title>
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
</head>
|
||||
<body class="min-h-screen bg-slate-950 font-sans text-slate-100 antialiased">
|
||||
<div class="min-h-screen lg:flex">
|
||||
<aside class="border-b border-slate-800 bg-slate-900/80 lg:fixed lg:inset-y-0 lg:w-64 lg:border-r lg:border-b-0">
|
||||
<div class="flex h-20 items-center gap-3 px-6">
|
||||
<a href="{{ route('dashboard') }}" class="grid size-10 shrink-0 place-items-center rounded-xl bg-brand p-1.5 transition-transform hover:scale-105" aria-label="HickLab3D overview"><img src="{{ asset('hicklab3d-touchmark.svg') }}" alt="" class="size-full object-contain"></a>
|
||||
<div><strong class="block text-lg tracking-tight">HickLab3D</strong><span class="text-xs text-slate-400">Operations studio</span></div>
|
||||
<aside data-sidebar class="hidden border-b border-slate-800 bg-slate-900/80 lg:fixed lg:inset-y-0 lg:block lg:w-64 lg:border-r lg:border-b-0">
|
||||
<div class="flex h-20 items-center px-6">
|
||||
<a href="{{ route('dashboard') }}" class="flex shrink-0 items-center gap-3 transition-transform hover:scale-105 motion-reduce:transition-none" aria-label="HL3D overview">
|
||||
<img src="{{ asset('branding/hl3d-lockup-dark-background.svg') }}" alt="HickLab3D" class="h-9 w-auto" data-sidebar-expanded-mark>
|
||||
<img src="{{ asset('branding/hl3d-monogram-dark-background.svg') }}" alt="HickLab3D" class="hidden size-8 object-contain" data-sidebar-collapsed-mark>
|
||||
</a>
|
||||
</div>
|
||||
<nav class="flex gap-1 overflow-x-auto px-4 pb-4 lg:flex-col lg:overflow-visible" aria-label="Main navigation">
|
||||
@php $links = [['dashboard', 'Overview'], ['printers.index', 'Print farm'], ['etsy.index', 'Etsy'], ['shipping', 'Shipping'], ['dryer', 'Dryer']]; @endphp
|
||||
@foreach($links as [$routeName, $label])
|
||||
@if(! in_array($routeName, ['shipping', 'etsy.index']) || auth()->user()->role === 'admin')
|
||||
<a href="{{ route($routeName) }}" @class(['shrink-0 rounded-xl px-4 py-3 text-sm font-medium transition-colors hover:bg-slate-800 hover:text-white', 'bg-brand/10 text-brand' => request()->routeIs($routeName) || request()->routeIs(str_replace('.index', '.*', $routeName)), 'text-slate-400' => !request()->routeIs($routeName)])>{{ $label }}</a>
|
||||
@endif
|
||||
<nav class="flex flex-col gap-1 px-4 pb-4" aria-label="Main navigation">
|
||||
@foreach($navigationGroups as $group)
|
||||
@continue($group['items'] === [])
|
||||
<details class="nav-group mb-1" data-nav-group="{{ $group['key'] }}" open>
|
||||
<summary class="flex cursor-pointer list-none items-center justify-between rounded-lg px-2 py-2 text-xs font-semibold uppercase tracking-[.15em] text-slate-500 hover:text-slate-300">
|
||||
<span data-sidebar-label>{{ $group['label'] }}</span>
|
||||
<svg class="nav-group-chevron size-3 shrink-0 transition-transform motion-reduce:transition-none" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M3 4.5 6 7.5 9 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</summary>
|
||||
<div class="flex flex-col gap-1 pt-1">
|
||||
@foreach($group['items'] as $item)
|
||||
<a href="{{ route($item['route']) }}" @if(request()->routeIs($item['activePatterns'])) aria-current="page" @endif @class(['block shrink-0 truncate rounded-xl px-4 py-3 text-sm font-medium transition-colors hover:bg-slate-800 hover:text-white motion-reduce:transition-none', 'bg-brand/10 text-brand' => request()->routeIs($item['activePatterns']), 'text-slate-400' => ! request()->routeIs($item['activePatterns'])])>{{ $item['label'] }}</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</details>
|
||||
@endforeach
|
||||
@if(auth()->user()->role === 'admin')
|
||||
<a href="{{ route('settings.index') }}" @class(['shrink-0 rounded-xl px-4 py-3 text-sm font-medium hover:bg-slate-800', 'bg-brand/10 text-brand' => request()->routeIs('settings.*'), 'text-slate-400' => !request()->routeIs('settings.*')])>Settings</a>
|
||||
<a href="{{ route('users.index') }}" @class(['shrink-0 rounded-xl px-4 py-3 text-sm font-medium hover:bg-slate-800', 'bg-brand/10 text-brand' => request()->routeIs('users.*'), 'text-slate-400' => !request()->routeIs('users.*')])>Users</a>
|
||||
@endif
|
||||
</nav>
|
||||
<div class="px-6 pb-5 text-xs text-slate-500 lg:absolute lg:bottom-0">Made for the HickLab3D workshop</div>
|
||||
<div class="px-6 pb-5 text-xs text-slate-500 lg:absolute lg:bottom-0" data-sidebar-label>Made for the HL3D workshop</div>
|
||||
<button type="button" data-sidebar-toggle class="mx-4 mb-4 hidden w-auto rounded-lg border border-slate-700 px-3 py-2 text-xs text-slate-400 hover:border-brand hover:text-white lg:block" aria-pressed="false">Collapse</button>
|
||||
</aside>
|
||||
<div class="min-w-0 flex-1 lg:pl-64">
|
||||
<div class="min-w-0 flex-1 lg:pl-64" data-content>
|
||||
<header class="flex min-h-20 items-center justify-between gap-4 border-b border-slate-800 px-6 lg:px-10">
|
||||
<div><p class="text-xs font-semibold uppercase tracking-[.2em] text-brand">Workshop dashboard</p><h1 class="text-xl font-bold">@yield('title', 'Overview')</h1></div>
|
||||
<div class="flex items-center gap-3">
|
||||
<button type="button" popovertarget="mobile-nav" popovertargetaction="show" class="rounded-lg border border-slate-700 p-2 text-slate-300 hover:border-brand hover:text-white lg:hidden" aria-label="Open navigation menu">
|
||||
<svg class="size-5" viewBox="0 0 20 20" fill="none" aria-hidden="true"><path d="M3 5h14M3 10h14M3 15h14" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
</button>
|
||||
<div><p class="text-xs font-semibold uppercase tracking-[.2em] text-brand">Operate</p><h1 class="text-xl font-bold">@yield('title', 'Overview')</h1></div>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">@include('partials.notifications')<span class="hidden text-sm text-slate-400 sm:inline">{{ auth()->user()->username }}</span><form method="post" action="{{ route('logout') }}">@csrf<button class="rounded-lg border border-slate-700 px-3 py-2 text-sm text-slate-300 hover:border-brand hover:text-white">Sign out</button></form></div>
|
||||
</header>
|
||||
<main class="flex w-full flex-col gap-7 px-6 py-8 lg:px-10">
|
||||
@@ -45,6 +54,29 @@
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mobile-nav" popover="auto" class="fixed inset-0 m-0 h-screen w-full max-w-none border-none bg-slate-950 p-0 lg:hidden" aria-label="Navigation menu">
|
||||
<div class="flex h-full flex-col">
|
||||
<div class="flex items-center justify-between border-b border-slate-800 px-6 py-5">
|
||||
<strong class="text-lg">HL3D navigation</strong>
|
||||
<button type="button" popovertarget="mobile-nav" popovertargetaction="hide" class="rounded-lg border border-slate-700 p-2 text-slate-300" aria-label="Close navigation menu">
|
||||
<svg class="size-5" viewBox="0 0 20 20" fill="none" aria-hidden="true"><path d="M5 5l10 10M15 5L5 15" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<nav class="flex flex-1 flex-col gap-4 overflow-y-auto px-6 py-6" aria-label="Main navigation">
|
||||
@foreach($navigationGroups as $group)
|
||||
@continue($group['items'] === [])
|
||||
<div>
|
||||
<p class="px-2 pb-2 text-xs font-semibold uppercase tracking-[.15em] text-slate-500">{{ $group['label'] }}</p>
|
||||
<div class="flex flex-col gap-1">
|
||||
@foreach($group['items'] as $item)
|
||||
<a href="{{ route($item['route']) }}" @if(request()->routeIs($item['activePatterns'])) aria-current="page" @endif @class(['rounded-xl px-4 py-3 text-sm font-medium', 'bg-brand/10 text-brand' => request()->routeIs($item['activePatterns']), 'text-slate-300' => ! request()->routeIs($item['activePatterns'])])>{{ $item['label'] }}</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
@stack('scripts')
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user