New Branch Structure

This commit is contained in:
Mark Gregory
2026-07-23 17:23:57 +01:00
commit 55bf5ea995
206 changed files with 23782 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
/* Dashboard backend theme
* The primary Tailwind bundle remains resources/css/app.css.
*/
:root {
--dashboard-sidebar-width: 16rem;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

+1
View File
@@ -0,0 +1 @@
// Dashboard backend theme JavaScript entry point.
+58
View File
@@ -0,0 +1,58 @@
{
"name": "Dashboard",
"slug": "admin",
"extends": "common",
"version": "1.0.0",
"author": "ABSDEV",
"description": "Backend-only Laravel Livewire and Flux dashboard theme.",
"entry_view": "dashboard",
"stylesheet": "css/theme.css",
"script": "js/app.js",
"type": "backend",
"views": true,
"livewire_views": true,
"supports": {
"dark_mode": true,
"animations": false,
"auth": false,
"preview": true,
"variants": true,
"settings": false,
"seo": false,
"export": true,
"accessibility_validation": true
},
"variables": {},
"preview": "images/preview.webp",
"variants": {
"light": {
"label": "Light",
"variables": {}
},
"dark": {
"label": "Dark",
"variables": {
"surface": "#18181b",
"surface-muted": "#27272a",
"text-primary": "#fafafa"
}
}
},
"settings": {
"site_title": {
"type": "text",
"label": "Dashboard title",
"default": "Dashboard"
},
"logo_url": {
"type": "url",
"label": "Logo URL",
"default": ""
},
"--brand-primary": {
"type": "color",
"label": "Primary colour",
"default": "#2563eb"
}
}
}
@@ -0,0 +1,34 @@
<x-layouts.app :title="__('Create user')">
<div class="mx-auto max-w-2xl space-y-6">
<div>
<h1 class="text-2xl font-semibold tracking-tight text-zinc-950 dark:text-zinc-100">Create user</h1>
<p class="mt-1 text-sm text-zinc-600 dark:text-zinc-400">Add a backend user and assign roles.</p>
</div>
<form method="POST" action="{{ route('administration.users.store') }}" class="space-y-5 rounded-xl border border-zinc-200 bg-white p-6 shadow-sm dark:border-zinc-700 dark:bg-zinc-900">
@csrf
<flux:input name="name" :label="__('Name')" :value="old('name')" required autofocus />
<flux:input name="email" type="email" :label="__('Email')" :value="old('email')" required />
<flux:input name="password" type="password" :label="__('Password')" required />
<flux:input name="password_confirmation" type="password" :label="__('Confirm password')" required />
<div class="space-y-2">
<div class="text-sm font-medium text-zinc-700 dark:text-zinc-300">Roles</div>
<div class="grid gap-2 sm:grid-cols-2">
@foreach ($roles as $role)
<label class="flex items-center gap-2 rounded-lg border border-zinc-200 px-3 py-2 text-sm dark:border-zinc-700">
<input type="checkbox" name="roles[]" value="{{ $role }}" @checked(in_array($role, old('roles', []), true))>
<span>{{ $role }}</span>
</label>
@endforeach
</div>
</div>
<div class="flex justify-end gap-3">
<flux:button :href="route('administration.users.index')" wire:navigate>Cancel</flux:button>
<flux:button variant="primary" type="submit">Create user</flux:button>
</div>
</form>
</div>
</x-layouts.app>
@@ -0,0 +1,35 @@
<x-layouts.app :title="__('Edit user')">
<div class="mx-auto max-w-2xl space-y-6">
<div>
<h1 class="text-2xl font-semibold tracking-tight text-zinc-950 dark:text-zinc-100">Edit user</h1>
<p class="mt-1 text-sm text-zinc-600 dark:text-zinc-400">Update account details and roles.</p>
</div>
<form method="POST" action="{{ route('administration.users.update', $user) }}" class="space-y-5 rounded-xl border border-zinc-200 bg-white p-6 shadow-sm dark:border-zinc-700 dark:bg-zinc-900">
@csrf
@method('PUT')
<flux:input name="name" :label="__('Name')" :value="old('name', $user->name)" required autofocus />
<flux:input name="email" type="email" :label="__('Email')" :value="old('email', $user->email)" required />
<flux:input name="password" type="password" :label="__('New password')" />
<flux:input name="password_confirmation" type="password" :label="__('Confirm new password')" />
<div class="space-y-2">
<div class="text-sm font-medium text-zinc-700 dark:text-zinc-300">Roles</div>
<div class="grid gap-2 sm:grid-cols-2">
@foreach ($roles as $role)
<label class="flex items-center gap-2 rounded-lg border border-zinc-200 px-3 py-2 text-sm dark:border-zinc-700">
<input type="checkbox" name="roles[]" value="{{ $role }}" @checked(in_array($role, old('roles', $user->roles->pluck('name')->all()), true))>
<span>{{ $role }}</span>
</label>
@endforeach
</div>
</div>
<div class="flex justify-end gap-3">
<flux:button :href="route('administration.users.index')" wire:navigate>Cancel</flux:button>
<flux:button variant="primary" type="submit">Save changes</flux:button>
</div>
</form>
</div>
</x-layouts.app>
@@ -0,0 +1,62 @@
<x-layouts.app :title="__('Users')">
<div class="space-y-6">
<div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
<div>
<h1 class="text-2xl font-semibold tracking-tight text-zinc-950 dark:text-zinc-100">Users</h1>
<p class="mt-1 text-sm text-zinc-600 dark:text-zinc-400">Create, edit and soft delete backend user accounts.</p>
</div>
<flux:button :href="route('administration.users.create')" variant="primary" wire:navigate>
Create user
</flux:button>
</div>
@if (session('status'))
<div class="rounded-xl border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm text-emerald-800 dark:border-emerald-900/60 dark:bg-emerald-950/40 dark:text-emerald-200">
{{ session('status') }}
</div>
@endif
<div class="overflow-hidden rounded-xl border border-zinc-200 bg-white shadow-sm dark:border-zinc-700 dark:bg-zinc-900">
<table class="min-w-full divide-y divide-zinc-200 text-sm dark:divide-zinc-700">
<thead class="bg-zinc-50 text-left text-xs font-semibold uppercase tracking-wide text-zinc-600 dark:bg-zinc-950 dark:text-zinc-400">
<tr>
<th class="px-4 py-3">Name</th>
<th class="px-4 py-3">Email</th>
<th class="px-4 py-3">Roles</th>
<th class="px-4 py-3 text-right">Actions</th>
</tr>
</thead>
<tbody class="divide-y divide-zinc-200 dark:divide-zinc-800">
@forelse ($users as $user)
<tr>
<td class="px-4 py-3 font-medium text-zinc-950 dark:text-zinc-100">{{ $user->name }}</td>
<td class="px-4 py-3 text-zinc-600 dark:text-zinc-400">{{ $user->email }}</td>
<td class="px-4 py-3 text-zinc-600 dark:text-zinc-400">
{{ $user->roles->pluck('name')->join(', ') ?: '—' }}
</td>
<td class="px-4 py-3">
<div class="flex justify-end gap-2">
<flux:button size="sm" :href="route('administration.users.edit', $user)" wire:navigate>Edit</flux:button>
<form method="POST" action="{{ route('administration.users.destroy', $user) }}">
@csrf
@method('DELETE')
<flux:button size="sm" variant="danger" type="submit">Delete</flux:button>
</form>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="4" class="px-4 py-8 text-center text-zinc-600 dark:text-zinc-400">No users found.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if (method_exists($users, 'links'))
{{ $users->links() }}
@endif
</div>
</x-layouts.app>
@@ -0,0 +1,35 @@
<div>
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300" for="name">Name</label>
<input id="name" name="name" value="{{ old('name', $user?->name) }}" class="mt-1 w-full rounded-lg border border-zinc-300 bg-white px-3 py-2 text-zinc-950 shadow-sm dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100" required>
@error('name') <p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p> @enderror
</div>
<div>
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300" for="email">Email</label>
<input id="email" name="email" type="email" value="{{ old('email', $user?->email) }}" class="mt-1 w-full rounded-lg border border-zinc-300 bg-white px-3 py-2 text-zinc-950 shadow-sm dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100" required>
@error('email') <p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p> @enderror
</div>
<div>
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300" for="password">Password</label>
<input id="password" name="password" type="password" class="mt-1 w-full rounded-lg border border-zinc-300 bg-white px-3 py-2 text-zinc-950 shadow-sm dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100" {{ $user ? '' : 'required' }}>
@error('password') <p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p> @enderror
</div>
<div>
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300" for="password_confirmation">Confirm password</label>
<input id="password_confirmation" name="password_confirmation" type="password" class="mt-1 w-full rounded-lg border border-zinc-300 bg-white px-3 py-2 text-zinc-950 shadow-sm dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100" {{ $user ? '' : 'required' }}>
</div>
<div>
<span class="block text-sm font-medium text-zinc-700 dark:text-zinc-300">Roles</span>
<div class="mt-2 space-y-2">
@foreach ($roles as $role)
<label class="flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300">
<input type="checkbox" name="roles[]" value="{{ $role->name }}" @checked(in_array($role->name, old('roles', $user?->roles->pluck('name')->all() ?? []), true)) class="rounded border-zinc-300 dark:border-zinc-700">
{{ $role->name }}
</label>
@endforeach
</div>
@error('roles') <p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p> @enderror
</div>
@@ -0,0 +1,12 @@
@props([
'id' => uniqid(),
])
<svg {{ $attributes }} fill="none">
<defs>
<pattern id="pattern-{{ $id }}" x="0" y="0" width="8" height="8" patternUnits="userSpaceOnUse">
<path d="M-1 5L5 -1M3 9L8.5 3.5" stroke-width="0.5"></path>
</pattern>
</defs>
<rect stroke="none" fill="url(#pattern-{{ $id }})" width="100%" height="100%"></rect>
</svg>
@@ -0,0 +1,18 @@
<x-layouts.app :title="__('Dashboard')">
<div class="flex h-full w-full flex-1 flex-col gap-4 rounded-xl">
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
<div class="relative aspect-video overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
<x-stylist-theme-admin::placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
</div>
<div class="relative aspect-video overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
<x-stylist-theme-admin::placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
</div>
<div class="relative aspect-video overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
<x-stylist-theme-admin::placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
</div>
</div>
<div class="relative h-full flex-1 overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
<x-stylist-theme-admin::placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
</div>
</div>
</x-layouts.app>
@@ -0,0 +1,47 @@
{{-- Credit: Lucide (https://lucide.dev) --}}
@props([
'variant' => 'outline',
])
@php
if ($variant === 'solid') {
throw new \Exception('The "solid" variant is not supported in Lucide.');
}
$classes = Flux::classes('shrink-0')->add(
match ($variant) {
'outline' => '[:where(&)]:size-6',
'solid' => '[:where(&)]:size-6',
'mini' => '[:where(&)]:size-5',
'micro' => '[:where(&)]:size-4',
},
);
$strokeWidth = match ($variant) {
'outline' => 2,
'mini' => 2.25,
'micro' => 2.5,
};
@endphp
<svg
{{ $attributes->class($classes) }}
data-flux-icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="{{ $strokeWidth }}"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
data-slot="icon"
>
<path d="M12 7v14" />
<path d="M16 12h2" />
<path d="M16 8h2" />
<path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" />
<path d="M6 12h2" />
<path d="M6 8h2" />
</svg>
@@ -0,0 +1,43 @@
{{-- Credit: Lucide (https://lucide.dev) --}}
@props([
'variant' => 'outline',
])
@php
if ($variant === 'solid') {
throw new \Exception('The "solid" variant is not supported in Lucide.');
}
$classes = Flux::classes('shrink-0')->add(
match ($variant) {
'outline' => '[:where(&)]:size-6',
'solid' => '[:where(&)]:size-6',
'mini' => '[:where(&)]:size-5',
'micro' => '[:where(&)]:size-4',
},
);
$strokeWidth = match ($variant) {
'outline' => 2,
'mini' => 2.25,
'micro' => 2.5,
};
@endphp
<svg
{{ $attributes->class($classes) }}
data-flux-icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="{{ $strokeWidth }}"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
data-slot="icon"
>
<path d="m7 15 5 5 5-5" />
<path d="m7 9 5-5 5 5" />
</svg>
@@ -0,0 +1,45 @@
{{-- Credit: Lucide (https://lucide.dev) --}}
@props([
'variant' => 'outline',
])
@php
if ($variant === 'solid') {
throw new \Exception('The "solid" variant is not supported in Lucide.');
}
$classes = Flux::classes('shrink-0')->add(
match ($variant) {
'outline' => '[:where(&)]:size-6',
'solid' => '[:where(&)]:size-6',
'mini' => '[:where(&)]:size-5',
'micro' => '[:where(&)]:size-4',
},
);
$strokeWidth = match ($variant) {
'outline' => 2,
'mini' => 2.25,
'micro' => 2.5,
};
@endphp
<svg
{{ $attributes->class($classes) }}
data-flux-icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="{{ $strokeWidth }}"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
data-slot="icon"
>
<path d="M9 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v5" />
<circle cx="13" cy="12" r="2" />
<path d="M18 19c-2.8 0-5-2.2-5-5v8" />
<circle cx="20" cy="19" r="2" />
</svg>
@@ -0,0 +1,45 @@
{{-- Credit: Lucide (https://lucide.dev) --}}
@props([
'variant' => 'outline',
])
@php
if ($variant === 'solid') {
throw new \Exception('The "solid" variant is not supported in Lucide.');
}
$classes = Flux::classes('shrink-0')->add(
match ($variant) {
'outline' => '[:where(&)]:size-6',
'solid' => '[:where(&)]:size-6',
'mini' => '[:where(&)]:size-5',
'micro' => '[:where(&)]:size-4',
},
);
$strokeWidth = match ($variant) {
'outline' => 2,
'mini' => 2.25,
'micro' => 2.5,
};
@endphp
<svg
{{ $attributes->class($classes) }}
data-flux-icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="{{ $strokeWidth }}"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
data-slot="icon"
>
<rect width="7" height="7" x="3" y="3" rx="1" />
<rect width="7" height="7" x="14" y="3" rx="1" />
<rect width="7" height="7" x="14" y="14" rx="1" />
<rect width="7" height="7" x="3" y="14" rx="1" />
</svg>
@@ -0,0 +1,51 @@
@props([
'expandable' => false,
'expanded' => true,
'heading' => null,
])
<?php if ($expandable && $heading): ?>
<ui-disclosure
{{ $attributes->class('group/disclosure') }}
@if ($expanded === true) open @endif
data-flux-navlist-group
>
<button
type="button"
class="group/disclosure-button mb-[2px] flex h-10 w-full items-center rounded-lg text-zinc-500 hover:bg-zinc-800/5 hover:text-zinc-800 lg:h-8 dark:text-white/80 dark:hover:bg-white/[7%] dark:hover:text-white"
>
<div class="ps-3 pe-4">
<flux:icon.chevron-down class="hidden size-3! group-data-open/disclosure-button:block" />
<flux:icon.chevron-right class="block size-3! group-data-open/disclosure-button:hidden" />
</div>
<span class="text-sm font-medium leading-none">{{ $heading }}</span>
</button>
<div class="relative hidden space-y-[2px] ps-7 data-open:block" @if ($expanded === true) data-open @endif>
<div class="absolute inset-y-[3px] start-0 ms-4 w-px bg-zinc-200 dark:bg-white/30"></div>
{{ $slot }}
</div>
</ui-disclosure>
<?php elseif ($heading): ?>
<div {{ $attributes->class('block space-y-[2px]') }}>
<div class="px-1 py-2">
<div class="text-xs leading-none text-zinc-400">{{ $heading }}</div>
</div>
<div>
{{ $slot }}
</div>
</div>
<?php else: ?>
<div {{ $attributes->class('block space-y-[2px]') }}>
{{ $slot }}
</div>
<?php endif; ?>