Files
WMS/resources/views/components/layouts/app.blade.php
T

1049 lines
46 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
@include('partials.head')
<script>
(function () {
const SIDEBAR_STATE_KEY = 'wms-sidebar-state';
const SIDEBAR_WIDTH_KEY = 'wms-sidebar-width';
const DEFAULT_WIDTH = 288;
const MIN_WIDTH = 224;
const MAX_WIDTH = 448;
function clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}
const savedWidth = Number.parseInt(localStorage.getItem(SIDEBAR_WIDTH_KEY) || DEFAULT_WIDTH, 10);
const width = clamp(Number.isFinite(savedWidth) ? savedWidth : DEFAULT_WIDTH, MIN_WIDTH, MAX_WIDTH);
const savedState = localStorage.getItem(SIDEBAR_STATE_KEY) || 'expanded';
document.documentElement.style.setProperty('--wms-sidebar-width', `${width}px`);
document.documentElement.dataset.wmsSidebar = savedState === 'collapsed' ? 'collapsed' : 'expanded';
})();
</script>
<body class="min-h-screen bg-white font-sans text-zinc-950 antialiased dark:bg-zinc-950 dark:text-zinc-100">
<style>
:root {
--wms-sidebar-width: 288px;
--wms-sidebar-min-width: 224px;
--wms-sidebar-max-width: 448px;
--wms-sidebar-collapsed-width: 76px;
--wms-active-parent-blue: #4164dc;
--wms-active-child-gold: #e7b72f;
--wms-active-child-gold-dark: #e7b72f;
}
.wms-app-shell {
display: grid;
grid-template-columns: var(--wms-sidebar-width) minmax(0, 1fr);
min-height: 100vh;
transition-property: none;
}
html[data-wms-sidebar="expanded"] .wms-app-shell {
grid-template-columns: var(--wms-sidebar-width) minmax(0, 1fr);
}
html[data-wms-sidebar="collapsed"] .wms-app-shell {
grid-template-columns: var(--wms-sidebar-collapsed-width) minmax(0, 1fr);
}
.wms-sidebar {
position: relative;
width: var(--wms-sidebar-width);
min-width: var(--wms-sidebar-width);
max-width: var(--wms-sidebar-width);
transition-property: none;
}
.wms-main-panel {
transition-property: none;
}
html[data-wms-sidebar="collapsed"] .wms-sidebar {
width: var(--wms-sidebar-collapsed-width);
min-width: var(--wms-sidebar-collapsed-width);
max-width: var(--wms-sidebar-collapsed-width);
}
.wms-sidebar-resizer {
position: absolute;
top: 0;
right: -4px;
z-index: 30;
width: 8px;
height: 100%;
cursor: col-resize;
border: 0;
background: transparent;
}
.wms-sidebar-resizer::after {
position: absolute;
top: 0;
right: 3px;
width: 1px;
height: 100%;
content: "";
background: rgba(148, 163, 184, 0.22);
transition: background 160ms ease;
}
.wms-sidebar-resizer:hover::after,
body.wms-sidebar-is-resizing .wms-sidebar-resizer::after {
background: rgba(59, 130, 246, 0.7);
}
body.wms-sidebar-is-resizing {
cursor: col-resize;
user-select: none;
}
html[data-wms-sidebar="collapsed"] .wms-sidebar-resizer {
display: none;
}
.wms-sidebar-nav {
overflow-x: hidden;
}
.wms-sidebar-heading-button {
display: flex;
width: 100%;
align-items: center;
justify-content: flex-start;
gap: 0.75rem;
border: 0;
background: transparent;
cursor: pointer;
text-align: left;
}
.wms-sidebar-heading-content {
display: inline-flex;
align-items: center;
gap: 0.7rem;
min-width: 0;
}
.wms-sidebar-heading-content > span {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.wms-sidebar-heading-chevron {
display: none;
}
.wms-sidebar-group-items {
display: none;
}
.wms-sidebar-group[data-wms-menu-open="true"] > .wms-sidebar-group-items {
display: block;
}
.wms-sidebar-group:not([data-wms-menu-group="platform"])[data-wms-selected="true"] > .wms-sidebar-heading-button {
position: relative;
width: calc(100% - 1.25rem);
min-height: 2.9rem;
margin: 0.25rem 0.65rem 0.35rem;
padding: 0.6rem 0.85rem;
border-radius: 1.35rem;
background: linear-gradient(135deg, #4667df 0%, #3f5fd2 100%);
color: #ffffff;
font-weight: 700;
letter-spacing: 0.035em;
box-shadow: 0 8px 18px rgba(65, 100, 220, 0.22);
}
.wms-sidebar-group:not([data-wms-menu-group="platform"])[data-wms-selected="true"] > .wms-sidebar-heading-button .wms-sidebar-icon {
color: #ffffff;
}
.wms-sidebar-link.is-active {
position: relative;
isolation: isolate;
width: calc(100% - 2.05rem);
min-height: 2.85rem;
margin: 0.2rem 1.25rem 0.25rem 0.8rem;
padding: 0.6rem 0.95rem;
border-radius: 1.65rem 0.75rem 0.75rem 1.65rem;
background: var(--wms-active-child-gold);
color: #ffffff;
font-weight: 700;
box-shadow: 0 8px 18px rgba(231, 183, 47, 0.24);
}
.wms-sidebar-link.is-active::after {
position: absolute;
top: 0;
right: -1.05rem;
z-index: -1;
width: 1.75rem;
height: 100%;
content: "";
background: var(--wms-active-child-gold);
clip-path: polygon(0 0, 64% 0, 100% 50%, 64% 100%, 0 100%);
border-radius: 0 0.9rem 0.9rem 0;
}
.wms-sidebar-link.is-active .wms-sidebar-icon,
.wms-sidebar-link.is-active i,
.wms-sidebar-link.is-active span {
position: relative;
z-index: 1;
color: #ffffff;
}
html[data-wms-sidebar="collapsed"] .wms-sidebar-heading-chevron,
html[data-wms-sidebar="collapsed"] .wms-sidebar-group-items {
display: none;
}
html[data-wms-sidebar="collapsed"] .wms-sidebar-heading-button {
pointer-events: none;
}
html[data-wms-sidebar="collapsed"] .wms-sidebar-group:not([data-wms-menu-group="platform"])[data-wms-selected="true"] > .wms-sidebar-heading-button,
html[data-wms-sidebar="collapsed"] .wms-sidebar-link.is-active {
width: 2.75rem;
min-height: 2.75rem;
margin: 0.25rem auto;
justify-content: center;
border-radius: 9999px;
padding: 0.65rem;
}
html[data-wms-sidebar="collapsed"] .wms-sidebar-link.is-active::after {
display: none;
}
@media (max-width: 1023px) {
.wms-app-shell {
display: block;
}
.wms-sidebar,
html[data-wms-sidebar="collapsed"] .wms-sidebar {
width: min(88vw, 22rem);
min-width: min(88vw, 22rem);
max-width: min(88vw, 22rem);
}
.wms-sidebar-resizer {
display: none;
}
.wms-sidebar-group:not([data-wms-menu-group="platform"])[data-wms-selected="true"] > .wms-sidebar-heading-button {
width: calc(100% - 1.25rem);
min-height: 2.85rem;
margin: 0.25rem 0.65rem 0.35rem;
padding: 0.6rem 0.85rem;
}
.wms-sidebar-link.is-active {
width: calc(100% - 2.05rem);
min-height: 2.8rem;
margin: 0.2rem 1.25rem 0.25rem 0.8rem;
padding: 0.6rem 0.95rem;
}
html[data-wms-sidebar="collapsed"] .wms-sidebar-group-items {
display: none;
}
html[data-wms-sidebar="collapsed"] .wms-sidebar-group[data-wms-menu-open="true"] > .wms-sidebar-group-items {
display: block;
}
html[data-wms-sidebar="collapsed"] .wms-sidebar-heading-button {
pointer-events: auto;
}
}
</style>
<div class="wms-app-shell" data-wms-shell data-wms-mobile-shell>
<button type="button" class="wms-mobile-overlay" data-wms-mobile-close aria-label="{{ __('Close navigation menu') }}"></button>
<aside id="wms-main-sidebar" class="wms-sidebar" data-wms-sidebar aria-label="{{ __('Main navigation') }}">
<div class="wms-sidebar-header">
<a href="{{ auth()->user()?->isMpbaPlatformAdmin() && Route::has('platform.dashboard') ? route('platform.dashboard') : route('dashboard') }}" wire:navigate class="wms-brand" aria-label="{{ __('Warehouse Management System') }}">
<span class="wms-brand-mark" data-wms-brand-toggle title="{{ __('Expand sidebar') }}">
<span class="wms-brand-mark-inner">W</span>
</span>
<span class="wms-brand-copy" data-wms-sidebar-label>
<span class="wms-brand-title">{{ __('Warehouse Management System') }}</span>
<span class="wms-brand-subtitle">MPBA</span>
</span>
</a>
<button type="button" class="wms-sidebar-toggle" data-wms-sidebar-toggle aria-label="{{ __('Collapse sidebar') }}" aria-expanded="true">
<span class="wms-toggle-expanded">‹</span>
</button>
<button type="button" class="wms-mobile-close" data-wms-mobile-close aria-label="{{ __('Close navigation') }}">×</button>
</div>
<nav class="wms-sidebar-nav" aria-label="{{ __('Main navigation') }}">
<div class="wms-sidebar-group" data-wms-menu-group="platform">
<button type="button" class="wms-sidebar-heading wms-sidebar-heading-button" data-wms-menu-toggle data-wms-sidebar-label aria-expanded="false">
<span class="wms-sidebar-heading-content">
<i class="fa-solid fa-screwdriver-wrench wms-sidebar-icon" aria-hidden="true"></i>
<span>{{ __('Platform') }}</span>
</span>
</button>
<div class="wms-sidebar-group-items" data-wms-menu-items>
@if(auth()->user()?->isMpbaPlatformAdmin() && Route::has('platform.dashboard'))
<a href="{{ route('platform.dashboard') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('platform.dashboard')) is-active @endif" title="{{ __('Platform') }}">
<i class="fa-solid fa-screwdriver-wrench wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Platform') }}</span>
</a>
@elseif(Route::has('dashboard'))
<a href="{{ route('dashboard') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('dashboard')) is-active @endif" title="{{ __('Dashboard') }}">
<i class="fa-solid fa-gauge-high wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Dashboard') }}</span>
</a>
@endif
</div>
</div>
<div class="wms-sidebar-group" data-wms-menu-group="operations">
<button type="button" class="wms-sidebar-heading wms-sidebar-heading-button" data-wms-menu-toggle data-wms-sidebar-label aria-expanded="false">
<span class="wms-sidebar-heading-content">
<i class="fa-solid fa-chart-simple wms-sidebar-icon" aria-hidden="true"></i>
<span>{{ __('Operations') }}</span>
</span>
</button>
<div class="wms-sidebar-group-items" data-wms-menu-items>
@if(Route::has('analytics.index'))
<a href="{{ route('analytics.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('analytics.*')) is-active @endif" title="{{ __('Analytics') }}">
<i class="fa-solid fa-chart-line wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Analytics') }}</span>
</a>
@endif
@if(Route::has('inventory-management.index'))
<a href="{{ route('inventory-management.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('inventory-management.*')) is-active @endif" title="{{ __('Inventory') }}">
<i class="fa-solid fa-boxes-stacked wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Inventory') }}</span>
</a>
@endif
@if(Route::has('replenishment.index'))
<a href="{{ route('replenishment.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('replenishment.*')) is-active @endif" title="{{ __('Replenishment') }}">
<i class="fa-solid fa-arrows-rotate wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Replenishment') }}</span>
</a>
@endif
@if(Route::has('shipping.index'))
<a href="{{ route('shipping.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('shipping.*')) is-active @endif" title="{{ __('Shipping') }}">
<i class="fa-solid fa-truck-fast wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Shipping') }}</span>
</a>
@endif
@if(Route::has('transportation.index'))
<a href="{{ route('transportation.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('transportation.*')) is-active @endif" title="{{ __('Transportation') }}">
<i class="fa-solid fa-truck-ramp-box wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Transportation') }}</span>
</a>
@endif
@if(Route::has('carrier-management.index'))
<a href="{{ route('carrier-management.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('carrier-management.*')) is-active @endif" title="{{ __('Carriers') }}">
<i class="fa-solid fa-route wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Carriers') }}</span>
</a>
@endif
</div>
</div>
@php
$helpdeskEnabled = Route::has('helpdesk.index') || Route::has('helpdesk.tickets.index');
$helpdeskSettingsRoute = Route::has('helpdesk.settings')
? 'helpdesk.settings'
: (Route::has('helpdesk.settings.index') ? 'helpdesk.settings.index' : null);
$helpdeskKanbanRoute = Route::has('helpdesk.kanban')
? 'helpdesk.kanban'
: (Route::has('helpdesk.kanban.index') ? 'helpdesk.kanban.index' : null);
$helpdeskGitRoute = Route::has('helpdesk.git.index')
? 'helpdesk.git.index'
: null;
$helpdeskWorkflowRoute = Route::has('helpdesk.workflow-templates.index')
? 'helpdesk.workflow-templates.index'
: null;
$documentationEnabled = Route::has('documentation.index') || Route::has('documentation.documents.index');
$documentationRoute = Route::has('documentation.index')
? 'documentation.index'
: (Route::has('documentation.documents.index') ? 'documentation.documents.index' : null);
@endphp
@if($helpdeskEnabled || $documentationEnabled)
<div class="wms-sidebar-group" data-wms-menu-group="support">
<button type="button" class="wms-sidebar-heading wms-sidebar-heading-button" data-wms-menu-toggle data-wms-sidebar-label aria-expanded="false">
<span class="wms-sidebar-heading-content">
<i class="fa-solid fa-headset wms-sidebar-icon" aria-hidden="true"></i>
<span>{{ __('Support') }}</span>
</span>
</button>
<div class="wms-sidebar-group-items" data-wms-menu-items>
@if(Route::has('helpdesk.index'))
<a href="{{ route('helpdesk.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('helpdesk.index')) is-active @endif" title="{{ __('Helpdesk Dashboard') }}">
<i class="fa-solid fa-headset wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Dashboard') }}</span>
</a>
@endif
@if(Route::has('helpdesk.tickets.index'))
<a href="{{ route('helpdesk.tickets.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('helpdesk.tickets.index') || request()->routeIs('helpdesk.tickets.show') || request()->routeIs('helpdesk.tickets.edit')) is-active @endif" title="{{ __('Tickets') }}">
<i class="fa-solid fa-ticket wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Tickets') }}</span>
</a>
@endif
@if(Route::has('helpdesk.tickets.create'))
<a href="{{ route('helpdesk.tickets.create') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('helpdesk.tickets.create')) is-active @endif" title="{{ __('Raise Ticket') }}">
<i class="fa-solid fa-circle-plus wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Raise Ticket') }}</span>
</a>
@endif
@if($helpdeskKanbanRoute)
<a href="{{ route($helpdeskKanbanRoute) }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('helpdesk.kanban') || request()->routeIs('helpdesk.kanban.index')) is-active @endif" title="{{ __('Kanban') }}">
<i class="fa-solid fa-table-columns wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Kanban') }}</span>
</a>
@endif
@if($helpdeskGitRoute)
<a href="{{ route($helpdeskGitRoute) }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('helpdesk.git.*')) is-active @endif" title="{{ __('Git Tracking') }}">
<i class="fa-solid fa-code-commit wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Git Tracking') }}</span>
</a>
@endif
@if($helpdeskWorkflowRoute)
<a href="{{ route($helpdeskWorkflowRoute) }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('helpdesk.workflow-templates.*')) is-active @endif" title="{{ __('Workflow Emails') }}">
<i class="fa-solid fa-envelope-circle-check wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Workflow Emails') }}</span>
</a>
@endif
@if($documentationRoute)
<a href="{{ route($documentationRoute) }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('documentation.*')) is-active @endif" title="{{ __('Documentation') }}">
<i class="fa-solid fa-book-open wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Documentation') }}</span>
</a>
@endif
@if($helpdeskSettingsRoute)
<a href="{{ route($helpdeskSettingsRoute) }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('helpdesk.settings') || request()->routeIs('helpdesk.settings.index')) is-active @endif" title="{{ __('Helpdesk Settings') }}">
<i class="fa-solid fa-gears wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Settings') }}</span>
</a>
@endif
</div>
</div>
@endif
<div class="wms-sidebar-group" data-wms-menu-group="integration-reporting">
<button type="button" class="wms-sidebar-heading wms-sidebar-heading-button" data-wms-menu-toggle data-wms-sidebar-label aria-expanded="false">
<span class="wms-sidebar-heading-content">
<i class="fa-solid fa-plug-circle-bolt wms-sidebar-icon" aria-hidden="true"></i>
<span>{{ __('Integration & Reporting') }}</span>
</span>
</button>
<div class="wms-sidebar-group-items" data-wms-menu-items>
@if(Route::has('m3-integration.index'))
<a href="{{ route('m3-integration.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('m3-integration.*')) is-active @endif" title="{{ __('M3 Integration') }}">
<i class="fa-solid fa-plug-circle-bolt wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('M3 Integration') }}</span>
</a>
@endif
@if(Route::has('sentinel-integration.index'))
<a href="{{ route('sentinel-integration.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('sentinel-integration.*')) is-active @endif" title="{{ __('Sentinel') }}">
<i class="fa-solid fa-satellite-dish wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Sentinel') }}</span>
</a>
@endif
@if(Route::has('document-archive.index'))
<a href="{{ route('document-archive.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('document-archive.*')) is-active @endif" title="{{ __('Documents') }}">
<i class="fa-solid fa-box-archive wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Documents') }}</span>
</a>
@endif
@if(Route::has('reporting.index'))
<a href="{{ route('reporting.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('reporting.*')) is-active @endif" title="{{ __('Reporting') }}">
<i class="fa-solid fa-file-lines wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Reporting') }}</span>
</a>
@endif
</div>
</div>
<div class="wms-sidebar-group" data-wms-menu-group="administration">
<button type="button" class="wms-sidebar-heading wms-sidebar-heading-button" data-wms-menu-toggle data-wms-sidebar-label aria-expanded="false">
<span class="wms-sidebar-heading-content">
<i class="fa-solid fa-sliders wms-sidebar-icon" aria-hidden="true"></i>
<span>{{ __('Administration') }}</span>
</span>
</button>
<div class="wms-sidebar-group-items" data-wms-menu-items>
@if(Route::has('warehouses.index'))
<a href="{{ route('warehouses.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('warehouses.*')) is-active @endif" title="{{ __('Warehouses') }}">
<i class="fa-solid fa-warehouse wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Warehouses') }}</span>
</a>
@endif
@if(Route::has('warehouse-rules.index'))
<a href="{{ route('warehouse-rules.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('warehouse-rules.*')) is-active @endif" title="{{ __('Validation Rules') }}">
<i class="fa-solid fa-shield-halved wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Validation Rules') }}</span>
</a>
@endif
@if(auth()->user()?->isMpbaPlatformAdmin() && Route::has('platform.prices.index'))
<a href="{{ route('platform.prices.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('platform.prices.*')) is-active @endif" title="{{ __('Prices') }}">
<i class="fa-solid fa-tags wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Prices') }}</span>
</a>
@endif
@if(Route::has('configuration.index'))
<a href="{{ route('configuration.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('configuration.*')) is-active @endif" title="{{ __('Configuration') }}">
<i class="fa-solid fa-sliders wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Configuration') }}</span>
</a>
@endif
@if(Route::has('security.index'))
<a href="{{ route('security.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('security.*')) is-active @endif" title="{{ __('Security') }}">
<i class="fa-solid fa-user-shield wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Security') }}</span>
</a>
@endif
@if(Route::has('audit.index'))
<a href="{{ route('audit.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('audit.*')) is-active @endif" title="{{ __('Audit') }}">
<i class="fa-solid fa-clipboard-check wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Audit') }}</span>
</a>
@endif
</div>
</div>
@if(auth()->user()?->isMpbaPlatformAdmin())
@php
$countriesRoute = Route::has('platform.countries.index')
? 'platform.countries.index'
: (Route::has('countries.index') ? 'countries.index' : null);
@endphp
<div class="wms-sidebar-group" data-wms-menu-group="platform-administration">
<button type="button" class="wms-sidebar-heading wms-sidebar-heading-button" data-wms-menu-toggle data-wms-sidebar-label aria-expanded="false">
<span class="wms-sidebar-heading-content">
<i class="fa-solid fa-building-shield wms-sidebar-icon" aria-hidden="true"></i>
<span>{{ __('Platform Administration') }}</span>
</span>
</button>
<div class="wms-sidebar-group-items" data-wms-menu-items>
@if(Route::has('platform.companies.index'))
<a href="{{ route('platform.companies.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('platform.companies.*')) is-active @endif" title="{{ __('Companies') }}">
<i class="fa-solid fa-building wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Companies') }}</span>
</a>
@endif
@if(Route::has('platform.licenses.index'))
<a href="{{ route('platform.licenses.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('platform.licenses.*')) is-active @endif" title="{{ __('Licences') }}">
<i class="fa-solid fa-key wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Licences') }}</span>
</a>
@endif
@if(Route::has('platform.payments.index'))
<a href="{{ route('platform.payments.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('platform.payments.*')) is-active @endif" title="{{ __('Payments') }}">
<i class="fa-solid fa-credit-card wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Payments') }}</span>
</a>
@endif
@if($countriesRoute)
<a href="{{ route($countriesRoute) }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('platform.countries.*') || request()->routeIs('countries.*') || request()->routeIs('country.*')) is-active @endif" title="{{ __('Countries') }}">
<i class="fa-solid fa-globe wms-sidebar-icon" aria-hidden="true"></i>
<span data-wms-sidebar-label>{{ __('Countries') }}</span>
</a>
@endif
</div>
</div>
@endif
</nav>
<div class="wms-sidebar-footer">
<flux:dropdown position="top" align="start">
<button type="button" class="wms-user-card wms-user-card-button" data-wms-sidebar-label>
<div class="wms-user-avatar">{{ auth()->user()?->initials() ?? 'U' }}</div>
<div class="wms-user-copy">
<div class="wms-user-name">{{ auth()->user()?->name ?? __('User') }}</div>
<div class="wms-user-email">{{ auth()->user()?->email ?? '' }}</div>
</div>
<i class="fa-solid fa-chevron-up wms-user-chevron" aria-hidden="true"></i>
</button>
<flux:menu>
<flux:menu.radio.group>
<div class="p-0 text-sm font-normal">
<div class="flex items-center gap-2 px-1 py-1.5 text-start text-sm">
<flux:avatar :name="auth()->user()?->name ?? 'User'" :initials="auth()->user()?->initials() ?? 'U'" />
<div class="grid flex-1 text-start text-sm leading-tight">
<flux:heading class="truncate">{{ auth()->user()?->name ?? __('User') }}</flux:heading>
<flux:text class="truncate">{{ auth()->user()?->email ?? '' }}</flux:text>
</div>
</div>
</div>
</flux:menu.radio.group>
<flux:menu.separator />
<flux:menu.item :href="route('profile.edit')" icon="cog" wire:navigate>
{{ __('Settings') }}
</flux:menu.item>
<flux:menu.separator />
<form method="POST" action="{{ route('logout') }}" class="w-full">
@csrf
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full cursor-pointer" data-test="logout-button">
{{ __('Log out') }}
</flux:menu.item>
</form>
</flux:menu>
</flux:dropdown>
<flux:dropdown position="top" align="start">
<button type="button" class="wms-user-rail-button" title="{{ __('Account') }}">
{{ auth()->user()?->initials() ?? 'U' }}
</button>
<flux:menu>
<flux:menu.item :href="route('profile.edit')" icon="cog" wire:navigate>
{{ __('Settings') }}
</flux:menu.item>
<flux:menu.separator />
<form method="POST" action="{{ route('logout') }}" class="w-full">
@csrf
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full cursor-pointer">
{{ __('Log out') }}
</flux:menu.item>
</form>
</flux:menu>
</flux:dropdown>
</div>
<button
type="button"
class="wms-sidebar-resizer"
data-wms-sidebar-resizer
aria-label="{{ __('Resize sidebar') }}"
title="{{ __('Drag to resize sidebar') }}"
></button>
</aside>
<div class="wms-main-panel">
<header class="wms-mobile-header" role="banner">
<button type="button" class="wms-mobile-menu" data-wms-mobile-open aria-label="{{ __('Open navigation menu') }}" aria-controls="wms-main-sidebar" aria-expanded="false">
<i class="fa-solid fa-bars" aria-hidden="true"></i>
</button>
<a href="{{ auth()->user()?->isMpbaPlatformAdmin() && Route::has('platform.dashboard') ? route('platform.dashboard') : route('dashboard') }}" wire:navigate class="wms-mobile-title">
{{ __('Warehouse Management System') }}
</a>
<span class="wms-mobile-badge">MPBA</span>
</header>
<main class="wms-content">
{{ $slot }}
</main>
</div>
</div>
@fluxScripts
<script>
(function () {
const SIDEBAR_STATE_KEY = 'wms-sidebar-state';
const SIDEBAR_WIDTH_KEY = 'wms-sidebar-width';
const PLATFORM_FIRST_OPEN_KEY = 'wms-platform-first-opened';
const DEFAULT_WIDTH = 288;
const MIN_WIDTH = 224;
const MAX_WIDTH = 448;
function clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}
function getSavedSidebarWidth() {
const savedWidth = Number.parseInt(localStorage.getItem(SIDEBAR_WIDTH_KEY) || DEFAULT_WIDTH, 10);
return clamp(Number.isFinite(savedWidth) ? savedWidth : DEFAULT_WIDTH, MIN_WIDTH, MAX_WIDTH);
}
function applySidebarWidth() {
const nextWidth = `${getSavedSidebarWidth()}px`;
document.documentElement.style.setProperty('--wms-sidebar-width', nextWidth);
}
function applySidebarState() {
const root = document.documentElement;
const saved = localStorage.getItem(SIDEBAR_STATE_KEY) || 'expanded';
root.dataset.wmsSidebar = saved === 'collapsed' ? 'collapsed' : 'expanded';
document.querySelectorAll('[data-wms-sidebar-toggle]').forEach((button) => {
const expanded = root.dataset.wmsSidebar !== 'collapsed';
button.setAttribute('aria-expanded', expanded ? 'true' : 'false');
button.setAttribute('aria-label', expanded ? '{{ __('Collapse sidebar') }}' : '{{ __('Expand sidebar') }}');
});
}
function getMenuItems(group) {
return Array.from(group.children).find((child) => child.matches('[data-wms-menu-items]')) || null;
}
function getMenuToggle(group) {
return Array.from(group.children).find((child) => child.matches('[data-wms-menu-toggle]')) || null;
}
function groupHasActiveLink(group) {
const items = getMenuItems(group);
return items ? items.querySelector('.wms-sidebar-link.is-active') !== null : false;
}
function setMenuGroupOpen(group, isOpen) {
group.dataset.wmsMenuOpen = isOpen ? 'true' : 'false';
const toggle = getMenuToggle(group);
if (toggle) {
toggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
}
}
function setMenuGroupSelected(group, isSelected) {
group.dataset.wmsSelected = isSelected ? 'true' : 'false';
group.dataset.wmsHasActive = isSelected ? 'true' : 'false';
}
function resetAllMenuGroups() {
document.querySelectorAll('[data-wms-menu-group]').forEach((group) => {
setMenuGroupOpen(group, false);
setMenuGroupSelected(group, false);
group.dataset.wmsManualActive = 'false';
});
}
function selectMenuGroup(group, openGroup = true) {
resetAllMenuGroups();
setMenuGroupSelected(group, true);
setMenuGroupOpen(group, openGroup);
}
function applyMenuState() {
const groups = Array.from(document.querySelectorAll('[data-wms-menu-group]'));
const selectedByRoute = groups.find((group) => groupHasActiveLink(group)) || null;
const selectedByManualClick = groups.find((group) => group.dataset.wmsManualActive === 'true') || null;
const selectedGroup = selectedByRoute || selectedByManualClick;
const shouldOpenPlatformForFirstVisit = !selectedGroup && localStorage.getItem(PLATFORM_FIRST_OPEN_KEY) !== '1';
resetAllMenuGroups();
if (selectedGroup) {
setMenuGroupSelected(selectedGroup, true);
setMenuGroupOpen(selectedGroup, true);
} else if (shouldOpenPlatformForFirstVisit) {
const platformGroup = groups.find((group) => group.dataset.wmsMenuGroup === 'platform');
if (platformGroup) {
setMenuGroupOpen(platformGroup, true);
}
localStorage.setItem(PLATFORM_FIRST_OPEN_KEY, '1');
}
}
function bindMenuControls() {
document.querySelectorAll('[data-wms-menu-toggle]').forEach((button) => {
if (button.dataset.wmsBound === '1') {
return;
}
button.dataset.wmsBound = '1';
button.addEventListener('click', function () {
const group = button.closest('[data-wms-menu-group]');
if (!group) {
return;
}
const nextOpen = group.dataset.wmsMenuOpen !== 'true';
resetAllMenuGroups();
if (nextOpen) {
group.dataset.wmsManualActive = 'true';
setMenuGroupSelected(group, true);
setMenuGroupOpen(group, true);
}
});
});
}
function bindSidebarResize() {
document.querySelectorAll('[data-wms-sidebar-resizer]').forEach((handle) => {
if (handle.dataset.wmsBound === '1') {
return;
}
handle.dataset.wmsBound = '1';
let startX = 0;
let startWidth = DEFAULT_WIDTH;
let isResizing = false;
function getClientX(event) {
if (event.touches && event.touches.length > 0) {
return event.touches[0].clientX;
}
return event.clientX;
}
function startResize(event) {
if (document.documentElement.dataset.wmsSidebar === 'collapsed') {
return;
}
isResizing = true;
startX = getClientX(event);
const currentWidth = Number.parseInt(
getComputedStyle(document.documentElement).getPropertyValue('--wms-sidebar-width'),
10
);
startWidth = Number.isFinite(currentWidth) ? currentWidth : DEFAULT_WIDTH;
document.body.classList.add('wms-sidebar-is-resizing');
event.preventDefault();
}
function moveResize(event) {
if (!isResizing) {
return;
}
const delta = getClientX(event) - startX;
const nextWidth = clamp(startWidth + delta, MIN_WIDTH, MAX_WIDTH);
document.documentElement.style.setProperty('--wms-sidebar-width', `${nextWidth}px`);
localStorage.setItem(SIDEBAR_WIDTH_KEY, String(nextWidth));
event.preventDefault();
}
function stopResize() {
if (!isResizing) {
return;
}
isResizing = false;
document.body.classList.remove('wms-sidebar-is-resizing');
}
handle.addEventListener('mousedown', startResize);
handle.addEventListener('touchstart', startResize, { passive: false });
window.addEventListener('mousemove', moveResize);
window.addEventListener('touchmove', moveResize, { passive: false });
window.addEventListener('mouseup', stopResize);
window.addEventListener('touchend', stopResize);
window.addEventListener('touchcancel', stopResize);
});
}
function setMobileToggleState(isOpen) {
document.querySelectorAll('[data-wms-mobile-open]').forEach((button) => {
button.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
});
document.body.classList.toggle('wms-mobile-nav-open', isOpen);
}
function closeMobileSidebar() {
document.documentElement.dataset.wmsMobileSidebar = 'closed';
setMobileToggleState(false);
}
function openMobileSidebar() {
document.documentElement.dataset.wmsMobileSidebar = 'open';
setMobileToggleState(true);
}
function toggleMobileSidebar() {
if (document.documentElement.dataset.wmsMobileSidebar === 'open') {
closeMobileSidebar();
return;
}
openMobileSidebar();
}
function bindSidebarControls() {
applySidebarWidth();
applySidebarState();
applyMenuState();
bindMenuControls();
bindSidebarResize();
document.querySelectorAll('[data-wms-sidebar-toggle]').forEach((button) => {
if (button.dataset.wmsBound === '1') {
return;
}
button.dataset.wmsBound = '1';
button.addEventListener('click', function () {
const root = document.documentElement;
const next = root.dataset.wmsSidebar === 'collapsed' ? 'expanded' : 'collapsed';
root.dataset.wmsSidebar = next;
localStorage.setItem(SIDEBAR_STATE_KEY, next);
applySidebarState();
});
});
document.querySelectorAll('[data-wms-brand-toggle]').forEach((button) => {
if (button.dataset.wmsBound === '1') {
return;
}
button.dataset.wmsBound = '1';
button.addEventListener('click', function (event) {
const root = document.documentElement;
if (root.dataset.wmsSidebar !== 'collapsed') {
return;
}
event.preventDefault();
event.stopPropagation();
root.dataset.wmsSidebar = 'expanded';
localStorage.setItem(SIDEBAR_STATE_KEY, 'expanded');
applySidebarState();
applyMenuState();
});
});
closeMobileSidebar();
document.querySelectorAll('[data-wms-mobile-open]').forEach((button) => {
if (button.dataset.wmsBound === '1') {
return;
}
button.dataset.wmsBound = '1';
button.addEventListener('click', function (event) {
event.preventDefault();
toggleMobileSidebar();
});
});
document.querySelectorAll('[data-wms-mobile-close]').forEach((button) => {
if (button.dataset.wmsBound === '1') {
return;
}
button.dataset.wmsBound = '1';
button.addEventListener('click', closeMobileSidebar);
});
document.querySelectorAll('.wms-sidebar-link[wire\\:navigate]').forEach((link) => {
if (link.dataset.wmsMobileBound === '1') {
return;
}
link.dataset.wmsMobileBound = '1';
link.addEventListener('click', function () {
document.querySelectorAll('.wms-sidebar-link.is-active').forEach((activeLink) => {
activeLink.classList.remove('is-active');
});
link.classList.add('is-active');
const selectedGroup = link.closest('[data-wms-menu-group]');
if (selectedGroup) {
selectMenuGroup(selectedGroup, true);
}
applySidebarWidth();
closeMobileSidebar();
});
});
}
applySidebarWidth();
applySidebarState();
document.addEventListener('DOMContentLoaded', bindSidebarControls);
document.addEventListener('livewire:navigated', bindSidebarControls);
})();
</script>
</body>
</html>