feat: Preline UI 改版與深色模式修復
All checks were successful
Star-Cloud-Deploy-System / deploy-demo (push) Successful in 35s
Star-Cloud-Deploy-System / deploy-production (push) Has been skipped

This commit is contained in:
2026-01-13 13:28:58 +08:00
parent 88c3678a4d
commit 74b6c71c95
20 changed files with 1053 additions and 909 deletions

View File

@@ -137,7 +137,7 @@ docker compose exec laravel.test php artisan migrate --seed
``` ```
> **預設管理員帳號** > **預設管理員帳號**
> - Email: `admin@star-cloud.com` > - Email: `admin`
> - Password: `password` > - Password: `password`
**4.4 安裝前端依賴** **4.4 安裝前端依賴**

2
package-lock.json generated
View File

@@ -12,7 +12,7 @@
"axios": "^1.6.4", "axios": "^1.6.4",
"laravel-vite-plugin": "^1.0.0", "laravel-vite-plugin": "^1.0.0",
"postcss": "^8.4.31", "postcss": "^8.4.31",
"preline": "^3.2.0", "preline": "^3.2.3",
"tailwindcss": "^3.1.0", "tailwindcss": "^3.1.0",
"vite": "^5.0.0" "vite": "^5.0.0"
} }

View File

@@ -13,7 +13,7 @@
"axios": "^1.6.4", "axios": "^1.6.4",
"laravel-vite-plugin": "^1.0.0", "laravel-vite-plugin": "^1.0.0",
"postcss": "^8.4.31", "postcss": "^8.4.31",
"preline": "^3.2.0", "preline": "^3.2.3",
"tailwindcss": "^3.1.0", "tailwindcss": "^3.1.0",
"vite": "^5.0.0" "vite": "^5.0.0"
} }

View File

@@ -2,17 +2,10 @@
@section('content') @section('content')
@php @php
$theme = request()->cookie('theme', 'dark-blue');
$isLight = in_array($theme, ['light-blue', 'light-green']);
$cardBg = $isLight ? 'bg-white' : 'bg-gray-800';
$textPrimary = $isLight ? 'text-gray-900' : 'text-gray-200';
$textSecondary = $isLight ? 'text-gray-600' : 'text-gray-400';
$borderColor = $isLight ? 'border-gray-200' : 'border-gray-700';
$inputBg = $isLight ? 'bg-gray-50 border-gray-300' : 'bg-gray-700 border-gray-600';
$inputText = $isLight ? 'text-gray-900' : 'text-gray-300'; $inputText = $isLight ? 'text-gray-900' : 'text-gray-300';
@endphp @endphp
<div class="container mx-auto px-6 py-8"> <div class="container mx-auto px-6 py-8">
<h3 class="{{ $textPrimary }} text-3xl font-medium">APP 管理設定</h3> <h3 class="text-gray-900 dark:text-gray-200 text-3xl font-medium">APP 管理設定</h3>
<div class="mt-8"> <div class="mt-8">
<form action="{{ route('admin.app-configs.update') }}" method="POST"> <form action="{{ route('admin.app-configs.update') }}" method="POST">
@@ -21,44 +14,44 @@
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- UI Settings --> <!-- UI Settings -->
<div class="{{ $cardBg }} rounded-lg shadow-xl overflow-hidden p-6"> <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6">
<h4 class="text-xl font-semibold {{ $textPrimary }} mb-4">UI 元素設定</h4> <h4 class="text-xl font-semibold text-gray-900 dark:text-gray-200 mb-4">UI 元素設定</h4>
<div class="space-y-4"> <div class="space-y-4">
<div> <div>
<label for="ui_primary_color" class="block text-sm font-medium {{ $textSecondary }}">主色調 (Hex)</label> <label for="ui_primary_color" class="block text-sm font-medium text-gray-600 dark:text-gray-400">主色調 (Hex)</label>
<input type="text" name="ui_primary_color" id="ui_primary_color" value="{{ $configs['ui']->where('key', 'ui_primary_color')->first()->value ?? '' }}" class="mt-1 block w-full {{ $inputBg }} rounded-md shadow-sm py-2 px-3 {{ $inputText }} focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <input type="text" name="ui_primary_color" id="ui_primary_color" value="{{ $configs['ui']->where('key', 'ui_primary_color')->first()->value ?? '' }}" class="mt-1 block w-full bg-white dark:bg-gray-700 rounded-md shadow-sm py-2 px-3 {{ $inputText }} focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
</div> </div>
<div> <div>
<label for="ui_logo_url" class="block text-sm font-medium {{ $textSecondary }}">Logo URL</label> <label for="ui_logo_url" class="block text-sm font-medium text-gray-600 dark:text-gray-400">Logo URL</label>
<input type="text" name="ui_logo_url" id="ui_logo_url" value="{{ $configs['ui']->where('key', 'ui_logo_url')->first()->value ?? '' }}" class="mt-1 block w-full {{ $inputBg }} rounded-md shadow-sm py-2 px-3 {{ $inputText }} focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <input type="text" name="ui_logo_url" id="ui_logo_url" value="{{ $configs['ui']->where('key', 'ui_logo_url')->first()->value ?? '' }}" class="mt-1 block w-full bg-white dark:bg-gray-700 rounded-md shadow-sm py-2 px-3 {{ $inputText }} focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
</div> </div>
</div> </div>
</div> </div>
<!-- Helper Settings --> <!-- Helper Settings -->
<div class="{{ $cardBg }} rounded-lg shadow-xl overflow-hidden p-6"> <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6">
<h4 class="text-xl font-semibold {{ $textPrimary }} mb-4">小幫手設定</h4> <h4 class="text-xl font-semibold text-gray-900 dark:text-gray-200 mb-4">小幫手設定</h4>
<div class="space-y-4"> <div class="space-y-4">
<div class="flex items-center"> <div class="flex items-center">
<input type="hidden" name="helper_enabled" value="0"> <input type="hidden" name="helper_enabled" value="0">
<input type="checkbox" name="helper_enabled" id="helper_enabled" value="1" {{ ($configs['helper']->where('key', 'helper_enabled')->first()->value ?? '0') == '1' ? 'checked' : '' }} class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded"> <input type="checkbox" name="helper_enabled" id="helper_enabled" value="1" {{ ($configs['helper']->where('key', 'helper_enabled')->first()->value ?? '0') == '1' ? 'checked' : '' }} class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded">
<label for="helper_enabled" class="ml-2 block text-sm {{ $textPrimary }}">啟用小幫手</label> <label for="helper_enabled" class="ml-2 block text-sm text-gray-900 dark:text-gray-200">啟用小幫手</label>
</div> </div>
</div> </div>
</div> </div>
<!-- Game Settings --> <!-- Game Settings -->
<div class="{{ $cardBg }} rounded-lg shadow-xl overflow-hidden p-6"> <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6">
<h4 class="text-xl font-semibold {{ $textPrimary }} mb-4">問卷與互動遊戲</h4> <h4 class="text-xl font-semibold text-gray-900 dark:text-gray-200 mb-4">問卷與互動遊戲</h4>
<div class="space-y-4"> <div class="space-y-4">
<div class="flex items-center"> <div class="flex items-center">
<input type="hidden" name="game_enabled" value="0"> <input type="hidden" name="game_enabled" value="0">
<input type="checkbox" name="game_enabled" id="game_enabled" value="1" {{ ($configs['game']->where('key', 'game_enabled')->first()->value ?? '0') == '1' ? 'checked' : '' }} class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded"> <input type="checkbox" name="game_enabled" id="game_enabled" value="1" {{ ($configs['game']->where('key', 'game_enabled')->first()->value ?? '0') == '1' ? 'checked' : '' }} class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded">
<label for="game_enabled" class="ml-2 block text-sm {{ $textPrimary }}">啟用互動遊戲</label> <label for="game_enabled" class="ml-2 block text-sm text-gray-900 dark:text-gray-200">啟用互動遊戲</label>
</div> </div>
<div> <div>
<label for="questionnaire_url" class="block text-sm font-medium {{ $textSecondary }}">問卷 URL</label> <label for="questionnaire_url" class="block text-sm font-medium text-gray-600 dark:text-gray-400">問卷 URL</label>
<input type="text" name="questionnaire_url" id="questionnaire_url" value="{{ $configs['game']->where('key', 'questionnaire_url')->first()->value ?? '' }}" class="mt-1 block w-full {{ $inputBg }} rounded-md shadow-sm py-2 px-3 {{ $inputText }} focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <input type="text" name="questionnaire_url" id="questionnaire_url" value="{{ $configs['game']->where('key', 'questionnaire_url')->first()->value ?? '' }}" class="mt-1 block w-full bg-white dark:bg-gray-700 rounded-md shadow-sm py-2 px-3 {{ $inputText }} focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,111 +1,165 @@
@extends('layouts.admin') @extends('layouts.admin')
@section('content') @section('content')
@php <div class="space-y-4 sm:space-y-6">
$theme = request()->cookie('theme', 'dark-blue'); <!-- Grid -->
$isLight = in_array($theme, ['light-blue', 'light-green']); <div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-6">
$cardBg = $isLight ? 'bg-white' : 'bg-gray-800'; <!-- Card -->
$textPrimary = $isLight ? 'text-gray-900' : 'text-gray-200'; <div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-gray-800 dark:border-gray-700">
$textSecondary = $isLight ? 'text-gray-600' : 'text-gray-400'; <div class="p-4 md:p-5">
$borderColor = $isLight ? 'border-gray-200' : 'border-gray-700'; <div class="flex items-center gap-x-2">
@endphp <p class="text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400">
<div class="container mx-auto px-6 py-8"> 總銷售額
<h3 class="{{ $textPrimary }} text-3xl font-medium">儀表板</h3> </p>
<div class="hs-tooltip">
<div class="mt-4"> <div class="hs-tooltip-toggle">
<div class="flex flex-wrap -mx-6"> <svg class="flex-shrink-0 w-4 h-4 text-gray-500" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>
<!-- Total Machines --> <span class="hs-tooltip-content hs-tooltip-shown:opacity-100 hs-tooltip-shown:visible opacity-0 transition-opacity inline-block absolute invisible z-10 py-1 px-2 bg-gray-900 text-xs font-medium text-white rounded shadow-sm dark:bg-slate-700" role="tooltip">
<div class="w-full px-6 sm:w-1/2 xl:w-1/4"> 本月累計銷售總額
<div class="flex items-center px-5 py-6 shadow-sm rounded-md {{ $cardBg }}"> </span>
<div class="p-3 rounded-full bg-indigo-600 bg-opacity-75">
<svg class="h-8 w-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z" />
</svg>
</div>
<div class="mx-5">
<h4 class="text-2xl font-semibold {{ $textPrimary }}">{{ $totalMachines }}</h4>
<div class="{{ $textSecondary }}">總機台數</div>
</div> </div>
</div> </div>
</div> </div>
<!-- Online Machines --> <div class="mt-1 flex items-center gap-x-2">
<div class="w-full px-6 sm:w-1/2 xl:w-1/4 mt-6 sm:mt-0"> <h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
<div class="flex items-center px-5 py-6 shadow-sm rounded-md {{ $cardBg }}"> $72,540
<div class="p-3 rounded-full bg-green-600 bg-opacity-75"> </h3>
<svg class="h-8 w-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <span class="flex items-center gap-x-1 text-green-600">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" /> <svg class="inline-block w-4 h-4 self-center" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/></svg>
</svg> <span class="inline-block text-sm">
</div> 1.7%
<div class="mx-5"> </span>
<h4 class="text-2xl font-semibold {{ $textPrimary }}">{{ $onlineMachines }}</h4> </span>
<div class="{{ $textSecondary }}">連線中</div>
</div> </div>
</div> </div>
</div> </div>
<!-- End Card -->
<!-- Card -->
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-gray-800 dark:border-gray-700">
<div class="p-4 md:p-5">
<div class="flex items-center gap-x-2">
<p class="text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400">
活躍機台
</p>
</div>
<!-- Offline Machines --> <div class="mt-1 flex items-center gap-x-2">
<div class="w-full px-6 sm:w-1/2 xl:w-1/4 mt-6 xl:mt-0"> <h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
<div class="flex items-center px-5 py-6 shadow-sm rounded-md {{ $cardBg }}"> 124
<div class="p-3 rounded-full bg-gray-600 bg-opacity-75"> </h3>
<svg class="h-8 w-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <span class="flex items-center gap-x-1 text-red-600">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636" /> <svg class="inline-block w-4 h-4 self-center" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 17 13.5 8.5 8.5 13.5 2 7"/><polyline points="16 17 22 17 22 11"/></svg>
</svg> <span class="inline-block text-sm">
</div> 0.3%
<div class="mx-5"> </span>
<h4 class="text-2xl font-semibold {{ $textPrimary }}">{{ $offlineMachines }}</h4> </span>
<div class="{{ $textSecondary }}">離線</div>
</div> </div>
</div> </div>
</div> </div>
<!-- End Card -->
<!-- Card -->
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-gray-800 dark:border-gray-700">
<div class="p-4 md:p-5">
<div class="flex items-center gap-x-2">
<p class="text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400">
庫存警告
</p>
</div>
<!-- Error Machines --> <div class="mt-1 flex items-center gap-x-2">
<div class="w-full px-6 sm:w-1/2 xl:w-1/4 mt-6 xl:mt-0"> <h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
<div class="flex items-center px-5 py-6 shadow-sm rounded-md {{ $cardBg }}"> 12
<div class="p-3 rounded-full bg-red-600 bg-opacity-75"> </h3>
<svg class="h-8 w-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
</div>
<div class="mx-5">
<h4 class="text-2xl font-semibold {{ $textPrimary }}">{{ $errorMachines }}</h4>
<div class="{{ $textSecondary }}">異常</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<!-- End Card -->
<!-- Card -->
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-gray-800 dark:border-gray-700">
<div class="p-4 md:p-5">
<div class="flex items-center gap-x-2">
<p class="text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400">
本月新增會員
</p>
</div> </div>
<div class="mt-8"> <div class="mt-1 flex items-center gap-x-2">
<div class="flex flex-col mt-8"> <h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8"> 28
<div class="align-middle inline-block min-w-full shadow overflow-hidden sm:rounded-lg border-b {{ $borderColor }}"> </h3>
<!-- 這裡可以放最近的銷售紀錄或日誌 -->
<table class="min-w-full">
<thead>
<tr>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $cardBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider">標題</th>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $cardBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider">狀態</th>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $cardBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider">時間</th>
</tr>
</thead>
<tbody class="{{ $cardBg }}">
<tr>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }}">
<div class="text-sm leading-5 {{ $textPrimary }}">系統初始化</div>
</td>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }}">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">正常</span>
</td>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }} text-sm leading-5 {{ $textSecondary }}">
剛剛
</td>
</tr>
</tbody>
</table>
</div> </div>
</div> </div>
</div> </div>
<!-- End Card -->
</div>
<!-- End Grid -->
<div class="grid lg:grid-cols-2 gap-4 sm:gap-6">
<!-- Card -->
<div class="p-4 md:p-5 min-h-[410px] flex flex-col bg-white border shadow-sm rounded-xl dark:bg-gray-800 dark:border-gray-700">
<!-- Header -->
<div class="flex justify-between items-center">
<div>
<h2 class="text-sm text-gray-500 dark:text-gray-400">
營收趨勢
</h2>
<p class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
$123,450
</p>
</div>
<div>
<span class="py-[5px] px-1.5 inline-flex items-center gap-x-1 text-xs font-medium rounded-md bg-teal-100 text-teal-800 dark:bg-teal-500/10 dark:text-teal-500">
<svg class="inline-block w-3.5 h-3.5" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14"/><path d="m19 12-7 7-7-7"/></svg>
25%
</span>
</div>
</div>
<!-- End Header -->
<div id="hs-multiple-bar-charts"></div>
</div>
<!-- End Card -->
<!-- Card -->
<div class="p-4 md:p-5 min-h-[410px] flex flex-col bg-white border shadow-sm rounded-xl dark:bg-gray-800 dark:border-gray-700">
<!-- Header -->
<div class="flex justify-between items-center">
<div>
<h2 class="text-sm text-gray-500 dark:text-gray-400">
訪客分析
</h2>
<p class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
92,913
</p>
</div>
<div>
<span class="py-[5px] px-1.5 inline-flex items-center gap-x-1 text-xs font-medium rounded-md bg-red-100 text-red-800 dark:bg-red-500/10 dark:text-red-500">
<svg class="inline-block w-3.5 h-3.5" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14"/><path d="m19 12-7 7-7-7"/></svg>
11%
</span>
</div>
</div>
<!-- End Header -->
<div id="hs-single-area-chart"></div>
</div>
<!-- End Card -->
</div> </div>
</div> </div>
@endsection @endsection
@section('scripts')
<script>
window.addEventListener('load', () => {
// Here you would initialize charts using ApexCharts or similar,
// as Preline examples often use ApexCharts.
// For now, placeholders are sufficient.
});
</script>
@endsection

View File

@@ -2,15 +2,6 @@
@section('content') @section('content')
@php @php
$theme = request()->cookie('theme', 'dark-blue');
$isLight = in_array($theme, ['light-blue', 'light-green']);
$cardBg = $isLight ? 'bg-white' : 'bg-gray-800';
$textPrimary = $isLight ? 'text-gray-900' : 'text-gray-200';
$textSecondary = $isLight ? 'text-gray-600' : 'text-gray-400';
$borderColor = $isLight ? 'border-gray-200' : 'border-gray-700';
$thBg = $isLight ? 'bg-gray-50' : 'bg-gray-700';
$inputBg = $isLight ? 'bg-white' : 'bg-gray-700';
$inputBorder = $isLight ? 'border-gray-300' : 'border-gray-600';
@endphp @endphp
{{-- Toast 通知 --}} {{-- Toast 通知 --}}
@@ -35,31 +26,31 @@
<div class="container mx-auto px-6 py-8"> <div class="container mx-auto px-6 py-8">
<div class="flex justify-between items-center mb-6"> <div class="flex justify-between items-center mb-6">
<h3 class="{{ $textPrimary }} text-3xl font-medium">儲值回饋設定</h3> <h3 class="text-gray-900 dark:text-gray-200 text-3xl font-medium">儲值回饋設定</h3>
<button onclick="document.getElementById('createModal').classList.remove('hidden')" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700"> <button onclick="document.getElementById('createModal').classList.remove('hidden')" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700">
新增規則 新增規則
</button> </button>
</div> </div>
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="min-w-full {{ $cardBg }} rounded-lg overflow-hidden"> <table class="min-w-full bg-white dark:bg-gray-800 rounded-lg overflow-hidden">
<thead class="{{ $thBg }}"> <thead class="bg-gray-100 dark:bg-gray-700">
<tr> <tr>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">名稱</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">名稱</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">最低儲值</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">最低儲值</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">回饋類型</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">回饋類型</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">回饋值</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">回饋值</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">狀態</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">狀態</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">操作</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">操作</th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y {{ $borderColor }}"> <tbody class="divide-y border-gray-200 dark:border-gray-700">
@forelse($rules as $rule) @forelse($rules as $rule)
<tr> <tr>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $rule->name }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $rule->name }}</td>
<td class="px-6 py-4 {{ $textPrimary }}">${{ number_format($rule->min_amount) }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">${{ number_format($rule->min_amount) }}</td>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $rule->bonus_type == 'fixed' ? '固定金額' : '百分比' }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $rule->bonus_type == 'fixed' ? '固定金額' : '百分比' }}</td>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $rule->bonus_type == 'fixed' ? '$'.number_format($rule->bonus_value) : $rule->bonus_value.'%' }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $rule->bonus_type == 'fixed' ? '$'.number_format($rule->bonus_value) : $rule->bonus_value.'%' }}</td>
<td class="px-6 py-4"> <td class="px-6 py-4">
@if($rule->is_active) @if($rule->is_active)
<span class="px-2 py-1 rounded-full bg-green-100 text-green-800 text-xs">啟用</span> <span class="px-2 py-1 rounded-full bg-green-100 text-green-800 text-xs">啟用</span>
@@ -77,7 +68,7 @@
</tr> </tr>
@empty @empty
<tr> <tr>
<td colspan="6" class="px-6 py-4 text-center {{ $textSecondary }}">尚無資料</td> <td colspan="6" class="px-6 py-4 text-center text-gray-600 dark:text-gray-400">尚無資料</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>
@@ -90,39 +81,39 @@
<div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:p-0"> <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:p-0">
<div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" onclick="document.getElementById('createModal').classList.add('hidden')"></div> <div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" onclick="document.getElementById('createModal').classList.add('hidden')"></div>
<div class="relative {{ $cardBg }} rounded-lg shadow-xl transform transition-all sm:max-w-lg sm:w-full mx-4"> <div class="relative bg-white dark:bg-gray-800 rounded-lg shadow-xl transform transition-all sm:max-w-lg sm:w-full mx-4">
<div class="px-6 py-4 border-b {{ $borderColor }}"> <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
<h3 class="{{ $textPrimary }} text-lg font-semibold">新增儲值回饋規則</h3> <h3 class="text-gray-900 dark:text-gray-200 text-lg font-semibold">新增儲值回饋規則</h3>
</div> </div>
<form action="{{ route('admin.deposit-bonus-rules.store') }}" method="POST"> <form action="{{ route('admin.deposit-bonus-rules.store') }}" method="POST">
@csrf @csrf
<div class="px-6 py-4 space-y-4"> <div class="px-6 py-4 space-y-4">
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">名稱</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">名稱</label>
<input type="text" name="name" required class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="text" name="name" required class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">最低儲值金額</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">最低儲值金額</label>
<input type="number" name="min_amount" value="0" step="0.01" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="number" name="min_amount" value="0" step="0.01" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">回饋類型</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">回饋類型</label>
<select name="bonus_type" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <select name="bonus_type" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
<option value="fixed">固定金額</option> <option value="fixed">固定金額</option>
<option value="percentage">百分比</option> <option value="percentage">百分比</option>
</select> </select>
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">回饋值</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">回饋值</label>
<input type="number" name="bonus_value" value="0" step="0.01" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="number" name="bonus_value" value="0" step="0.01" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<input type="checkbox" name="is_active" value="1" checked id="is_active" class="mr-2 rounded text-indigo-600 focus:ring-indigo-500"> <input type="checkbox" name="is_active" value="1" checked id="is_active" class="mr-2 rounded text-indigo-600 focus:ring-indigo-500">
<label for="is_active" class="{{ $textSecondary }} text-sm">啟用</label> <label for="is_active" class="text-gray-600 dark:text-gray-400 text-sm">啟用</label>
</div> </div>
</div> </div>
<div class="px-6 py-4 border-t {{ $borderColor }} flex justify-end space-x-3"> <div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-3">
<button type="button" onclick="document.getElementById('createModal').classList.add('hidden')" class="px-4 py-2 {{ $textSecondary }} border {{ $inputBorder }} rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">取消</button> <button type="button" onclick="document.getElementById('createModal').classList.add('hidden')" class="px-4 py-2 text-gray-600 dark:text-gray-400 border border-gray-300 dark:border-gray-600 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">取消</button>
<button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">建立</button> <button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">建立</button>
</div> </div>
</form> </form>

View File

@@ -2,16 +2,6 @@
@section('content') @section('content')
@php @php
$theme = request()->cookie('theme', 'dark-blue');
$isLight = in_array($theme, ['light-blue', 'light-green']);
$cardBg = $isLight ? 'bg-white' : 'bg-gray-800';
$textPrimary = $isLight ? 'text-gray-900' : 'text-gray-200';
$textSecondary = $isLight ? 'text-gray-600' : 'text-gray-400';
$borderColor = $isLight ? 'border-gray-200' : 'border-gray-700';
$thBg = $isLight ? 'bg-gray-50' : 'bg-gray-700';
$inputBg = $isLight ? 'bg-white' : 'bg-gray-700';
$inputBorder = $isLight ? 'border-gray-300' : 'border-gray-600';
$typeLabels = [ $typeLabels = [
'points' => '點數', 'points' => '點數',
'coupon' => '優惠券', 'coupon' => '優惠券',
@@ -51,33 +41,33 @@
<div class="container mx-auto px-6 py-8"> <div class="container mx-auto px-6 py-8">
<div class="flex justify-between items-center mb-6"> <div class="flex justify-between items-center mb-6">
<h3 class="{{ $textPrimary }} text-3xl font-medium">禮品設定</h3> <h3 class="text-gray-900 dark:text-gray-200 text-3xl font-medium">禮品設定</h3>
<button onclick="document.getElementById('createModal').classList.remove('hidden')" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700"> <button onclick="document.getElementById('createModal').classList.remove('hidden')" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700">
新增禮品 新增禮品
</button> </button>
</div> </div>
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="min-w-full {{ $cardBg }} rounded-lg overflow-hidden"> <table class="min-w-full bg-white dark:bg-gray-800 rounded-lg overflow-hidden">
<thead class="{{ $thBg }}"> <thead class="bg-gray-100 dark:bg-gray-700">
<tr> <tr>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">名稱</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">名稱</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">類型</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">類型</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">數值</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">數值</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">適用等級</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">適用等級</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">觸發條件</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">觸發條件</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">狀態</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">狀態</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">操作</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">操作</th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y {{ $borderColor }}"> <tbody class="divide-y border-gray-200 dark:border-gray-700">
@forelse($gifts as $gift) @forelse($gifts as $gift)
<tr> <tr>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $gift->name }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $gift->name }}</td>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $typeLabels[$gift->type] ?? $gift->type }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $typeLabels[$gift->type] ?? $gift->type }}</td>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $gift->value }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $gift->value }}</td>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $gift->tier?->name ?? '全部' }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $gift->tier?->name ?? '全部' }}</td>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $triggerLabels[$gift->trigger] ?? $gift->trigger }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $triggerLabels[$gift->trigger] ?? $gift->trigger }}</td>
<td class="px-6 py-4"> <td class="px-6 py-4">
@if($gift->is_active) @if($gift->is_active)
<span class="px-2 py-1 rounded-full bg-green-100 text-green-800 text-xs">啟用</span> <span class="px-2 py-1 rounded-full bg-green-100 text-green-800 text-xs">啟用</span>
@@ -95,7 +85,7 @@
</tr> </tr>
@empty @empty
<tr> <tr>
<td colspan="7" class="px-6 py-4 text-center {{ $textSecondary }}">尚無資料</td> <td colspan="7" class="px-6 py-4 text-center text-gray-600 dark:text-gray-400">尚無資料</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>
@@ -108,32 +98,32 @@
<div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:p-0"> <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:p-0">
<div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" onclick="document.getElementById('createModal').classList.add('hidden')"></div> <div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" onclick="document.getElementById('createModal').classList.add('hidden')"></div>
<div class="relative {{ $cardBg }} rounded-lg shadow-xl transform transition-all sm:max-w-lg sm:w-full mx-4"> <div class="relative bg-white dark:bg-gray-800 rounded-lg shadow-xl transform transition-all sm:max-w-lg sm:w-full mx-4">
<div class="px-6 py-4 border-b {{ $borderColor }}"> <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
<h3 class="{{ $textPrimary }} text-lg font-semibold">新增禮品</h3> <h3 class="text-gray-900 dark:text-gray-200 text-lg font-semibold">新增禮品</h3>
</div> </div>
<form action="{{ route('admin.gift-definitions.store') }}" method="POST"> <form action="{{ route('admin.gift-definitions.store') }}" method="POST">
@csrf @csrf
<div class="px-6 py-4 space-y-4"> <div class="px-6 py-4 space-y-4">
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">名稱</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">名稱</label>
<input type="text" name="name" required class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="text" name="name" required class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">類型</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">類型</label>
<select name="type" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <select name="type" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
@foreach($typeLabels as $key => $label) @foreach($typeLabels as $key => $label)
<option value="{{ $key }}">{{ $label }}</option> <option value="{{ $key }}">{{ $label }}</option>
@endforeach @endforeach
</select> </select>
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">數值</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">數值</label>
<input type="number" name="value" value="0" step="0.01" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="number" name="value" value="0" step="0.01" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">適用等級</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">適用等級</label>
<select name="tier_id" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <select name="tier_id" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
<option value="">全部</option> <option value="">全部</option>
@foreach($tiers as $tier) @foreach($tiers as $tier)
<option value="{{ $tier->id }}">{{ $tier->name }}</option> <option value="{{ $tier->id }}">{{ $tier->name }}</option>
@@ -141,24 +131,24 @@
</select> </select>
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">觸發條件</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">觸發條件</label>
<select name="trigger" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <select name="trigger" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
@foreach($triggerLabels as $key => $label) @foreach($triggerLabels as $key => $label)
<option value="{{ $key }}">{{ $label }}</option> <option value="{{ $key }}">{{ $label }}</option>
@endforeach @endforeach
</select> </select>
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">有效天數</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">有效天數</label>
<input type="number" name="validity_days" value="30" min="1" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="number" name="validity_days" value="30" min="1" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<input type="checkbox" name="is_active" value="1" checked id="is_active" class="mr-2 rounded text-indigo-600 focus:ring-indigo-500"> <input type="checkbox" name="is_active" value="1" checked id="is_active" class="mr-2 rounded text-indigo-600 focus:ring-indigo-500">
<label for="is_active" class="{{ $textSecondary }} text-sm">啟用</label> <label for="is_active" class="text-gray-600 dark:text-gray-400 text-sm">啟用</label>
</div> </div>
</div> </div>
<div class="px-6 py-4 border-t {{ $borderColor }} flex justify-end space-x-3"> <div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-3">
<button type="button" onclick="document.getElementById('createModal').classList.add('hidden')" class="px-4 py-2 {{ $textSecondary }} border {{ $inputBorder }} rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">取消</button> <button type="button" onclick="document.getElementById('createModal').classList.add('hidden')" class="px-4 py-2 text-gray-600 dark:text-gray-400 border border-gray-300 dark:border-gray-600 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">取消</button>
<button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">建立</button> <button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">建立</button>
</div> </div>
</form> </form>

View File

@@ -2,27 +2,27 @@
@section('content') @section('content')
<div class="container mx-auto px-6 py-8"> <div class="container mx-auto px-6 py-8">
<h3 class="text-gray-300 text-3xl font-medium">新增機台</h3> <h3 class="text-gray-900 dark:text-gray-300 text-3xl font-medium">新增機台</h3>
<div class="mt-8"> <div class="mt-8">
<form action="{{ route('admin.machines.store') }}" method="POST" class="bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6 space-y-6"> <form action="{{ route('admin.machines.store') }}" method="POST" class="bg-white dark:bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6 space-y-6">
@csrf @csrf
<div> <div>
<label for="name" class="block text-sm font-medium text-gray-400">機台名稱</label> <label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-400">機台名稱</label>
<input type="text" name="name" id="name" class="mt-1 block w-full bg-gray-700 border border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" required> <input type="text" name="name" id="name" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" required>
@error('name') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror @error('name') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div> </div>
<div> <div>
<label for="location" class="block text-sm font-medium text-gray-400">位置</label> <label for="location" class="block text-sm font-medium text-gray-700 dark:text-gray-400">位置</label>
<input type="text" name="location" id="location" class="mt-1 block w-full bg-gray-700 border border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <input type="text" name="location" id="location" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('location') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror @error('location') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div> </div>
<div> <div>
<label for="status" class="block text-sm font-medium text-gray-400">狀態</label> <label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-400">狀態</label>
<select name="status" id="status" class="mt-1 block w-full bg-gray-700 border border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <select name="status" id="status" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
<option value="offline">離線</option> <option value="offline">離線</option>
<option value="online">連線中</option> <option value="online">連線中</option>
<option value="error">異常</option> <option value="error">異常</option>
@@ -31,19 +31,19 @@
</div> </div>
<div> <div>
<label for="temperature" class="block text-sm font-medium text-gray-400">溫度 (°C)</label> <label for="temperature" class="block text-sm font-medium text-gray-700 dark:text-gray-400">溫度 (°C)</label>
<input type="number" step="0.1" name="temperature" id="temperature" class="mt-1 block w-full bg-gray-700 border border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <input type="number" step="0.1" name="temperature" id="temperature" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('temperature') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror @error('temperature') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div> </div>
<div> <div>
<label for="firmware_version" class="block text-sm font-medium text-gray-400">韌體版本</label> <label for="firmware_version" class="block text-sm font-medium text-gray-700 dark:text-gray-400">韌體版本</label>
<input type="text" name="firmware_version" id="firmware_version" class="mt-1 block w-full bg-gray-700 border border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <input type="text" name="firmware_version" id="firmware_version" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('firmware_version') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror @error('firmware_version') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div> </div>
<div class="flex justify-end"> <div class="flex justify-end">
<a href="{{ route('admin.machines.index') }}" class="bg-gray-600 hover:bg-gray-500 text-white font-bold py-2 px-4 rounded mr-2">取消</a> <a href="{{ route('admin.machines.index') }}" class="bg-gray-200 dark:bg-gray-600 hover:bg-gray-300 dark:hover:bg-gray-500 text-gray-800 dark:text-white font-bold py-2 px-4 rounded mr-2">取消</a>
<button type="submit" class="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded">建立</button> <button type="submit" class="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded">建立</button>
</div> </div>
</form> </form>

View File

@@ -2,28 +2,28 @@
@section('content') @section('content')
<div class="container mx-auto px-6 py-8"> <div class="container mx-auto px-6 py-8">
<h3 class="text-gray-300 text-3xl font-medium">編輯機台</h3> <h3 class="text-gray-900 dark:text-gray-300 text-3xl font-medium">編輯機台</h3>
<div class="mt-8"> <div class="mt-8">
<form action="{{ route('admin.machines.update', $machine) }}" method="POST" class="bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6 space-y-6"> <form action="{{ route('admin.machines.update', $machine) }}" method="POST" class="bg-white dark:bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6 space-y-6">
@csrf @csrf
@method('PUT') @method('PUT')
<div> <div>
<label for="name" class="block text-sm font-medium text-gray-400">機台名稱</label> <label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-400">機台名稱</label>
<input type="text" name="name" id="name" value="{{ old('name', $machine->name) }}" class="mt-1 block w-full bg-gray-700 border border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" required> <input type="text" name="name" id="name" value="{{ old('name', $machine->name) }}" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" required>
@error('name') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror @error('name') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div> </div>
<div> <div>
<label for="location" class="block text-sm font-medium text-gray-400">位置</label> <label for="location" class="block text-sm font-medium text-gray-700 dark:text-gray-400">位置</label>
<input type="text" name="location" id="location" value="{{ old('location', $machine->location) }}" class="mt-1 block w-full bg-gray-700 border border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <input type="text" name="location" id="location" value="{{ old('location', $machine->location) }}" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('location') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror @error('location') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div> </div>
<div> <div>
<label for="status" class="block text-sm font-medium text-gray-400">狀態</label> <label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-400">狀態</label>
<select name="status" id="status" class="mt-1 block w-full bg-gray-700 border border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <select name="status" id="status" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
<option value="offline" {{ $machine->status == 'offline' ? 'selected' : '' }}>離線</option> <option value="offline" {{ $machine->status == 'offline' ? 'selected' : '' }}>離線</option>
<option value="online" {{ $machine->status == 'online' ? 'selected' : '' }}>連線中</option> <option value="online" {{ $machine->status == 'online' ? 'selected' : '' }}>連線中</option>
<option value="error" {{ $machine->status == 'error' ? 'selected' : '' }}>異常</option> <option value="error" {{ $machine->status == 'error' ? 'selected' : '' }}>異常</option>
@@ -32,19 +32,19 @@
</div> </div>
<div> <div>
<label for="temperature" class="block text-sm font-medium text-gray-400">溫度 (°C)</label> <label for="temperature" class="block text-sm font-medium text-gray-700 dark:text-gray-400">溫度 (°C)</label>
<input type="number" step="0.1" name="temperature" id="temperature" value="{{ old('temperature', $machine->temperature) }}" class="mt-1 block w-full bg-gray-700 border border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <input type="number" step="0.1" name="temperature" id="temperature" value="{{ old('temperature', $machine->temperature) }}" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('temperature') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror @error('temperature') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div> </div>
<div> <div>
<label for="firmware_version" class="block text-sm font-medium text-gray-400">韌體版本</label> <label for="firmware_version" class="block text-sm font-medium text-gray-700 dark:text-gray-400">韌體版本</label>
<input type="text" name="firmware_version" id="firmware_version" value="{{ old('firmware_version', $machine->firmware_version) }}" class="mt-1 block w-full bg-gray-700 border border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <input type="text" name="firmware_version" id="firmware_version" value="{{ old('firmware_version', $machine->firmware_version) }}" class="mt-1 block w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 text-gray-900 dark:text-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('firmware_version') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror @error('firmware_version') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div> </div>
<div class="flex justify-end"> <div class="flex justify-end">
<a href="{{ route('admin.machines.index') }}" class="bg-gray-600 hover:bg-gray-500 text-white font-bold py-2 px-4 rounded mr-2">取消</a> <a href="{{ route('admin.machines.index') }}" class="bg-gray-200 dark:bg-gray-600 hover:bg-gray-300 dark:hover:bg-gray-500 text-gray-800 dark:text-white font-bold py-2 px-4 rounded mr-2">取消</a>
<button type="submit" class="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded">更新</button> <button type="submit" class="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded">更新</button>
</div> </div>
</form> </form>

View File

@@ -2,16 +2,10 @@
@section('content') @section('content')
@php @php
$theme = request()->cookie('theme', 'dark-blue');
$isLight = in_array($theme, ['light-blue', 'light-green']);
$cardBg = $isLight ? 'bg-white' : 'bg-gray-800';
$textPrimary = $isLight ? 'text-gray-900' : 'text-gray-200';
$textSecondary = $isLight ? 'text-gray-600' : 'text-gray-400';
$borderColor = $isLight ? 'border-gray-200' : 'border-gray-700';
@endphp @endphp
<div class="container mx-auto px-6 py-8"> <div class="container mx-auto px-6 py-8">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<h3 class="{{ $textPrimary }} text-3xl font-medium">機台管理</h3> <h3 class="text-gray-900 dark:text-gray-200 text-3xl font-medium">機台管理</h3>
<a href="{{ route('admin.machines.create') }}" class="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded"> <a href="{{ route('admin.machines.create') }}" class="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded">
新增機台 新增機台
</a> </a>
@@ -20,28 +14,28 @@
<div class="mt-8"> <div class="mt-8">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8"> <div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
<div class="align-middle inline-block min-w-full shadow overflow-hidden sm:rounded-lg border-b {{ $borderColor }}"> <div class="align-middle inline-block min-w-full shadow overflow-hidden sm:rounded-lg border-b border-gray-200 dark:border-gray-700">
<table class="min-w-full"> <table class="min-w-full">
<thead> <thead>
<tr> <tr>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $cardBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider">名稱</th> <th class="px-6 py-3 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-left text-xs leading-4 font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">名稱</th>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $cardBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider">位置</th> <th class="px-6 py-3 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-left text-xs leading-4 font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">位置</th>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $cardBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider">狀態</th> <th class="px-6 py-3 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-left text-xs leading-4 font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">狀態</th>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $cardBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider">溫度</th> <th class="px-6 py-3 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-left text-xs leading-4 font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">溫度</th>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $cardBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider">最後心跳</th> <th class="px-6 py-3 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-left text-xs leading-4 font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">最後心跳</th>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $cardBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider">操作</th> <th class="px-6 py-3 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-left text-xs leading-4 font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">操作</th>
</tr> </tr>
</thead> </thead>
<tbody class="{{ $cardBg }}"> <tbody class="bg-white dark:bg-gray-800">
@foreach($machines as $machine) @foreach($machines as $machine)
<tr> <tr>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }}"> <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700">
<div class="text-sm leading-5 font-medium {{ $textPrimary }}">{{ $machine->name }}</div> <div class="text-sm leading-5 font-medium text-gray-900 dark:text-gray-200">{{ $machine->name }}</div>
</td> </td>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }}"> <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700">
<div class="text-sm leading-5 {{ $textSecondary }}">{{ $machine->location ?? '-' }}</div> <div class="text-sm leading-5 text-gray-600 dark:text-gray-400">{{ $machine->location ?? '-' }}</div>
</td> </td>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }}"> <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700">
@if($machine->status === 'online') @if($machine->status === 'online')
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">連線中</span> <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">連線中</span>
@elseif($machine->status === 'offline') @elseif($machine->status === 'offline')
@@ -50,13 +44,13 @@
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">異常</span> <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">異常</span>
@endif @endif
</td> </td>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }}"> <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700">
<div class="text-sm leading-5 {{ $textSecondary }}">{{ $machine->temperature ? $machine->temperature . '°C' : '-' }}</div> <div class="text-sm leading-5 text-gray-600 dark:text-gray-400">{{ $machine->temperature ? $machine->temperature . '°C' : '-' }}</div>
</td> </td>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }}"> <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700">
<div class="text-sm leading-5 {{ $textSecondary }}">{{ $machine->last_heartbeat_at ? $machine->last_heartbeat_at->diffForHumans() : '-' }}</div> <div class="text-sm leading-5 text-gray-600 dark:text-gray-400">{{ $machine->last_heartbeat_at ? $machine->last_heartbeat_at->diffForHumans() : '-' }}</div>
</td> </td>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }} text-sm leading-5 font-medium"> <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700 text-sm leading-5 font-medium">
<a href="{{ route('admin.machines.show', $machine) }}" class="text-indigo-400 hover:text-indigo-600 mr-3">查看</a> <a href="{{ route('admin.machines.show', $machine) }}" class="text-indigo-400 hover:text-indigo-600 mr-3">查看</a>
<a href="{{ route('admin.machines.edit', $machine) }}" class="text-yellow-400 hover:text-yellow-600 mr-3">編輯</a> <a href="{{ route('admin.machines.edit', $machine) }}" class="text-yellow-400 hover:text-yellow-600 mr-3">編輯</a>
<form action="{{ route('admin.machines.destroy', $machine) }}" method="POST" class="inline-block" onsubmit="return confirm('確定要刪除嗎?');"> <form action="{{ route('admin.machines.destroy', $machine) }}" method="POST" class="inline-block" onsubmit="return confirm('確定要刪除嗎?');">

View File

@@ -3,12 +3,12 @@
@section('content') @section('content')
<div class="container mx-auto px-6 py-8"> <div class="container mx-auto px-6 py-8">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<h3 class="text-gray-300 text-3xl font-medium">機台詳情:{{ $machine->name }}</h3> <h3 class="text-gray-900 dark:text-gray-300 text-3xl font-medium">機台詳情:{{ $machine->name }}</h3>
<div> <div>
<a href="{{ route('admin.machines.edit', $machine) }}" class="bg-yellow-600 hover:bg-yellow-700 text-white font-bold py-2 px-4 rounded mr-2"> <a href="{{ route('admin.machines.edit', $machine) }}" class="bg-yellow-600 hover:bg-yellow-700 text-white font-bold py-2 px-4 rounded mr-2">
編輯 編輯
</a> </a>
<a href="{{ route('admin.machines.index') }}" class="bg-gray-600 hover:bg-gray-500 text-white font-bold py-2 px-4 rounded"> <a href="{{ route('admin.machines.index') }}" class="bg-gray-200 dark:bg-gray-600 hover:bg-gray-300 dark:hover:bg-gray-500 text-gray-800 dark:text-white font-bold py-2 px-4 rounded">
返回列表 返回列表
</a> </a>
</div> </div>
@@ -16,15 +16,15 @@
<div class="mt-8 grid grid-cols-1 md:grid-cols-2 gap-6"> <div class="mt-8 grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Basic Info --> <!-- Basic Info -->
<div class="bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6"> <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6">
<h4 class="text-xl font-semibold text-gray-200 mb-4">基本資訊</h4> <h4 class="text-xl font-semibold text-gray-200 mb-4">基本資訊</h4>
<div class="grid grid-cols-2 gap-4"> <div class="grid grid-cols-2 gap-4">
<div> <div>
<p class="text-sm text-gray-400">位置</p> <p class="text-sm text-gray-700 dark:text-gray-400">位置</p>
<p class="text-lg text-gray-200">{{ $machine->location ?? '-' }}</p> <p class="text-lg text-gray-200">{{ $machine->location ?? '-' }}</p>
</div> </div>
<div> <div>
<p class="text-sm text-gray-400">狀態</p> <p class="text-sm text-gray-700 dark:text-gray-400">狀態</p>
@if($machine->status === 'online') @if($machine->status === 'online')
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">連線中</span> <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">連線中</span>
@elseif($machine->status === 'offline') @elseif($machine->status === 'offline')
@@ -34,22 +34,22 @@
@endif @endif
</div> </div>
<div> <div>
<p class="text-sm text-gray-400">溫度</p> <p class="text-sm text-gray-700 dark:text-gray-400">溫度</p>
<p class="text-lg text-gray-200">{{ $machine->temperature ? $machine->temperature . '°C' : '-' }}</p> <p class="text-lg text-gray-200">{{ $machine->temperature ? $machine->temperature . '°C' : '-' }}</p>
</div> </div>
<div> <div>
<p class="text-sm text-gray-400">韌體版本</p> <p class="text-sm text-gray-700 dark:text-gray-400">韌體版本</p>
<p class="text-lg text-gray-200">{{ $machine->firmware_version ?? '-' }}</p> <p class="text-lg text-gray-200">{{ $machine->firmware_version ?? '-' }}</p>
</div> </div>
<div> <div>
<p class="text-sm text-gray-400">最後心跳</p> <p class="text-sm text-gray-700 dark:text-gray-400">最後心跳</p>
<p class="text-lg text-gray-200">{{ $machine->last_heartbeat_at ? $machine->last_heartbeat_at->diffForHumans() : '-' }}</p> <p class="text-lg text-gray-200">{{ $machine->last_heartbeat_at ? $machine->last_heartbeat_at->diffForHumans() : '-' }}</p>
</div> </div>
</div> </div>
</div> </div>
<!-- Logs --> <!-- Logs -->
<div class="bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6"> <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl overflow-hidden p-6">
<h4 class="text-xl font-semibold text-gray-200 mb-4">最近日誌</h4> <h4 class="text-xl font-semibold text-gray-200 mb-4">最近日誌</h4>
<div class="overflow-y-auto max-h-64"> <div class="overflow-y-auto max-h-64">
<ul class="divide-y divide-gray-700"> <ul class="divide-y divide-gray-700">
@@ -64,7 +64,7 @@
@else @else
<span class="h-2 w-2 rounded-full bg-blue-500 mr-2"></span> <span class="h-2 w-2 rounded-full bg-blue-500 mr-2"></span>
@endif @endif
<p class="text-sm text-gray-300">{{ $log->message }}</p> <p class="text-sm text-gray-900 dark:text-gray-300">{{ $log->message }}</p>
</div> </div>
<span class="text-xs text-gray-500">{{ $log->created_at->format('m/d H:i') }}</span> <span class="text-xs text-gray-500">{{ $log->created_at->format('m/d H:i') }}</span>
</div> </div>

View File

@@ -2,62 +2,55 @@
@section('content') @section('content')
@php @php
$theme = request()->cookie('theme', 'dark-blue');
$isLight = in_array($theme, ['light-blue', 'light-green']);
$cardBg = $isLight ? 'bg-white' : 'bg-gray-800';
$textPrimary = $isLight ? 'text-gray-900' : 'text-gray-200';
$textSecondary = $isLight ? 'text-gray-600' : 'text-gray-400';
$borderColor = $isLight ? 'border-gray-200' : 'border-gray-700';
$thBg = $isLight ? 'bg-gray-50' : 'bg-gray-700';
@endphp @endphp
<div class="container mx-auto px-6 py-8"> <div class="container mx-auto px-6 py-8">
<h3 class="{{ $textPrimary }} text-3xl font-medium">會員列表</h3> <h3 class="text-gray-900 dark:text-gray-200 text-3xl font-medium">會員列表</h3>
<div class="mt-8"> <div class="mt-8">
{{-- 搜尋與篩選 (預留空間) --}} {{-- 搜尋與篩選 (預留空間) --}}
<div class="flex flex-col mt-4"> <div class="flex flex-col mt-4">
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8"> <div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
<div class="align-middle inline-block min-w-full shadow overflow-hidden sm:rounded-lg border-b {{ $borderColor }}"> <div class="align-middle inline-block min-w-full shadow overflow-hidden sm:rounded-lg border-b border-gray-200 dark:border-gray-700">
<table class="min-w-full"> <table class="min-w-full">
<thead> <thead>
<tr> <tr>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $thBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider"> <th class="px-6 py-3 border-b border-gray-200 dark:border-gray-700 bg-gray-100 dark:bg-gray-700 text-left text-xs leading-4 font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">
UUID UUID
</th> </th>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $thBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider"> <th class="px-6 py-3 border-b border-gray-200 dark:border-gray-700 bg-gray-100 dark:bg-gray-700 text-left text-xs leading-4 font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">
姓名 姓名
</th> </th>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $thBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider"> <th class="px-6 py-3 border-b border-gray-200 dark:border-gray-700 bg-gray-100 dark:bg-gray-700 text-left text-xs leading-4 font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">
Email Email
</th> </th>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $thBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider"> <th class="px-6 py-3 border-b border-gray-200 dark:border-gray-700 bg-gray-100 dark:bg-gray-700 text-left text-xs leading-4 font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">
手機 手機
</th> </th>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $thBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider"> <th class="px-6 py-3 border-b border-gray-200 dark:border-gray-700 bg-gray-100 dark:bg-gray-700 text-left text-xs leading-4 font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">
狀態 狀態
</th> </th>
<th class="px-6 py-3 border-b {{ $borderColor }} {{ $thBg }} text-left text-xs leading-4 font-medium {{ $textSecondary }} uppercase tracking-wider"> <th class="px-6 py-3 border-b border-gray-200 dark:border-gray-700 bg-gray-100 dark:bg-gray-700 text-left text-xs leading-4 font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">
註冊時間 註冊時間
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody class="{{ $cardBg }}"> <tbody class="bg-white dark:bg-gray-800">
@forelse ($members as $member) @forelse ($members as $member)
<tr> <tr>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }}"> <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700">
<div class="text-sm leading-5 font-medium {{ $textSecondary }}">{{ $member->uuid }}</div> <div class="text-sm leading-5 font-medium text-gray-600 dark:text-gray-400">{{ $member->uuid }}</div>
</td> </td>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }}"> <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700">
<div class="text-sm leading-5 font-bold {{ $textPrimary }}">{{ $member->name }}</div> <div class="text-sm leading-5 font-bold text-gray-900 dark:text-gray-200">{{ $member->name }}</div>
</td> </td>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }}"> <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700">
<div class="text-sm leading-5 {{ $textPrimary }}">{{ $member->email ?? '-' }}</div> <div class="text-sm leading-5 text-gray-900 dark:text-gray-200">{{ $member->email ?? '-' }}</div>
</td> </td>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }}"> <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700">
<div class="text-sm leading-5 {{ $textPrimary }}">{{ $member->phone ?? '-' }}</div> <div class="text-sm leading-5 text-gray-900 dark:text-gray-200">{{ $member->phone ?? '-' }}</div>
</td> </td>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }}"> <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700">
@if($member->is_active) @if($member->is_active)
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"> <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
啟用 啟用
@@ -68,13 +61,13 @@
</span> </span>
@endif @endif
</td> </td>
<td class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }} text-sm leading-5 {{ $textSecondary }}"> <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700 text-sm leading-5 text-gray-600 dark:text-gray-400">
{{ $member->created_at->format('Y-m-d H:i') }} {{ $member->created_at->format('Y-m-d H:i') }}
</td> </td>
</tr> </tr>
@empty @empty
<tr> <tr>
<td colspan="6" class="px-6 py-4 whitespace-no-wrap border-b {{ $borderColor }} text-center {{ $textSecondary }}"> <td colspan="6" class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 dark:border-gray-700 text-center text-gray-600 dark:text-gray-400">
尚無會員資料 尚無會員資料
</td> </td>
</tr> </tr>

View File

@@ -2,15 +2,6 @@
@section('content') @section('content')
@php @php
$theme = request()->cookie('theme', 'dark-blue');
$isLight = in_array($theme, ['light-blue', 'light-green']);
$cardBg = $isLight ? 'bg-white' : 'bg-gray-800';
$textPrimary = $isLight ? 'text-gray-900' : 'text-gray-200';
$textSecondary = $isLight ? 'text-gray-600' : 'text-gray-400';
$borderColor = $isLight ? 'border-gray-200' : 'border-gray-700';
$thBg = $isLight ? 'bg-gray-50' : 'bg-gray-700';
$inputBg = $isLight ? 'bg-white' : 'bg-gray-700';
$inputBorder = $isLight ? 'border-gray-300' : 'border-gray-600';
@endphp @endphp
{{-- Toast 通知 --}} {{-- Toast 通知 --}}
@@ -35,31 +26,31 @@
<div class="container mx-auto px-6 py-8"> <div class="container mx-auto px-6 py-8">
<div class="flex justify-between items-center mb-6"> <div class="flex justify-between items-center mb-6">
<h3 class="{{ $textPrimary }} text-3xl font-medium">會員等級設定</h3> <h3 class="text-gray-900 dark:text-gray-200 text-3xl font-medium">會員等級設定</h3>
<button onclick="document.getElementById('createModal').classList.remove('hidden')" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700"> <button onclick="document.getElementById('createModal').classList.remove('hidden')" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700">
新增等級 新增等級
</button> </button>
</div> </div>
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="min-w-full {{ $cardBg }} rounded-lg overflow-hidden"> <table class="min-w-full bg-white dark:bg-gray-800 rounded-lg overflow-hidden">
<thead class="{{ $thBg }}"> <thead class="bg-gray-100 dark:bg-gray-700">
<tr> <tr>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">名稱</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">名稱</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">年費</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">年費</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">折扣</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">折扣</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">點數倍率</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">點數倍率</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">預設</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">預設</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">操作</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">操作</th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y {{ $borderColor }}"> <tbody class="divide-y border-gray-200 dark:border-gray-700">
@forelse($tiers as $tier) @forelse($tiers as $tier)
<tr> <tr>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $tier->name }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $tier->name }}</td>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $tier->annual_fee == 0 ? '免費' : '$'.number_format($tier->annual_fee) }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $tier->annual_fee == 0 ? '免費' : '$'.number_format($tier->annual_fee) }}</td>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $tier->discount_rate * 100 }}%</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $tier->discount_rate * 100 }}%</td>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $tier->point_multiplier }}x</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $tier->point_multiplier }}x</td>
<td class="px-6 py-4"> <td class="px-6 py-4">
@if($tier->is_default) @if($tier->is_default)
<span class="px-2 py-1 rounded-full bg-green-100 text-green-800 text-xs">預設</span> <span class="px-2 py-1 rounded-full bg-green-100 text-green-800 text-xs">預設</span>
@@ -75,7 +66,7 @@
</tr> </tr>
@empty @empty
<tr> <tr>
<td colspan="6" class="px-6 py-4 text-center {{ $textSecondary }}">尚無資料</td> <td colspan="6" class="px-6 py-4 text-center text-gray-600 dark:text-gray-400">尚無資料</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>
@@ -90,36 +81,36 @@
<div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" onclick="document.getElementById('createModal').classList.add('hidden')"></div> <div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" onclick="document.getElementById('createModal').classList.add('hidden')"></div>
{{-- Modal 內容 --}} {{-- Modal 內容 --}}
<div class="relative {{ $cardBg }} rounded-lg shadow-xl transform transition-all sm:max-w-lg sm:w-full mx-4"> <div class="relative bg-white dark:bg-gray-800 rounded-lg shadow-xl transform transition-all sm:max-w-lg sm:w-full mx-4">
<div class="px-6 py-4 border-b {{ $borderColor }}"> <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
<h3 class="{{ $textPrimary }} text-lg font-semibold">新增會員等級</h3> <h3 class="text-gray-900 dark:text-gray-200 text-lg font-semibold">新增會員等級</h3>
</div> </div>
<form action="{{ route('admin.membership-tiers.store') }}" method="POST"> <form action="{{ route('admin.membership-tiers.store') }}" method="POST">
@csrf @csrf
<div class="px-6 py-4 space-y-4"> <div class="px-6 py-4 space-y-4">
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">名稱</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">名稱</label>
<input type="text" name="name" required class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500 focus:border-transparent"> <input type="text" name="name" required class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500 focus:border-transparent">
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">年費</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">年費</label>
<input type="number" name="annual_fee" value="0" step="0.01" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="number" name="annual_fee" value="0" step="0.01" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">折扣比例 (0.95 = 95)</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">折扣比例 (0.95 = 95)</label>
<input type="number" name="discount_rate" value="1.00" step="0.01" min="0" max="1" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="number" name="discount_rate" value="1.00" step="0.01" min="0" max="1" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">點數倍率</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">點數倍率</label>
<input type="number" name="point_multiplier" value="1.00" step="0.01" min="0" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="number" name="point_multiplier" value="1.00" step="0.01" min="0" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<input type="checkbox" name="is_default" value="1" id="is_default" class="mr-2 rounded text-indigo-600 focus:ring-indigo-500"> <input type="checkbox" name="is_default" value="1" id="is_default" class="mr-2 rounded text-indigo-600 focus:ring-indigo-500">
<label for="is_default" class="{{ $textSecondary }} text-sm">設為預設等級</label> <label for="is_default" class="text-gray-600 dark:text-gray-400 text-sm">設為預設等級</label>
</div> </div>
</div> </div>
<div class="px-6 py-4 border-t {{ $borderColor }} flex justify-end space-x-3"> <div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-3">
<button type="button" onclick="document.getElementById('createModal').classList.add('hidden')" class="px-4 py-2 {{ $textSecondary }} border {{ $inputBorder }} rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">取消</button> <button type="button" onclick="document.getElementById('createModal').classList.add('hidden')" class="px-4 py-2 text-gray-600 dark:text-gray-400 border border-gray-300 dark:border-gray-600 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">取消</button>
<button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">建立</button> <button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">建立</button>
</div> </div>
</form> </form>

View File

@@ -1,39 +1,26 @@
@php
$theme = request()->cookie('theme', 'dark-blue');
$themes = [
'dark-blue' => ['card' => 'bg-gray-800', 'accent' => 'indigo'],
'dark-purple' => ['card' => 'bg-slate-800', 'accent' => 'purple'],
'dark-green' => ['card' => 'bg-zinc-800', 'accent' => 'emerald'],
'light-blue' => ['card' => 'bg-white', 'accent' => 'blue'],
'light-green' => ['card' => 'bg-white', 'accent' => 'green'],
];
$currentTheme = $themes[$theme] ?? $themes['dark-blue'];
$isLight = in_array($theme, ['light-blue', 'light-green']);
@endphp
@extends('layouts.admin') @extends('layouts.admin')
@section('content') @section('content')
<div class="max-w-7xl mx-auto"> <div class="max-w-7xl mx-auto">
<div class="{{ $currentTheme['card'] }} rounded-lg shadow-lg p-8 text-center border {{ $isLight ? 'border-gray-200' : 'border-gray-700' }}"> <div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-8 text-center border border-gray-200 dark:border-gray-700">
<div class="mb-6"> <div class="mb-6">
<svg class="mx-auto h-24 w-24 text-{{ $currentTheme['accent'] }}-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg class="mx-auto h-24 w-24 text-gray-400 dark:text-gray-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" />
</svg> </svg>
</div> </div>
<h1 class="text-3xl font-bold {{ $isLight ? 'text-gray-900' : 'text-white' }} mb-4">{{ $title ?? '功能頁面' }}</h1> <h1 class="text-3xl font-bold text-gray-900 dark:text-white mb-4">{{ $title ?? '功能頁面' }}</h1>
<p class="{{ $isLight ? 'text-gray-600' : 'text-gray-400' }} mb-6 text-lg">{{ $description ?? '此功能正在開發中' }}</p> <p class="text-gray-600 dark:text-gray-400 mb-6 text-lg">{{ $description ?? '此功能正在開發中' }}</p>
<div class="inline-block px-6 py-3 bg-{{ $currentTheme['accent'] }}-600 text-white rounded-lg font-semibold"> <div class="inline-block px-6 py-3 bg-blue-600 text-white rounded-lg font-semibold">
🚧 功能開發中 🚧 功能開發中
</div> </div>
@if(isset($features) && count($features) > 0) @if(isset($features) && count($features) > 0)
<div class="mt-8 text-left max-w-2xl mx-auto"> <div class="mt-8 text-left max-w-2xl mx-auto">
<h3 class="text-xl font-semibold {{ $isLight ? 'text-gray-900' : 'text-white' }} mb-4">規劃功能:</h3> <h3 class="text-xl font-semibold text-gray-900 dark:text-white mb-4">規劃功能:</h3>
<ul class="space-y-2 {{ $isLight ? 'text-gray-700' : 'text-gray-300' }}"> <ul class="space-y-2 text-gray-700 dark:text-gray-300">
@foreach($features as $feature) @foreach($features as $feature)
<li class="flex items-start"> <li class="flex items-start">
<svg class="h-6 w-6 text-{{ $currentTheme['accent'] }}-500 mr-2 flex-shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg class="h-6 w-6 text-blue-500 mr-2 flex-shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg> </svg>
<span>{{ $feature }}</span> <span>{{ $feature }}</span>

View File

@@ -2,15 +2,6 @@
@section('content') @section('content')
@php @php
$theme = request()->cookie('theme', 'dark-blue');
$isLight = in_array($theme, ['light-blue', 'light-green']);
$cardBg = $isLight ? 'bg-white' : 'bg-gray-800';
$textPrimary = $isLight ? 'text-gray-900' : 'text-gray-200';
$textSecondary = $isLight ? 'text-gray-600' : 'text-gray-400';
$borderColor = $isLight ? 'border-gray-200' : 'border-gray-700';
$thBg = $isLight ? 'bg-gray-50' : 'bg-gray-700';
$inputBg = $isLight ? 'bg-white' : 'bg-gray-700';
$inputBorder = $isLight ? 'border-gray-300' : 'border-gray-600';
$triggerLabels = [ $triggerLabels = [
'purchase' => '消費', 'purchase' => '消費',
@@ -43,33 +34,33 @@
<div class="container mx-auto px-6 py-8"> <div class="container mx-auto px-6 py-8">
<div class="flex justify-between items-center mb-6"> <div class="flex justify-between items-center mb-6">
<h3 class="{{ $textPrimary }} text-3xl font-medium">點數規則設定</h3> <h3 class="text-gray-900 dark:text-gray-200 text-3xl font-medium">點數規則設定</h3>
<button onclick="document.getElementById('createModal').classList.remove('hidden')" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700"> <button onclick="document.getElementById('createModal').classList.remove('hidden')" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700">
新增規則 新增規則
</button> </button>
</div> </div>
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="min-w-full {{ $cardBg }} rounded-lg overflow-hidden"> <table class="min-w-full bg-white dark:bg-gray-800 rounded-lg overflow-hidden">
<thead class="{{ $thBg }}"> <thead class="bg-gray-100 dark:bg-gray-700">
<tr> <tr>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">名稱</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">名稱</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">觸發條件</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">觸發條件</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">每單位點數</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">每單位點數</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">單位金額</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">單位金額</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">有效天數</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">有效天數</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">狀態</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">狀態</th>
<th class="px-6 py-3 text-left text-xs font-medium {{ $textSecondary }} uppercase">操作</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-600 dark:text-gray-400 uppercase">操作</th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y {{ $borderColor }}"> <tbody class="divide-y border-gray-200 dark:border-gray-700">
@forelse($rules as $rule) @forelse($rules as $rule)
<tr> <tr>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $rule->name }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $rule->name }}</td>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $triggerLabels[$rule->trigger] ?? $rule->trigger }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $triggerLabels[$rule->trigger] ?? $rule->trigger }}</td>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $rule->points_per_unit }} </td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $rule->points_per_unit }} </td>
<td class="px-6 py-4 {{ $textPrimary }}">${{ number_format($rule->unit_amount) }}</td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">${{ number_format($rule->unit_amount) }}</td>
<td class="px-6 py-4 {{ $textPrimary }}">{{ $rule->validity_days }} </td> <td class="px-6 py-4 text-gray-900 dark:text-gray-200">{{ $rule->validity_days }} </td>
<td class="px-6 py-4"> <td class="px-6 py-4">
@if($rule->is_active) @if($rule->is_active)
<span class="px-2 py-1 rounded-full bg-green-100 text-green-800 text-xs">啟用</span> <span class="px-2 py-1 rounded-full bg-green-100 text-green-800 text-xs">啟用</span>
@@ -87,7 +78,7 @@
</tr> </tr>
@empty @empty
<tr> <tr>
<td colspan="7" class="px-6 py-4 text-center {{ $textSecondary }}">尚無資料</td> <td colspan="7" class="px-6 py-4 text-center text-gray-600 dark:text-gray-400">尚無資料</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>
@@ -100,44 +91,44 @@
<div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:p-0"> <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:p-0">
<div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" onclick="document.getElementById('createModal').classList.add('hidden')"></div> <div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" onclick="document.getElementById('createModal').classList.add('hidden')"></div>
<div class="relative {{ $cardBg }} rounded-lg shadow-xl transform transition-all sm:max-w-lg sm:w-full mx-4"> <div class="relative bg-white dark:bg-gray-800 rounded-lg shadow-xl transform transition-all sm:max-w-lg sm:w-full mx-4">
<div class="px-6 py-4 border-b {{ $borderColor }}"> <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
<h3 class="{{ $textPrimary }} text-lg font-semibold">新增點數規則</h3> <h3 class="text-gray-900 dark:text-gray-200 text-lg font-semibold">新增點數規則</h3>
</div> </div>
<form action="{{ route('admin.point-rules.store') }}" method="POST"> <form action="{{ route('admin.point-rules.store') }}" method="POST">
@csrf @csrf
<div class="px-6 py-4 space-y-4"> <div class="px-6 py-4 space-y-4">
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">名稱</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">名稱</label>
<input type="text" name="name" required class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="text" name="name" required class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">觸發條件</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">觸發條件</label>
<select name="trigger" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <select name="trigger" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
@foreach($triggerLabels as $key => $label) @foreach($triggerLabels as $key => $label)
<option value="{{ $key }}">{{ $label }}</option> <option value="{{ $key }}">{{ $label }}</option>
@endforeach @endforeach
</select> </select>
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">每單位獲得點數</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">每單位獲得點數</label>
<input type="number" name="points_per_unit" value="1" min="1" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="number" name="points_per_unit" value="1" min="1" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">單位金額</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">單位金額</label>
<input type="number" name="unit_amount" value="100" step="0.01" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="number" name="unit_amount" value="100" step="0.01" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div> <div>
<label class="{{ $textSecondary }} text-sm block mb-1">有效天數</label> <label class="text-gray-600 dark:text-gray-400 text-sm block mb-1">有效天數</label>
<input type="number" name="validity_days" value="365" min="1" class="w-full px-3 py-2 {{ $inputBg }} {{ $inputBorder }} border rounded-md {{ $textPrimary }} focus:ring-2 focus:ring-indigo-500"> <input type="number" name="validity_days" value="365" min="1" class="w-full px-3 py-2 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 border rounded-md text-gray-900 dark:text-gray-200 focus:ring-2 focus:ring-indigo-500">
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<input type="checkbox" name="is_active" value="1" checked id="is_active" class="mr-2 rounded text-indigo-600 focus:ring-indigo-500"> <input type="checkbox" name="is_active" value="1" checked id="is_active" class="mr-2 rounded text-indigo-600 focus:ring-indigo-500">
<label for="is_active" class="{{ $textSecondary }} text-sm">啟用</label> <label for="is_active" class="text-gray-600 dark:text-gray-400 text-sm">啟用</label>
</div> </div>
</div> </div>
<div class="px-6 py-4 border-t {{ $borderColor }} flex justify-end space-x-3"> <div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-3">
<button type="button" onclick="document.getElementById('createModal').classList.add('hidden')" class="px-4 py-2 {{ $textSecondary }} border {{ $inputBorder }} rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">取消</button> <button type="button" onclick="document.getElementById('createModal').classList.add('hidden')" class="px-4 py-2 text-gray-600 dark:text-gray-400 border border-gray-300 dark:border-gray-600 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">取消</button>
<button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">建立</button> <button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">建立</button>
</div> </div>
</form> </form>

View File

@@ -1,47 +1,123 @@
<x-guest-layout> <!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=inter:400,500,600,700&display=swap" rel="stylesheet" />
<script>
// Dark mode
const html = document.querySelector('html');
const isLightOrAuto = localStorage.getItem('hs_theme') === 'light' || (localStorage.getItem('hs_theme') !== 'dark' && !window.matchMedia('(prefers-color-scheme: dark)').matches);
const isDarkOrAuto = localStorage.getItem('hs_theme') === 'dark' || (localStorage.getItem('hs_theme') !== 'light' && window.matchMedia('(prefers-color-scheme: dark)').matches);
if (isLightOrAuto && html.classList.contains('dark')) html.classList.remove('dark');
else if (isDarkOrAuto && html.classList.contains('light')) html.classList.remove('light');
else if (isDarkOrAuto && !html.classList.contains('dark')) html.classList.add('dark');
else if (isLightOrAuto && !html.classList.contains('light')) html.classList.add('light');
</script>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="font-sans antialiased bg-white dark:bg-slate-900">
<div class="flex h-screen">
<!-- Sidebar - Image Section -->
<div class="hidden md:flex md:w-1/2 lg:w-3/5 bg-gray-50 border-r border-gray-200 dark:bg-slate-800 dark:border-slate-700 justify-center items-center relative overflow-hidden">
<!-- Background Pattern or Gradient -->
<div class="absolute inset-0 bg-gradient-to-tr from-blue-600 to-purple-500 opacity-90 dark:from-blue-900 dark:to-purple-900"></div>
<div class="relative z-10 text-center px-6">
<h2 class="text-3xl font-bold text-white sm:text-4xl">
{{ config('app.name', 'Star Cloud') }}
</h2>
<p class="mt-3 text-lg text-blue-100">
智能販賣機管理平台
</p>
</div>
</div>
<!-- Main Content - Login Form -->
<div class="w-full md:w-1/2 lg:w-2/5 flex flex-col justify-center px-4 sm:px-6 md:px-8 lg:px-10 py-8">
<div class="max-w-md w-full mx-auto">
<div class="text-center mb-8">
<h1 class="block text-2xl font-bold text-gray-800 dark:text-white">登入</h1>
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">
請輸入您的帳號密碼以繼續
</p>
</div>
<!-- Session Status --> <!-- Session Status -->
<x-auth-session-status class="mb-4" :status="session('status')" /> @if (session('status'))
<div class="mb-4 text-sm font-medium text-green-600">
{{ session('status') }}
</div>
@endif
<form method="POST" action="{{ route('login') }}"> <form method="POST" action="{{ route('login') }}">
@csrf @csrf
<!-- 帳號 --> <div class="grid gap-y-4">
<!-- Form Group -->
<div> <div>
<x-input-label for="username" :value="__('帳號')" /> <label for="username" class="block text-sm mb-2 dark:text-white">帳號</label>
<x-text-input id="username" class="block mt-1 w-full" type="text" name="username" :value="old('username')" required autofocus autocomplete="username" /> <div class="relative">
<x-input-error :messages="$errors->get('username')" class="mt-2" /> <input type="text" id="username" name="username" value="{{ old('username') }}" class="py-3 px-4 block w-full border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-slate-900 dark:border-slate-700 dark:text-gray-400 dark:focus:ring-gray-600" required autofocus autocomplete="username">
<div class="hidden absolute inset-y-0 end-0 flex items-center pointer-events-none pe-3">
<svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"/>
</svg>
</div> </div>
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />
<x-text-input id="password" class="block mt-1 w-full"
type="password"
name="password"
required autocomplete="current-password" />
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div> </div>
@if ($errors->get('username'))
<!-- Remember Me --> <p class="text-xs text-red-600 mt-2" id="username-error">{{ $errors->first('username') }}</p>
<div class="block mt-4"> @endif
<label for="remember_me" class="inline-flex items-center">
<input id="remember_me" type="checkbox" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="remember">
<span class="ms-2 text-sm text-gray-600 dark:text-gray-400">{{ __('Remember me') }}</span>
</label>
</div> </div>
<!-- End Form Group -->
<div class="flex items-center justify-end mt-4"> <!-- Form Group -->
<div>
<div class="flex justify-between items-center">
<label for="password" class="block text-sm mb-2 dark:text-white">密碼</label>
@if (Route::has('password.request')) @if (Route::has('password.request'))
<a class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800" href="{{ route('password.request') }}"> <a class="text-sm text-blue-600 decoration-2 hover:underline font-medium dark:text-blue-500" href="{{ route('password.request') }}">
{{ __('Forgot your password?') }} 忘記密碼?
</a> </a>
@endif @endif
</div>
<div class="relative">
<input type="password" id="password" name="password" class="py-3 px-4 block w-full border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-slate-900 dark:border-slate-700 dark:text-gray-400 dark:focus:ring-gray-600" required autocomplete="current-password">
<div class="hidden absolute inset-y-0 end-0 flex items-center pointer-events-none pe-3">
<svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"/>
</svg>
</div>
</div>
@if ($errors->get('password'))
<p class="text-xs text-red-600 mt-2" id="password-error">{{ $errors->first('password') }}</p>
@endif
</div>
<!-- End Form Group -->
<x-primary-button class="ms-3"> <!-- Checkbox -->
{{ __('Log in') }} <div class="flex items-center">
</x-primary-button> <div class="flex">
<input id="remember-me" name="remember" type="checkbox" class="shrink-0 mt-0.5 border-gray-200 rounded text-blue-600 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-700 dark:checked:bg-blue-500 dark:checked:border-blue-500 dark:focus:ring-offset-gray-800">
</div>
<div class="ms-3">
<label for="remember-me" class="text-sm dark:text-white">記住我</label>
</div>
</div>
<!-- End Checkbox -->
<button type="submit" class="w-full py-3 px-4 inline-flex justify-center items-center gap-x-2 text-sm font-semibold rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600">
登入
</button>
</div> </div>
</form> </form>
</x-guest-layout> </div>
</div>
</div>
</body>
</html>

View File

@@ -1,17 +1,165 @@
<x-app-layout> @extends('layouts.admin')
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="py-12"> @section('content')
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> <div class="space-y-4 sm:space-y-6">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg"> <!-- Grid -->
<div class="p-6 text-gray-900 dark:text-gray-100"> <div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-6">
{{ __("You're logged in!") }} <!-- Card -->
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-gray-800 dark:border-gray-700">
<div class="p-4 md:p-5">
<div class="flex items-center gap-x-2">
<p class="text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400">
總銷售額
</p>
<div class="hs-tooltip">
<div class="hs-tooltip-toggle">
<svg class="flex-shrink-0 w-4 h-4 text-gray-500" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>
<span class="hs-tooltip-content hs-tooltip-shown:opacity-100 hs-tooltip-shown:visible opacity-0 transition-opacity inline-block absolute invisible z-10 py-1 px-2 bg-gray-900 text-xs font-medium text-white rounded shadow-sm dark:bg-slate-700" role="tooltip">
本月累計銷售總額
</span>
</div> </div>
</div> </div>
</div> </div>
<div class="mt-1 flex items-center gap-x-2">
<h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
$72,540
</h3>
<span class="flex items-center gap-x-1 text-green-600">
<svg class="inline-block w-4 h-4 self-center" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/></svg>
<span class="inline-block text-sm">
1.7%
</span>
</span>
</div> </div>
</x-app-layout> </div>
</div>
<!-- End Card -->
<!-- Card -->
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-gray-800 dark:border-gray-700">
<div class="p-4 md:p-5">
<div class="flex items-center gap-x-2">
<p class="text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400">
活躍機台
</p>
</div>
<div class="mt-1 flex items-center gap-x-2">
<h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
124
</h3>
<span class="flex items-center gap-x-1 text-red-600">
<svg class="inline-block w-4 h-4 self-center" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 17 13.5 8.5 8.5 13.5 2 7"/><polyline points="16 17 22 17 22 11"/></svg>
<span class="inline-block text-sm">
0.3%
</span>
</span>
</div>
</div>
</div>
<!-- End Card -->
<!-- Card -->
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-gray-800 dark:border-gray-700">
<div class="p-4 md:p-5">
<div class="flex items-center gap-x-2">
<p class="text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400">
庫存警告
</p>
</div>
<div class="mt-1 flex items-center gap-x-2">
<h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
12
</h3>
</div>
</div>
</div>
<!-- End Card -->
<!-- Card -->
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-gray-800 dark:border-gray-700">
<div class="p-4 md:p-5">
<div class="flex items-center gap-x-2">
<p class="text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400">
本月新增會員
</p>
</div>
<div class="mt-1 flex items-center gap-x-2">
<h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
28
</h3>
</div>
</div>
</div>
<!-- End Card -->
</div>
<!-- End Grid -->
<div class="grid lg:grid-cols-2 gap-4 sm:gap-6">
<!-- Card -->
<div class="p-4 md:p-5 min-h-[410px] flex flex-col bg-white border shadow-sm rounded-xl dark:bg-gray-800 dark:border-gray-700">
<!-- Header -->
<div class="flex justify-between items-center">
<div>
<h2 class="text-sm text-gray-500 dark:text-gray-400">
營收趨勢
</h2>
<p class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
$123,450
</p>
</div>
<div>
<span class="py-[5px] px-1.5 inline-flex items-center gap-x-1 text-xs font-medium rounded-md bg-teal-100 text-teal-800 dark:bg-teal-500/10 dark:text-teal-500">
<svg class="inline-block w-3.5 h-3.5" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14"/><path d="m19 12-7 7-7-7"/></svg>
25%
</span>
</div>
</div>
<!-- End Header -->
<div id="hs-multiple-bar-charts"></div>
</div>
<!-- End Card -->
<!-- Card -->
<div class="p-4 md:p-5 min-h-[410px] flex flex-col bg-white border shadow-sm rounded-xl dark:bg-gray-800 dark:border-gray-700">
<!-- Header -->
<div class="flex justify-between items-center">
<div>
<h2 class="text-sm text-gray-500 dark:text-gray-400">
訪客分析
</h2>
<p class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
92,913
</p>
</div>
<div>
<span class="py-[5px] px-1.5 inline-flex items-center gap-x-1 text-xs font-medium rounded-md bg-red-100 text-red-800 dark:bg-red-500/10 dark:text-red-500">
<svg class="inline-block w-3.5 h-3.5" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14"/><path d="m19 12-7 7-7-7"/></svg>
11%
</span>
</div>
</div>
<!-- End Header -->
<div id="hs-single-area-chart"></div>
</div>
<!-- End Card -->
</div>
</div>
@endsection
@section('scripts')
<script>
window.addEventListener('load', () => {
// Here you would initialize charts using ApexCharts or similar,
// as Preline examples often use ApexCharts.
// For now, placeholders are sufficient.
});
</script>
@endsection

View File

@@ -1,55 +1,5 @@
@php
$theme = request()->cookie('theme', 'dark-blue');
// 主題配置
$themes = [
'dark-blue' => [
'name' => '深色藍',
'body' => 'bg-gray-900 text-gray-100',
'sidebar' => 'bg-gray-800 border-gray-700',
'header' => 'bg-gray-800 border-gray-700',
'card' => 'bg-gray-800',
'accent' => 'indigo',
],
'dark-purple' => [
'name' => '深色紫',
'body' => 'bg-slate-900 text-slate-100',
'sidebar' => 'bg-slate-800 border-slate-700',
'header' => 'bg-slate-800 border-slate-700',
'card' => 'bg-slate-800',
'accent' => 'purple',
],
'dark-green' => [
'name' => '深色綠',
'body' => 'bg-zinc-900 text-zinc-100',
'sidebar' => 'bg-zinc-800 border-zinc-700',
'header' => 'bg-zinc-800 border-zinc-700',
'card' => 'bg-zinc-800',
'accent' => 'emerald',
],
'light-blue' => [
'name' => '亮色藍',
'body' => 'bg-gray-50 text-gray-900',
'sidebar' => 'bg-white border-gray-200',
'header' => 'bg-white border-gray-200',
'card' => 'bg-white',
'accent' => 'blue',
],
'light-green' => [
'name' => '亮色綠',
'body' => 'bg-green-50 text-gray-900',
'sidebar' => 'bg-white border-green-200',
'header' => 'bg-white border-green-200',
'card' => 'bg-white',
'accent' => 'green',
],
];
$currentTheme = $themes[$theme] ?? $themes['dark-blue'];
$isLight = in_array($theme, ['light-blue', 'light-green']);
@endphp
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="{{ $isLight ? '' : 'dark' }}"> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="h-full" x-data="{ darkMode: localStorage.getItem('darkMode') === 'true' }" :class="{ 'dark': darkMode }">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -62,88 +12,168 @@
<link href="https://fonts.bunny.net/css?family=inter:400,500,600,700&display=swap" rel="stylesheet" /> <link href="https://fonts.bunny.net/css?family=inter:400,500,600,700&display=swap" rel="stylesheet" />
<!-- Scripts --> <!-- Scripts -->
<script>
// Dark Mode Initialization (before Alpine loads)
if (localStorage.getItem('darkMode') === 'true' || (!('darkMode' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
localStorage.setItem('darkMode', 'true');
} else {
document.documentElement.classList.remove('dark');
}
</script>
@vite(['resources/css/app.css', 'resources/js/app.js']) @vite(['resources/css/app.css', 'resources/js/app.js'])
</head> </head>
<body class="font-sans antialiased {{ $currentTheme['body'] }}" x-data="{ sidebarOpen: false, themeOpen: false, dropdownOpen: false }" x-cloak> <body class="bg-gray-50 dark:bg-slate-900 antialiased font-sans h-full" x-data="{ sidebarOpen: false, userDropdownOpen: false }">
<div class="min-h-screen flex">
<!-- Mobile Sidebar Backdrop --> <!-- Sidebar Overlay (Mobile) -->
<div x-show="sidebarOpen" <div x-show="sidebarOpen"
x-cloak
@click="sidebarOpen = false"
x-transition:enter="transition-opacity ease-linear duration-300" x-transition:enter="transition-opacity ease-linear duration-300"
x-transition:enter-start="opacity-0" x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100" x-transition:enter-end="opacity-100"
x-transition:leave="transition-opacity ease-linear duration-300" x-transition:leave="transition-opacity ease-linear duration-300"
x-transition:leave-start="opacity-100" x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0" x-transition:leave-end="opacity-0"
class="fixed inset-0 bg-black bg-opacity-50 z-40 lg:hidden"> @click="sidebarOpen = false"
class="fixed inset-0 z-[55] bg-gray-900/50 lg:hidden"
x-cloak></div>
<!-- ========== HEADER ========== -->
<header class="sticky top-0 inset-x-0 flex flex-wrap sm:justify-start sm:flex-nowrap z-[48] w-full bg-white border-b text-sm py-2.5 sm:py-4 lg:pl-64 dark:bg-gray-800 dark:border-gray-700">
<nav class="flex basis-full items-center w-full mx-auto px-4 sm:px-6 md:px-8" aria-label="Global">
<div class="mr-5 lg:mr-0 lg:hidden">
<a class="flex-none text-xl font-semibold dark:text-white" href="#" aria-label="Brand">Star Cloud</a>
</div> </div>
<!-- Sidebar --> <div class="w-full flex items-center justify-end ml-auto sm:justify-between sm:gap-x-3 sm:order-3">
<aside class="fixed inset-y-0 left-0 z-50 w-64 {{ $currentTheme['sidebar'] }} border-r overflow-y-auto transition-transform duration-300 ease-in-out lg:translate-x-0 lg:static lg:inset-0" <div class="sm:hidden">
:class="{'translate-x-0': sidebarOpen, '-translate-x-full': !sidebarOpen}" <button type="button" class="inline-flex flex-shrink-0 justify-center items-center gap-2 h-[2.375rem] w-[2.375rem] rounded-full font-medium bg-white text-gray-700 align-middle hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 focus:ring-offset-white transition-all text-xs dark:bg-gray-800 dark:hover:bg-slate-800 dark:text-gray-400 dark:hover:text-white dark:focus:ring-gray-700 dark:focus:ring-offset-gray-800">
<svg class="w-3.5 h-3.5" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
</svg>
</button>
</div>
<div class="hidden sm:block">
<!-- Search Input (Optional) -->
</div>
<div class="flex flex-row items-center justify-end gap-2">
<!-- Dark Mode Toggle -->
<button type="button"
@click="darkMode = !darkMode; localStorage.setItem('darkMode', darkMode); document.documentElement.classList.toggle('dark', darkMode)"
class="inline-flex flex-shrink-0 justify-center items-center gap-2 h-[2.375rem] w-[2.375rem] rounded-full font-medium bg-white text-gray-700 align-middle hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 focus:ring-offset-white transition-all text-xs dark:bg-gray-800 dark:hover:bg-slate-800 dark:text-gray-400 dark:hover:text-white dark:focus:ring-gray-700 dark:focus:ring-offset-gray-800">
<!-- Moon Icon (shown in light mode) -->
<svg x-show="!darkMode" class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278zM4.858 1.311A7.269 7.269 0 0 0 1.025 7.71c0 4.02 3.279 7.276 7.319 7.276a7.316 7.316 0 0 0 5.205-2.162c-.337.042-.68.063-1.029.063-4.61 0-8.343-3.714-8.343-8.29 0-1.167.242-2.278.681-3.286z"/>
</svg>
<!-- Sun Icon (shown in dark mode) -->
<svg x-show="darkMode" class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M8 11a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 1a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"/>
</svg>
</button>
<!-- Profile Dropdown -->
<div class="relative inline-flex" x-data="{ open: false }">
<button id="hs-dropdown-with-header" type="button" @click="open = !open" @click.away="open = false" class="inline-flex flex-shrink-0 justify-center items-center gap-2 h-[2.375rem] w-[2.375rem] rounded-full font-medium bg-white text-gray-700 align-middle hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 focus:ring-offset-white transition-all text-xs dark:bg-gray-800 dark:hover:bg-slate-800 dark:text-gray-400 dark:hover:text-white dark:focus:ring-gray-700 dark:focus:ring-offset-gray-800">
<img class="inline-block h-[2.375rem] w-[2.375rem] rounded-full ring-2 ring-white dark:ring-gray-800" src="https://ui-avatars.com/api/?name={{ Auth::user()->name }}&background=0D8ABC&color=fff" alt="Image Description">
</button>
<div x-show="open"
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="transform opacity-0 scale-95"
x-transition:enter-end="transform opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="transform opacity-100 scale-100"
x-transition:leave-end="transform opacity-0 scale-95"
class="absolute right-0 top-full mt-2 min-w-[15rem] bg-white shadow-md rounded-lg p-2 dark:bg-gray-800 dark:border dark:border-gray-700 z-50"
x-cloak> x-cloak>
<div class="flex items-center justify-center h-16 {{ $currentTheme['header'] }} border-b"> <div class="py-3 px-5 -m-2 bg-gray-100 rounded-t-lg dark:bg-gray-700">
<span class="text-2xl font-bold text-{{ $currentTheme['accent'] }}-500">Star Cloud</span> <p class="text-sm text-gray-500 dark:text-gray-400">Signed in as</p>
<p class="text-sm font-medium text-gray-800 dark:text-gray-300">{{ Auth::user()->email }}</p>
</div> </div>
<nav class="mt-5 px-2 space-y-1 pb-4"> <div class="mt-2 py-2 first:pt-0 last:pb-0">
@include('layouts.partials.sidebar-menu') <a class="flex items-center gap-x-3.5 py-2 px-3 rounded-md text-sm text-gray-800 hover:bg-gray-100 focus:ring-2 focus:ring-blue-500 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-300" href="{{ route('profile.edit') }}">
</nav> <svg class="flex-shrink-0 w-4 h-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
</aside> 個人檔案
</a>
<!-- Content -->
<div class="flex-1 flex flex-col overflow-hidden">
<!-- Topbar -->
<header class="flex items-center justify-between h-16 {{ $currentTheme['header'] }} border-b px-6">
<div class="flex items-center">
<button @click="sidebarOpen = !sidebarOpen" class="{{ $isLight ? 'text-gray-600' : 'text-gray-400' }} focus:outline-none lg:hidden">
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<div class="flex items-center space-x-4">
<!-- Theme Selector -->
<div class="relative">
<button @click="themeOpen = !themeOpen" class="relative block h-8 w-8 rounded-full overflow-hidden shadow focus:outline-none {{ $isLight ? 'bg-gray-200' : 'bg-gray-700' }}">
<svg class="h-5 w-5 m-auto mt-1.5 {{ $isLight ? 'text-gray-600' : 'text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" />
</svg>
</button>
<div x-show="themeOpen" x-cloak @click.away="themeOpen = false" class="absolute right-0 w-48 mt-2 {{ $currentTheme['card'] }} rounded-md shadow-lg py-1 ring-1 ring-black ring-opacity-5 z-50">
@foreach($themes as $key => $themeData)
<form method="POST" action="{{ route('admin.theme.update') }}">
@csrf
<input type="hidden" name="theme" value="{{ $key }}">
<button type="submit" class="block w-full text-left px-4 py-2 text-sm {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700' }} {{ $theme === $key ? 'font-bold' : '' }}">
{{ $themeData['name'] }} {{ $theme === $key ? '✓' : '' }}
</button>
</form>
@endforeach
</div>
</div>
<!-- User Menu -->
<div class="ml-3 relative">
<button @click="dropdownOpen = !dropdownOpen" class="relative block h-8 w-8 rounded-full overflow-hidden shadow focus:outline-none">
<img class="h-full w-full object-cover" src="https://ui-avatars.com/api/?name={{ Auth::user()->name }}&background=random" alt="Avatar">
</button>
<div x-show="dropdownOpen" x-cloak @click.away="dropdownOpen = false" class="absolute right-0 w-48 mt-2 {{ $currentTheme['card'] }} rounded-md shadow-lg py-1 ring-1 ring-black ring-opacity-5 z-50">
<a href="{{ route('profile.edit') }}" class="block px-4 py-2 text-sm {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700' }}">個人檔案</a>
<form method="POST" action="{{ route('logout') }}"> <form method="POST" action="{{ route('logout') }}">
@csrf @csrf
<button type="submit" class="block w-full text-left px-4 py-2 text-sm {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700' }}">登出</button> <button type="submit" class="w-full flex items-center gap-x-3.5 py-2 px-3 rounded-md text-sm text-gray-800 hover:bg-gray-100 focus:ring-2 focus:ring-blue-500 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-300">
<svg class="flex-shrink-0 w-4 h-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" x2="9" y1="12" y2="12"/></svg>
登出
</button>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
</nav>
</header> </header>
<!-- ========== END HEADER ========== -->
<!-- Main Content --> <!-- ========== MAIN CONTENT ========== -->
<main class="flex-1 overflow-x-hidden overflow-y-auto {{ $currentTheme['body'] }} p-6"> <!-- Sidebar Toggle (Mobile) -->
<div class="sticky top-[3.75rem] inset-x-0 z-20 bg-white border-y px-4 sm:px-6 md:px-8 lg:hidden dark:bg-gray-800 dark:border-gray-700">
<div class="flex items-center py-4">
<!-- Navigation Toggle -->
<button type="button" class="text-gray-500 hover:text-gray-600" @click="sidebarOpen = !sidebarOpen">
<span class="sr-only">Toggle Navigation</span>
<svg class="w-5 h-5" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
</svg>
</button>
<!-- End Navigation Toggle -->
<!-- Breadcrumb -->
<ol class="ms-3 flex items-center whitespace-nowrap" aria-label="Breadcrumb">
<li class="flex items-center text-sm text-gray-800 dark:text-gray-400">
Star Cloud
<svg class="flex-shrink-0 mx-3 overflow-visible h-2.5 w-2.5 text-gray-400 dark:text-gray-600" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 1L10.6869 7.16086C10.8637 7.35239 10.8637 7.64761 10.6869 7.83914L5 14" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
</li>
<li class="text-sm font-semibold text-gray-800 truncate dark:text-gray-200" aria-current="page">
Dashboard
</li>
</ol>
<!-- End Breadcrumb -->
</div>
</div>
<!-- End Sidebar Toggle -->
<!-- Sidebar -->
<div id="application-sidebar"
class="fixed top-0 left-0 bottom-0 z-[60] w-64 bg-white border-r border-gray-200 pt-7 pb-10 overflow-y-auto transition-transform duration-300 transform lg:translate-x-0 dark:bg-gray-800 dark:border-gray-700"
:class="sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'">
<!-- Close Button (Mobile) -->
<button type="button" @click="sidebarOpen = false" class="absolute top-4 right-4 text-gray-500 hover:text-gray-700 lg:hidden dark:text-gray-400 dark:hover:text-gray-200">
<span class="sr-only">Close sidebar</span>
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
<div class="px-6">
<a class="flex-none text-xl font-semibold dark:text-white" href="#" aria-label="Brand">Star Cloud</a>
</div>
<nav class="p-6 w-full flex flex-col flex-wrap">
<ul class="space-y-1.5">
@include('layouts.partials.sidebar-menu')
</ul>
</nav>
</div>
<!-- End Sidebar -->
<!-- Content -->
<div class="w-full pt-10 px-4 sm:px-6 md:px-8 lg:pl-72">
<main>
@yield('content') @yield('content')
</main> </main>
</div> </div>
</div> <!-- End Content -->
@yield('scripts')
</body> </body>
</html> </html>

View File

@@ -1,374 +1,278 @@
{{-- 1. 儀表板 (獨立項目) --}} {{-- 1. 儀表板 --}}
<a href="{{ route('admin.dashboard') }}" <li>
@click="if (window.innerWidth < 1024) sidebarOpen = false" <a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.dashboard') ? 'bg-gray-100 dark:bg-gray-900 text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.dashboard') }}">
class="group flex items-center px-2 py-2 text-sm font-medium rounded-md {{ request()->routeIs('admin.dashboard') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}"> <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="7" height="9" x="3" y="3" rx="1"/><rect width="7" height="5" x="14" y="3" rx="1"/><rect width="7" height="9" x="14" y="12" rx="1"/><rect width="7" height="5" x="3" y="16" rx="1"/></svg>
<svg class="mr-3 h-5 w-5 {{ request()->routeIs('admin.dashboard') ? 'text-white' : ($isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300') }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" />
</svg>
儀表板 儀表板
</a> </a>
</li>
{{-- 2. 應用程式 --}} {{-- 2. 應用程式 (個人) --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_profile') === 'true' || {{ request()->routeIs('profile.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_profile') === 'true' || {{ request()->routeIs('profile.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_profile', open)"
init() { class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
this.$watch('open', value => localStorage.setItem('menu_profile', value)) <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
} 個人設定
}"> <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
<span class="flex-1 text-left">應用程式</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('profile.edit') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('profile.edit') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">個人檔案</a> <ul class="pt-2 ps-2">
</div> <li>
<a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('profile.edit') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('profile.edit') }}">
個人檔案
</a>
</li>
</ul>
</div> </div>
</li>
{{-- 會員管理 (新增) --}} {{-- 3. 會員管理 --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_members') === 'true' || {{ request()->routeIs('admin.members.*') || request()->routeIs('admin.membership-tiers.*') || request()->routeIs('admin.deposit-bonus-rules.*') || request()->routeIs('admin.point-rules.*') || request()->routeIs('admin.gift-definitions.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_members') === 'true' || {{ request()->routeIs('admin.members.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_members', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
init() { <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" /></svg>
this.$watch('open', value => localStorage.setItem('menu_members', value)) 會員管理
} <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
<span class="flex-1 text-left">會員管理</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('admin.members.index') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.members.index') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">會員列表</a> <ul class="pt-2 ps-2">
<a href="{{ route('admin.membership-tiers.index') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.membership-tiers.*') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">會員等級設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.members.index') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.members.index') }}">會員列表</a></li>
<a href="{{ route('admin.deposit-bonus-rules.index') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.deposit-bonus-rules.*') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">儲值回饋設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.membership-tiers.*') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.membership-tiers.index') }}">會員等級</a></li>
<a href="{{ route('admin.point-rules.index') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.point-rules.*') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">點數規則設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.deposit-bonus-rules.*') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.deposit-bonus-rules.index') }}">儲值回饋</a></li>
<a href="{{ route('admin.gift-definitions.index') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.gift-definitions.*') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">禮品設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.point-rules.*') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.point-rules.index') }}">點數規則</a></li>
</div> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.gift-definitions.*') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.gift-definitions.index') }}">禮品設定</a></li>
</ul>
</div> </div>
</li>
{{-- 3. 機台管理 --}} {{-- 4. 機台管理 --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_machines') === 'true' || {{ request()->routeIs('admin.machines.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_machines') === 'true' || {{ request()->routeIs('admin.machines.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_machines', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
init() { <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 01-2 2v4a2 2 0 012 2h14a2 2 0 012-2v-4a2 2 0 01-2-2m-2-4h.01M17 16h.01" /></svg>
this.$watch('open', value => localStorage.setItem('menu_machines', value)) 機台管理
} <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 01-2 2v4a2 2 0 012 2h14a2 2 0 012-2v-4a2 2 0 01-2-2m-2-4h.01M17 16h.01" />
</svg>
<span class="flex-1 text-left">機台管理</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('admin.machines.logs') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.machines.logs') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">機台日誌</a> <ul class="pt-2 ps-2">
<a href="{{ route('admin.machines.index') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.machines.index') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">機台列表</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.machines.logs') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.machines.logs') }}">機台日誌</a></li>
<a href="{{ route('admin.machines.permissions') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.machines.permissions') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">機台權限</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.machines.index') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.machines.index') }}">機台列表</a></li>
<a href="{{ route('admin.machines.utilization') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.machines.utilization') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">機台稼動率</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.machines.permissions') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.machines.permissions') }}">機台權限</a></li>
<a href="{{ route('admin.machines.expiry') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.machines.expiry') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">效期管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.machines.utilization') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.machines.utilization') }}">機台稼動率</a></li>
<a href="{{ route('admin.machines.maintenance') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.machines.maintenance') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">維修管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.machines.expiry') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.machines.expiry') }}">效期管理</a></li>
</div> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.machines.maintenance') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.machines.maintenance') }}">維修管理單</a></li>
</ul>
</div> </div>
</li>
{{-- 4. APP管理 --}} {{-- 5. APP管理 --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_app') === 'true' || {{ request()->routeIs('admin.app.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_app') === 'true' || {{ request()->routeIs('admin.app.*') || request()->routeIs('admin.app-configs.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_app', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
init() { <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z" /></svg>
this.$watch('open', value => localStorage.setItem('menu_app', value)) APP管理
} <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z" />
</svg>
<span class="flex-1 text-left">APP管理</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('admin.app.ui-elements') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.app.ui-elements') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">UI元素設定</a> <ul class="pt-2 ps-2">
<a href="{{ route('admin.app.helper') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.app.helper') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">小幫手設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.app.ui-elements') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.app.ui-elements') }}">UI元素</a></li>
<a href="{{ route('admin.app.questionnaire') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.app.questionnaire') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">問卷設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.app.helper') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.app.helper') }}">小幫手</a></li>
<a href="{{ route('admin.app.games') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.app.games') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">互動遊戲設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.app.questionnaire') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.app.questionnaire') }}">問卷</a></li>
<a href="{{ route('admin.app.timer') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.app.timer') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">計時器</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.app.games') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.app.games') }}">互動遊戲</a></li>
</div> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.app.timer') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.app.timer') }}">計時器</a></li>
</ul>
</div> </div>
</li>
{{-- 5. 倉庫管理 --}} {{-- 6. 倉庫管理 --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_warehouses') === 'true' || {{ request()->routeIs('admin.warehouses.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_warehouses') === 'true' || {{ request()->routeIs('admin.warehouses.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_warehouses', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
init() { <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" /></svg>
this.$watch('open', value => localStorage.setItem('menu_warehouses', value)) 倉庫管理
} <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
<span class="flex-1 text-left">倉庫管理</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('admin.warehouses.index') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.warehouses.index') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">倉庫列表(全部)</a> <ul class="pt-2 ps-2">
<a href="{{ route('admin.warehouses.personal') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.warehouses.personal') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">倉庫列表(個人)</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.warehouses.index') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.warehouses.index') }}">倉庫列表()</a></li>
<a href="{{ route('admin.warehouses.stock-management') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.warehouses.stock-management') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">庫存管理單</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.warehouses.personal') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.warehouses.personal') }}">倉庫列表()</a></li>
<a href="{{ route('admin.warehouses.transfers') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.warehouses.transfers') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">調撥</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.warehouses.stock-management') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.warehouses.stock-management') }}">庫存管理</a></li>
<a href="{{ route('admin.warehouses.purchases') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.warehouses.purchases') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">採購</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.warehouses.transfers') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.warehouses.transfers') }}">調撥</a></li>
<a href="{{ route('admin.warehouses.replenishments') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.warehouses.replenishments') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">機台補貨</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.warehouses.purchases') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.warehouses.purchases') }}">採購</a></li>
<a href="{{ route('admin.warehouses.replenishment-records') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.warehouses.replenishment-records') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">機台補貨紀錄</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.warehouses.replenishments') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.warehouses.replenishments') }}">機台補貨</a></li>
<a href="{{ route('admin.warehouses.replenishment-records-all') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.warehouses.replenishment-records-all') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">機台補貨紀錄()</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.warehouses.replenishment-records') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.warehouses.replenishment-records') }}">機台補貨紀錄</a></li>
<a href="{{ route('admin.warehouses.machine-stock') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.warehouses.machine-stock') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">機台庫存</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.warehouses.machine-stock') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.warehouses.machine-stock') }}">機台庫存</a></li>
<a href="{{ route('admin.warehouses.staff-stock') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.warehouses.staff-stock') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">人員庫存</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.warehouses.staff-stock') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.warehouses.staff-stock') }}">人員庫存</a></li>
<a href="{{ route('admin.warehouses.returns') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.warehouses.returns') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">回庫單</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.warehouses.returns') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.warehouses.returns') }}">回庫單</a></li>
</div> </ul>
</div> </div>
</li>
{{-- 6. 銷售管理 --}} {{-- 7. 銷售管理 --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_sales') === 'true' || {{ request()->routeIs('admin.sales.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_sales') === 'true' || {{ request()->routeIs('admin.sales.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_sales', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
init() { <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
this.$watch('open', value => localStorage.setItem('menu_sales', value)) 銷售管理
} <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="flex-1 text-left">銷售管理</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('admin.sales.index') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.sales.index') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">銷售&金流紀錄</a> <ul class="pt-2 ps-2">
<a href="{{ route('admin.sales.pickup-codes') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.sales.pickup-codes') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">取貨碼設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.sales.index') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.sales.index') }}">銷售紀錄</a></li>
<a href="{{ route('admin.sales.orders') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.sales.orders') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">購買單</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.sales.pickup-codes') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.sales.pickup-codes') }}">取貨碼</a></li>
<a href="{{ route('admin.sales.promotions') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.sales.promotions') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">促銷時段設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.sales.orders') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.sales.orders') }}">購買單</a></li>
<a href="{{ route('admin.sales.pass-codes') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.sales.pass-codes') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">通行碼設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.sales.promotions') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.sales.promotions') }}">促銷時段</a></li>
<a href="{{ route('admin.sales.store-gifts') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.sales.store-gifts') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">來店禮設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.sales.pass-codes') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.sales.pass-codes') }}">通行碼</a></li>
</div> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.sales.store-gifts') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.sales.store-gifts') }}">來店禮</a></li>
</ul>
</div> </div>
</li>
{{-- 7. 分析管理 --}} {{-- 8. 分析管理 --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_analysis') === 'true' || {{ request()->routeIs('admin.analysis.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_analysis') === 'true' || {{ request()->routeIs('admin.analysis.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_analysis', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
init() { <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" /></svg>
this.$watch('open', value => localStorage.setItem('menu_analysis', value)) 分析管理
} <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
</svg>
<span class="flex-1 text-left">分析管理</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('admin.analysis.change-stock') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.analysis.change-stock') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">零錢庫存分析</a> <ul class="pt-2 ps-2">
<a href="{{ route('admin.analysis.machine-reports') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.analysis.machine-reports') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">機台報表分析</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.analysis.change-stock') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.analysis.change-stock') }}">零錢庫存</a></li>
<a href="{{ route('admin.analysis.product-reports') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.analysis.product-reports') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">商品報表分析</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.analysis.machine-reports') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.analysis.machine-reports') }}">機台報表</a></li>
<a href="{{ route('admin.analysis.survey-analysis') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.analysis.survey-analysis') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">互動問卷分析</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.analysis.product-reports') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.analysis.product-reports') }}">商品報表</a></li>
</div> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.analysis.survey-analysis') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.analysis.survey-analysis') }}">問卷分析</a></li>
</ul>
</div> </div>
</li>
{{-- 8. 稽核管理 --}} {{-- 9. 稽核管理 --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_audit') === 'true' || {{ request()->routeIs('admin.audit.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_audit') === 'true' || {{ request()->routeIs('admin.audit.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_audit', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
init() { <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg>
this.$watch('open', value => localStorage.setItem('menu_audit', value)) 稽核管理
} <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<span class="flex-1 text-left">稽核管理</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('admin.audit.purchases') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.audit.purchases') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">採購單稽核</a> <ul class="pt-2 ps-2">
<a href="{{ route('admin.audit.transfers') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.audit.transfers') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">調撥單稽核</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.audit.purchases') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.audit.purchases') }}">採購單</a></li>
<a href="{{ route('admin.audit.replenishments') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.audit.replenishments') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">補貨單稽核</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.audit.transfers') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.audit.transfers') }}">調撥單</a></li>
</div> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.audit.replenishments') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.audit.replenishments') }}">補貨單</a></li>
</ul>
</div> </div>
</li>
{{-- 9. 資料設定 --}} {{-- 10. 資料設定 --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_data_config') === 'true' || {{ request()->routeIs('admin.data-config.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_data_config') === 'true' || {{ request()->routeIs('admin.data-config.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_data_config', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
init() { <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.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 stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /></svg>
this.$watch('open', value => localStorage.setItem('menu_data_config', value)) 資料設定
} <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.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 stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
<span class="flex-1 text-left">資料設定</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('admin.data-config.products') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.data-config.products') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">商品管理</a> <ul class="pt-2 ps-2">
<a href="{{ route('admin.data-config.advertisements') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.data-config.advertisements') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">廣告管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.data-config.products') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.data-config.products') }}">商品管理</a></li>
<a href="{{ route('admin.data-config.admin-products') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.data-config.admin-products') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">管理者可賣商品</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.data-config.advertisements') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.data-config.advertisements') }}">廣告管理</a></li>
<a href="{{ route('admin.data-config.accounts') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.data-config.accounts') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">帳號管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.data-config.admin-products') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.data-config.admin-products') }}">管理者可賣</a></li>
<a href="{{ route('admin.data-config.sub-accounts') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.data-config.sub-accounts') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">帳號管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.data-config.accounts') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.data-config.accounts') }}">帳號管理</a></li>
<a href="{{ route('admin.data-config.sub-account-roles') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.data-config.sub-account-roles') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">子帳號角色管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.data-config.sub-accounts') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.data-config.sub-accounts') }}">子帳號</a></li>
<a href="{{ route('admin.data-config.points') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.data-config.points') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">點數設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.data-config.sub-account-roles') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.data-config.sub-account-roles') }}">子帳號角色</a></li>
<a href="{{ route('admin.data-config.badges') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.data-config.badges') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">識別證管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.data-config.points') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.data-config.points') }}">點數設定</a></li>
</div> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.data-config.badges') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.data-config.badges') }}">識別證</a></li>
</ul>
</div> </div>
</li>
{{-- 10. 遠端管理 --}}
<div x-data="{
open: localStorage.getItem('menu_remote') === 'true' || {{ request()->routeIs('admin.remote.*') ? 'true' : 'false' }},
init() {
this.$watch('open', value => localStorage.setItem('menu_remote', value))
}
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5.636 18.364a9 9 0 010-12.728m12.728 0a9 9 0 010 12.728m-9.9-2.829a5 5 0 010-7.07m7.072 0a5 5 0 010 7.07M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="flex-1 text-left">遠端管理</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1">
<a href="{{ route('admin.remote.stock') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.remote.stock') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">機台庫存</a>
<a href="{{ route('admin.remote.restart') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.remote.restart') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">機台重啟</a>
<a href="{{ route('admin.remote.restart-card-reader') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.remote.restart-card-reader') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">卡機重啟</a>
<a href="{{ route('admin.remote.checkout') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.remote.checkout') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">遠端結帳</a>
<a href="{{ route('admin.remote.lock') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.remote.lock') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">遠端鎖定頁</a>
<a href="{{ route('admin.remote.change') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.remote.change') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">遠端找零</a>
<a href="{{ route('admin.remote.dispense') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.remote.dispense') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">遠端出貨</a>
</div>
</div>
{{-- 11. Line管理 --}} {{-- 11. 遠端管理 --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_remote') === 'true' || {{ request()->routeIs('admin.remote.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_line') === 'true' || {{ request()->routeIs('admin.line.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_remote', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
init() { <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M5.636 18.364a9 9 0 010-12.728m12.728 0a9 9 0 010 12.728m-9.9-2.829a5 5 0 010-7.07m7.072 0a5 5 0 010 7.07M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
this.$watch('open', value => localStorage.setItem('menu_line', value)) 遠端管理
} <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
<span class="flex-1 text-left">Line管理</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('admin.line.members') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.line.members') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line會員管理</a> <ul class="pt-2 ps-2">
<a href="{{ route('admin.line.machines') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.line.machines') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line機台管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.remote.stock') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.remote.stock') }}">機台庫存</a></li>
<a href="{{ route('admin.line.products') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.line.products') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line商城商品</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.remote.restart') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.remote.restart') }}">機台重啟</a></li>
<a href="{{ route('admin.line.official-account') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.line.official-account') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line生活圈</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.remote.restart-card-reader') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.remote.restart-card-reader') }}">卡機重啟</a></li>
<a href="{{ route('admin.line.orders') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.line.orders') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line商城訂單</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.remote.checkout') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.remote.checkout') }}">遠端結帳</a></li>
<a href="{{ route('admin.line.coupons') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.line.coupons') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line優惠券</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.remote.lock') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.remote.lock') }}">遠端鎖定</a></li>
</div> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.remote.change') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.remote.change') }}">遠端找零</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.remote.dispense') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.remote.dispense') }}">遠端出貨</a></li>
</ul>
</div> </div>
</li>
{{-- 12. 預約系統 --}} {{-- 12. Line管理 --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_line') === 'true' || {{ request()->routeIs('admin.line.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_reservation') === 'true' || {{ request()->routeIs('admin.reservation.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_line', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
init() { <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" /></svg>
this.$watch('open', value => localStorage.setItem('menu_reservation', value)) Line管理
} <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<span class="flex-1 text-left">預約系統</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('admin.reservation.members') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.reservation.members') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line會員管理</a> <ul class="pt-2 ps-2">
<a href="{{ route('admin.reservation.stores') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.reservation.stores') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line店家管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.line.members') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.line.members') }}">Line會員</a></li>
<a href="{{ route('admin.reservation.time-slots') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.reservation.time-slots') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line時段組合</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.line.machines') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.line.machines') }}">Line機台</a></li>
<a href="{{ route('admin.reservation.venues') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.reservation.venues') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line場地管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.line.products') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.line.products') }}">Line商品</a></li>
<a href="{{ route('admin.reservation.coupons') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.reservation.coupons') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line優惠券管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.line.official-account') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.line.official-account') }}">Line生活圈</a></li>
<a href="{{ route('admin.reservation.reservations') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.reservation.reservations') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line預約管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.line.orders') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.line.orders') }}">Line訂單</a></li>
<a href="{{ route('admin.reservation.orders') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.reservation.orders') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line訂單管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.line.coupons') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.line.coupons') }}">Line優惠券</a></li>
</div> </ul>
</div> </div>
</li>
{{-- 13. 特殊權限管理 --}} {{-- 13. 預約系統 --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_reservation') === 'true' || {{ request()->routeIs('admin.reservation.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_special_permission') === 'true' || {{ request()->routeIs('admin.special-permission.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_reservation', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
init() { <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /></svg>
this.$watch('open', value => localStorage.setItem('menu_special_permission', value)) 預約系統
} <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
</svg>
<span class="flex-1 text-left">特殊權限管理</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('admin.special-permission.clear-stock') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.special-permission.clear-stock') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">庫存清空</a> <ul class="pt-2 ps-2">
<a href="{{ route('admin.special-permission.apk-versions') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.special-permission.apk-versions') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">APK版本管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.reservation.members') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.reservation.members') }}">預約會員</a></li>
<a href="{{ route('admin.special-permission.discord-notifications') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.special-permission.discord-notifications') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Discord通知設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.reservation.stores') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.reservation.stores') }}">店家管理</a></li>
</div> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.reservation.time-slots') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.reservation.time-slots') }}">時段組合</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.reservation.venues') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.reservation.venues') }}">場地管理</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.reservation.coupons') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.reservation.coupons') }}">優惠券</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.reservation.reservations') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.reservation.reservations') }}">預約管理</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.reservation.orders') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.reservation.orders') }}">訂單管理</a></li>
</ul>
</div> </div>
</li>
{{-- 14. 權限設定 --}} {{-- 14. 特殊權限 --}}
<div x-data="{ <li x-data="{ open: localStorage.getItem('menu_special_permission') === 'true' || {{ request()->routeIs('admin.special-permission.*') ? 'true' : 'false' }} }">
open: localStorage.getItem('menu_permissions') === 'true' || {{ request()->routeIs('admin.permission.*') ? 'true' : 'false' }}, <button type="button" @click="open = !open; localStorage.setItem('menu_special_permission', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
init() { <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" /></svg>
this.$watch('open', value => localStorage.setItem('menu_permissions', value)) 特殊權限
} <svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
}">
<button @click="open = !open" class="group flex items-center w-full px-2 py-2 text-sm font-medium rounded-md {{ $isLight ? 'text-gray-700 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white' }}">
<svg class="mr-3 h-5 w-5 {{ $isLight ? 'text-gray-400 group-hover:text-gray-500' : 'text-gray-400 group-hover:text-gray-300' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z" />
</svg>
<span class="flex-1 text-left">權限設定</span>
<svg class="ml-auto h-5 w-5 transform transition-transform duration-200" :class="{'rotate-90': open}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button> </button>
<div x-show="open" x-collapse.duration.500ms class="mt-1 space-y-1"> <div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<a href="{{ route('admin.permission.app-features') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.permission.app-features') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">APP功能管理</a> <ul class="pt-2 ps-2">
<a href="{{ route('admin.permission.data-config') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.permission.data-config') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">資料設定</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.special-permission.clear-stock') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.special-permission.clear-stock') }}">庫存清空</a></li>
<a href="{{ route('admin.permission.sales') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.permission.sales') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">銷售管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.special-permission.apk-versions') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.special-permission.apk-versions') }}">APK版本</a></li>
<a href="{{ route('admin.permission.machines') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.permission.machines') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">機台管理</a> <li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.special-permission.discord-notifications') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.special-permission.discord-notifications') }}">Discord通知</a></li>
<a href="{{ route('admin.permission.warehouses') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.permission.warehouses') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">倉庫管理</a> </ul>
<a href="{{ route('admin.permission.analysis') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.permission.analysis') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">分析管理</a>
<a href="{{ route('admin.permission.audit') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.permission.audit') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">稽核管理</a>
<a href="{{ route('admin.permission.remote') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.permission.remote') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">遠端管理</a>
<a href="{{ route('admin.permission.line') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.permission.line') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">Line管理</a>
<a href="{{ route('admin.permission.roles') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.permission.roles') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">權限角色設定</a>
<a href="{{ route('admin.permission.others') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.permission.others') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">其他功能管理</a>
<a href="{{ route('admin.permission.ai-prediction') }}" @click="if (window.innerWidth < 1024) sidebarOpen = false" class="group flex items-center pl-14 pr-2 py-2 text-sm rounded-md {{ request()->routeIs('admin.permission.ai-prediction') ? 'bg-'.$currentTheme['accent'].'-600 text-white' : ($isLight ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 hover:bg-gray-700 hover:text-white') }}" style="padding-left: 3.5rem;">AI智能預測</a>
</div> </div>
</li>
{{-- 15. 權限設定 --}}
<li x-data="{ open: localStorage.getItem('menu_permissions') === 'true' || {{ request()->routeIs('admin.permission.*') ? 'true' : 'false' }} }">
<button type="button" @click="open = !open; localStorage.setItem('menu_permissions', open)" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300">
<svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z" /></svg>
權限設定
<svg class="ms-auto w-4 h-4 transition-transform duration-300" :class="{ 'rotate-180': open, 'rotate-0': !open }" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
</button>
<div x-show="open" x-collapse class="w-full overflow-hidden transition-[height] duration-300">
<ul class="pt-2 ps-2">
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.permission.app-features') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.permission.app-features') }}">APP功能</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.permission.data-config') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.permission.data-config') }}">資料設定</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.permission.sales') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.permission.sales') }}">銷售管理</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.permission.machines') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.permission.machines') }}">機台管理</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.permission.warehouses') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.permission.warehouses') }}">倉庫管理</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.permission.analysis') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.permission.analysis') }}">分析管理</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.permission.audit') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.permission.audit') }}">稽核管理</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.permission.remote') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.permission.remote') }}">遠端管理</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.permission.line') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.permission.line') }}">Line管理</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.permission.roles') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.permission.roles') }}">角色設定</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.permission.others') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.permission.others') }}">其他功能</a></li>
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-gray-400 dark:hover:text-gray-300 {{ request()->routeIs('admin.permission.ai-prediction') ? 'text-blue-600 dark:text-blue-500' : '' }}" href="{{ route('admin.permission.ai-prediction') }}">AI智能預測</a></li>
</ul>
</div> </div>
</li>

View File

@@ -8,7 +8,7 @@ export default {
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php', './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./storage/framework/views/*.php', './storage/framework/views/*.php',
'./resources/views/**/*.blade.php', './resources/views/**/*.blade.php',
'./node_modules/preline/preline.js', './node_modules/preline/dist/*.js',
], ],
safelist: [ safelist: [
@@ -30,5 +30,7 @@ export default {
}, },
}, },
plugins: [forms], plugins: [
forms,
],
}; };