Working state before icon/utils fixes - Oct 22

This commit is contained in:
2025-10-21 21:56:54 +02:00
parent a7d9d44a13
commit 5be47b91a2
39 changed files with 6017 additions and 508 deletions

View File

@@ -0,0 +1,72 @@
<!-- static/admin/partials/base-layout.html -->
<!DOCTYPE html>
<html :class="{ 'theme-dark': dark }" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title data-page-title>Admin Panel - Multi-Tenant Platform</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<!-- Tailwind CSS -->
<link rel="stylesheet" href="/static/admin/css/tailwind.output.css" />
<!-- Alpine Cloak -->
<style>
[x-cloak] { display: none !important; }
</style>
<!-- Page-specific styles slot -->
<slot name="head"></slot>
</head>
<body x-cloak>
<div class="flex h-screen bg-gray-50 dark:bg-gray-900" :class="{ 'overflow-hidden': isSideMenuOpen }">
<!-- Sidebar Container -->
<div id="sidebar-container"></div>
<div class="flex flex-col flex-1 w-full">
<!-- Header Container -->
<div id="header-container"></div>
<!-- Main Content Area (Child pages inject content here) -->
<main class="h-full overflow-y-auto">
<div class="container px-6 mx-auto grid">
<!-- Page content slot -->
<slot name="content"></slot>
</div>
</main>
</div>
</div>
<!-- Core Scripts (loaded for all pages) -->
<!-- 1. Partial Loader -->
<script src="/static/shared/js/partial-loader.js"></script>
<!-- 2. Icons Helper -->
<script src="/static/shared/js/icons.js"></script>
<!-- 3. Load Header & Sidebar -->
<script>
(async () => {
await window.partialLoader.loadAll({
'header-container': 'header.html',
'sidebar-container': 'sidebar.html'
});
})();
</script>
<!-- 4. Base Alpine Data -->
<script src="/static/admin/js/init-alpine.js"></script>
<!-- 5. API Client & Utils -->
<script src="/static/shared/js/api-client.js"></script>
<script src="/static/shared/js/utils.js"></script>
<!-- 6. Alpine.js v3 -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.0/dist/cdn.min.js"></script>
<!-- Page-specific scripts slot -->
<slot name="scripts"></slot>
</body>
</html>

View File

@@ -1,133 +0,0 @@
<!-- Top header bar with search, theme toggle, notifications, profile -->
<header class="z-10 py-4 bg-white shadow-md dark:bg-gray-800">
<div class="container flex items-center justify-between h-full px-6 mx-auto text-purple-600 dark:text-purple-300">
<!-- Mobile hamburger -->
<button class="p-1 mr-5 -ml-1 rounded-md md:hidden focus:outline-none focus:shadow-outline-purple"
@click="toggleSideMenu" aria-label="Menu">
<span x-html="$icon('menu', 'w-6 h-6')"></span>
</button>
<!-- Search input -->
<div class="flex justify-center flex-1 lg:mr-32">
<div class="relative w-full max-w-xl mr-6 focus-within:text-purple-500">
<div class="absolute inset-y-0 flex items-center pl-2">
<span x-html="$icon('search', 'w-4 h-4')"></span>
</div>
<input class="w-full pl-8 pr-2 text-sm text-gray-700 placeholder-gray-600 bg-gray-100 border-0 rounded-md dark:placeholder-gray-500 dark:focus:shadow-outline-gray dark:focus:placeholder-gray-600 dark:bg-gray-700 dark:text-gray-200 focus:placeholder-gray-500 focus:bg-white focus:border-purple-300 focus:outline-none focus:shadow-outline-purple form-input"
type="text" placeholder="Search for projects" aria-label="Search"/>
</div>
</div>
<ul class="flex items-center flex-shrink-0 space-x-6">
<!-- Theme toggler -->
<li class="flex">
<button class="rounded-md focus:outline-none focus:shadow-outline-purple"
@click="toggleTheme" aria-label="Toggle color mode">
<template x-if="!dark">
<span x-html="$icon('moon', 'w-5 h-5')"></span>
</template>
<template x-if="dark">
<span x-html="$icon('sun', 'w-5 h-5')"></span>
</template>
</button>
</li>
<!-- Notifications menu -->
<li class="relative">
<button class="relative align-middle rounded-md focus:outline-none focus:shadow-outline-purple"
@click="toggleNotificationsMenu" @keydown.escape="closeNotificationsMenu"
aria-label="Notifications" aria-haspopup="true">
<span x-html="$icon('bell', 'w-5 h-5')"></span>
<span aria-hidden="true" class="absolute top-0 right-0 inline-block w-3 h-3 transform translate-x-1 -translate-y-1 bg-red-600 border-2 border-white rounded-full dark:border-gray-800"></span>
</button>
<template x-if="isNotificationsMenuOpen">
<ul x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
@click.away="closeNotificationsMenu"
@keydown.escape="closeNotificationsMenu"
class="absolute right-0 w-56 p-2 mt-2 space-y-2 text-gray-600 bg-white border border-gray-100 rounded-md shadow-md dark:text-gray-300 dark:border-gray-700 dark:bg-gray-700">
<li class="flex">
<a class="inline-flex items-center justify-between w-full px-2 py-1 text-sm font-semibold transition-colors duration-150 rounded-md hover:bg-gray-100 hover:text-gray-800 dark:hover:bg-gray-800 dark:hover:text-gray-200" href="#">
<span>Messages</span>
<span class="inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-red-600 bg-red-100 rounded-full dark:text-red-100 dark:bg-red-600">13</span>
</a>
</li>
<li class="flex">
<a class="inline-flex items-center justify-between w-full px-2 py-1 text-sm font-semibold transition-colors duration-150 rounded-md hover:bg-gray-100 hover:text-gray-800 dark:hover:bg-gray-800 dark:hover:text-gray-200" href="#">
<span>Sales</span>
<span class="inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-red-600 bg-red-100 rounded-full dark:text-red-100 dark:bg-red-600">2</span>
</a>
</li>
<li class="flex">
<a class="inline-flex items-center justify-between w-full px-2 py-1 text-sm font-semibold transition-colors duration-150 rounded-md hover:bg-gray-100 hover:text-gray-800 dark:hover:bg-gray-800 dark:hover:text-gray-200" href="#">
<span>Alerts</span>
</a>
</li>
</ul>
</template>
</li>
<!-- Profile menu -->
<li class="relative">
<button class="align-middle rounded-full focus:shadow-outline-purple focus:outline-none"
@click="toggleProfileMenu" @keydown.escape="closeProfileMenu"
aria-label="Account" aria-haspopup="true">
<img class="object-cover w-8 h-8 rounded-full"
src="https://images.unsplash.com/photo-1502378735452-bc7d86632805?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=aa3a807e1bbdfd4364d1f449eaa96d82"
alt="" aria-hidden="true"/>
</button>
<template x-if="isProfileMenuOpen">
<ul x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
@click.away="closeProfileMenu"
@keydown.escape="closeProfileMenu"
class="absolute right-0 w-56 p-2 mt-2 space-y-2 text-gray-600 bg-white border border-gray-100 rounded-md shadow-md dark:border-gray-700 dark:text-gray-300 dark:bg-gray-700"
aria-label="submenu">
<li class="flex">
<a class="inline-flex items-center w-full px-2 py-1 text-sm font-semibold transition-colors duration-150 rounded-md hover:bg-gray-100 hover:text-gray-800 dark:hover:bg-gray-800 dark:hover:text-gray-200" href="#">
<span x-html="$icon('user', 'w-4 h-4 mr-3')"></span>
<span>Profile</span>
</a>
</li>
<li class="flex">
<a class="inline-flex items-center w-full px-2 py-1 text-sm font-semibold transition-colors duration-150 rounded-md hover:bg-gray-100 hover:text-gray-800 dark:hover:bg-gray-800 dark:hover:text-gray-200" href="#">
<span x-html="$icon('cog', 'w-4 h-4 mr-3')"></span>
<span>Settings</span>
</a>
</li>
<li class="flex">
<a class="inline-flex items-center w-full px-2 py-1 text-sm font-semibold transition-colors duration-150 rounded-md hover:bg-gray-100 hover:text-gray-800 dark:hover:bg-gray-800 dark:hover:text-gray-200" href="/static/admin/login.html">
<span x-html="$icon('logout', 'w-4 h-4 mr-3')"></span>
<span>Log out</span>
</a>
</li>
</ul>
</template>
</li>
</ul>
</div>
</header>.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path>
<path d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
<span>Settings</span>
</a>
</li>
<li class="flex">
<a class="inline-flex items-center w-full px-2 py-1 text-sm font-semibold transition-colors duration-150 rounded-md hover:bg-gray-100 hover:text-gray-800 dark:hover:bg-gray-800 dark:hover:text-gray-200" href="/static/admin/login.html">
<!-- Heroicon: logout -->
<svg class="w-4 h-4 mr-3" aria-hidden="true" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" stroke="currentColor">
<path d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1"></path>
</svg>
<span>Log out</span>
</a>
</li>
</ul>
</template>
</li>
</ul>
</div>
</header>

View File

@@ -1,116 +0,0 @@
<!-- Desktop sidebar -->
<aside class="z-20 hidden w-64 overflow-y-auto bg-white dark:bg-gray-800 md:block flex-shrink-0">
<div class="py-4 text-gray-500 dark:text-gray-400">
<a class="ml-6 text-lg font-bold text-gray-800 dark:text-gray-200" href="/static/admin/dashboard.html">
Admin Portal
</a>
<ul class="mt-6">
<li class="relative px-6 py-3">
<span x-show="currentPage === 'dashboard'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'dashboard' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/static/admin/dashboard.html">
<span x-html="$icon('home')"></span>
<span class="ml-4">Dashboard</span>
</a>
</li>
</ul>
<ul>
<li class="relative px-6 py-3">
<span x-show="currentPage === 'vendors'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'vendors' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/static/admin/vendors.html">
<span x-html="$icon('shopping-bag')"></span>
<span class="ml-4">Vendors</span>
</a>
</li>
<li class="relative px-6 py-3">
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200" href="#">
<span x-html="$icon('users')"></span>
<span class="ml-4">Users</span>
</a>
</li>
<li class="relative px-6 py-3">
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200" href="#">
<span x-html="$icon('cube')"></span>
<span class="ml-4">Import Jobs</span>
</a>
</li>
</ul>
<div class="px-6 my-6">
<button class="flex items-center justify-between w-full px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-purple-600 border border-transparent rounded-lg active:bg-purple-600 hover:bg-purple-700 focus:outline-none focus:shadow-outline-purple">
Create vendor
<span class="ml-2" aria-hidden="true">+</span>
</button>
</div>
</div>
</aside>
<!-- Mobile sidebar -->
<!-- Backdrop -->
<div x-show="isSideMenuOpen"
x-transition:enter="transition ease-in-out duration-150"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in-out duration-150"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
class="fixed inset-0 z-10 flex items-end bg-black bg-opacity-50 sm:items-center sm:justify-center"></div>
<aside class="fixed inset-y-0 z-20 flex-shrink-0 w-64 mt-16 overflow-y-auto bg-white dark:bg-gray-800 md:hidden"
x-show="isSideMenuOpen"
x-transition:enter="transition ease-in-out duration-150"
x-transition:enter-start="opacity-0 transform -translate-x-20"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in-out duration-150"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0 transform -translate-x-20"
@click.away="closeSideMenu"
@keydown.escape="closeSideMenu">
<div class="py-4 text-gray-500 dark:text-gray-400">
<a class="ml-6 text-lg font-bold text-gray-800 dark:text-gray-200" href="/static/admin/dashboard.html">
Admin Portal
</a>
<ul class="mt-6">
<li class="relative px-6 py-3">
<span x-show="currentPage === 'dashboard'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'dashboard' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/static/admin/dashboard.html">
<span x-html="$icon('home')"></span>
<span class="ml-4">Dashboard</span>
</a>
</li>
</ul>
<ul>
<li class="relative px-6 py-3">
<span x-show="currentPage === 'vendors'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg" aria-hidden="true"></span>
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'vendors' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/static/admin/vendors.html">
<span x-html="$icon('shopping-bag')"></span>
<span class="ml-4">Vendors</span>
</a>
</li>
<li class="relative px-6 py-3">
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200" href="#">
<span x-html="$icon('users')"></span>
<span class="ml-4">Users</span>
</a>
</li>
<li class="relative px-6 py-3">
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200" href="#">
<span x-html="$icon('cube')"></span>
<span class="ml-4">Import Jobs</span>
</a>
</li>
</ul>
<div class="px-6 my-6">
<button class="flex items-center justify-between px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-purple-600 border border-transparent rounded-lg active:bg-purple-600 hover:bg-purple-700 focus:outline-none focus:shadow-outline-purple">
Create vendor
<span class="ml-2" aria-hidden="true">+</span>
</button>
</div>
</div>
</aside>