feat(app-ui): UI組合編輯/機台設定 也加每頁筆數+搜尋+分頁
抽共用元件 x-app-list-controls(3頁共用);bundles 依名稱、machines 依名稱/序號搜尋 paginate Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
32dfa2bdd1
commit
888db7ffe7
@ -99,11 +99,19 @@ class UiElementController extends Controller
|
|||||||
// 頁籤二:UI 組合編輯
|
// 頁籤二:UI 組合編輯
|
||||||
// ==================================================================
|
// ==================================================================
|
||||||
|
|
||||||
public function bundles()
|
public function bundles(Request $request)
|
||||||
{
|
{
|
||||||
$bundles = UiBundle::orderBy('id')->get();
|
$perPage = (int) $request->input('per_page', 10);
|
||||||
|
$perPage = in_array($perPage, [10, 25, 50, 100], true) ? $perPage : 10;
|
||||||
|
$search = trim((string) $request->input('search', ''));
|
||||||
|
|
||||||
return view('admin.app.ui-bundles.index', compact('bundles'));
|
$query = UiBundle::orderBy('id');
|
||||||
|
if ($search !== '') {
|
||||||
|
$query->where('name', 'like', "%{$search}%");
|
||||||
|
}
|
||||||
|
$bundles = $query->paginate($perPage)->withQueryString();
|
||||||
|
|
||||||
|
return view('admin.app.ui-bundles.index', compact('bundles', 'perPage', 'search'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function storeBundle(Request $request)
|
public function storeBundle(Request $request)
|
||||||
@ -186,16 +194,28 @@ class UiElementController extends Controller
|
|||||||
|
|
||||||
public function machines(Request $request)
|
public function machines(Request $request)
|
||||||
{
|
{
|
||||||
$machines = Machine::orderBy('name')->paginate(20);
|
$perPage = (int) $request->input('per_page', 25);
|
||||||
$bundles = UiBundle::orderBy('name')->get();
|
$perPage = in_array($perPage, [10, 25, 50, 100], true) ? $perPage : 25;
|
||||||
|
$search = trim((string) $request->input('search', ''));
|
||||||
|
|
||||||
// 現有綁定名稱對照
|
$query = Machine::orderBy('name');
|
||||||
|
if ($search !== '') {
|
||||||
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->where('name', 'like', "%{$search}%")
|
||||||
|
->orWhere('serial_no', 'like', "%{$search}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$machines = $query->paginate($perPage)->withQueryString();
|
||||||
|
|
||||||
|
$bundles = UiBundle::orderBy('name')->get();
|
||||||
$bundleNames = $bundles->pluck('name', 'id');
|
$bundleNames = $bundles->pluck('name', 'id');
|
||||||
|
|
||||||
return view('admin.app.ui-machines.index', [
|
return view('admin.app.ui-machines.index', [
|
||||||
'machines' => $machines,
|
'machines' => $machines,
|
||||||
'bundles' => $bundles,
|
'bundles' => $bundles,
|
||||||
'bundleNames' => $bundleNames,
|
'bundleNames' => $bundleNames,
|
||||||
|
'perPage' => $perPage,
|
||||||
|
'search' => $search,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2350,6 +2350,8 @@
|
|||||||
"No data": "No data",
|
"No data": "No data",
|
||||||
"entries": "entries",
|
"entries": "entries",
|
||||||
"Search name or category...": "Search name or category...",
|
"Search name or category...": "Search name or category...",
|
||||||
|
"Search name...": "Search name...",
|
||||||
|
"Search machine or serial...": "Search machine or serial...",
|
||||||
"Back": "Back",
|
"Back": "Back",
|
||||||
"Rename": "Rename",
|
"Rename": "Rename",
|
||||||
"Content Settings": "Content Settings",
|
"Content Settings": "Content Settings",
|
||||||
|
|||||||
@ -2351,6 +2351,8 @@
|
|||||||
"No data": "無資料",
|
"No data": "無資料",
|
||||||
"entries": "筆",
|
"entries": "筆",
|
||||||
"Search name or category...": "搜尋名稱或類別…",
|
"Search name or category...": "搜尋名稱或類別…",
|
||||||
|
"Search name...": "搜尋名稱…",
|
||||||
|
"Search machine or serial...": "搜尋機台名稱或序號…",
|
||||||
"Back": "返回",
|
"Back": "返回",
|
||||||
"Rename": "重新命名",
|
"Rename": "重新命名",
|
||||||
"Content Settings": "內容設定",
|
"Content Settings": "內容設定",
|
||||||
|
|||||||
@ -9,6 +9,8 @@
|
|||||||
</button>
|
</button>
|
||||||
</x-app-tabs>
|
</x-app-tabs>
|
||||||
|
|
||||||
|
<x-app-list-controls :route="route('admin.app.ui-bundles')" :perPage="$perPage" :search="$search" :placeholder="__('Search name...')" />
|
||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full bg-white dark:bg-gray-800 rounded-lg overflow-hidden">
|
<table class="min-w-full bg-white dark:bg-gray-800 rounded-lg overflow-hidden">
|
||||||
<thead class="bg-gray-100 dark:bg-gray-700">
|
<thead class="bg-gray-100 dark:bg-gray-700">
|
||||||
@ -48,6 +50,10 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
{{ $bundles->links() }}
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- 新增組合 Modal --}}
|
{{-- 新增組合 Modal --}}
|
||||||
<div x-show="showCreate" x-cloak class="fixed inset-0 z-50 overflow-y-auto" @keydown.escape.window="showCreate = false">
|
<div x-show="showCreate" x-cloak class="fixed inset-0 z-50 overflow-y-auto" @keydown.escape.window="showCreate = false">
|
||||||
<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">
|
||||||
|
|||||||
@ -9,27 +9,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</x-app-tabs>
|
</x-app-tabs>
|
||||||
|
|
||||||
{{-- 控制列:每頁筆數 + 搜尋 --}}
|
<x-app-list-controls :route="route('admin.app.ui-elements')" :perPage="$perPage" :search="$search" :placeholder="__('Search name or category...')" />
|
||||||
<form method="GET" action="{{ route('admin.app.ui-elements') }}" class="flex flex-wrap items-center justify-between gap-3 mb-4">
|
|
||||||
<div class="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400">
|
|
||||||
<span>{{ __('Show') }}</span>
|
|
||||||
<select name="per_page" onchange="this.form.submit()" class="luxury-input py-1.5 px-2 text-sm w-auto">
|
|
||||||
@foreach([10, 25, 50, 100] as $n)
|
|
||||||
<option value="{{ $n }}" {{ $perPage === $n ? 'selected' : '' }}>{{ $n }}</option>
|
|
||||||
@endforeach
|
|
||||||
</select>
|
|
||||||
<span>{{ __('entries') }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<input type="text" name="search" value="{{ $search }}" placeholder="{{ __('Search name or category...') }}" class="luxury-input py-2 px-3 text-sm sm:w-72">
|
|
||||||
<button type="submit" class="p-2.5 rounded-xl bg-cyan-500 text-white hover:bg-cyan-600 shadow-lg shadow-cyan-500/25 transition-all active:scale-95" title="{{ __('Search') }}">
|
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg>
|
|
||||||
</button>
|
|
||||||
<a href="{{ route('admin.app.ui-elements') }}" class="p-2.5 rounded-xl bg-slate-100 dark:bg-slate-800 text-slate-500 hover:bg-slate-200 dark:hover:bg-slate-700 transition-all active:scale-95" title="{{ __('Reset') }}">
|
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" /></svg>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full bg-white dark:bg-gray-800 rounded-lg overflow-hidden">
|
<table class="min-w-full bg-white dark:bg-gray-800 rounded-lg overflow-hidden">
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
<div class="px-6 py-8">
|
<div class="px-6 py-8">
|
||||||
<x-app-tabs active="machines" />
|
<x-app-tabs active="machines" />
|
||||||
|
|
||||||
|
<x-app-list-controls :route="route('admin.app.ui-machines')" :perPage="$perPage" :search="$search" :placeholder="__('Search machine or serial...')" />
|
||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full bg-white dark:bg-gray-800 rounded-lg overflow-hidden">
|
<table class="min-w-full bg-white dark:bg-gray-800 rounded-lg overflow-hidden">
|
||||||
<thead class="bg-gray-100 dark:bg-gray-700">
|
<thead class="bg-gray-100 dark:bg-gray-700">
|
||||||
|
|||||||
29
resources/views/components/app-list-controls.blade.php
Normal file
29
resources/views/components/app-list-controls.blade.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{{-- APP UI元素設定 列表控制列:每頁筆數下拉(左)+ 搜尋欄/重置(右)。一般 GET 表單(非 AJAX)。
|
||||||
|
用法:<x-app-list-controls :route="route('admin.app.ui-elements')" :perPage="$perPage" :search="$search" :placeholder="__('...')" /> --}}
|
||||||
|
@props([
|
||||||
|
'route' => '',
|
||||||
|
'perPage' => 10,
|
||||||
|
'search' => '',
|
||||||
|
'placeholder' => '',
|
||||||
|
])
|
||||||
|
|
||||||
|
<form method="GET" action="{{ $route }}" class="flex flex-wrap items-center justify-between gap-3 mb-4">
|
||||||
|
<div class="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
<span>{{ __('Show') }}</span>
|
||||||
|
<select name="per_page" onchange="this.form.submit()" class="luxury-input py-1.5 px-2 text-sm w-auto">
|
||||||
|
@foreach([10, 25, 50, 100] as $n)
|
||||||
|
<option value="{{ $n }}" {{ (int)$perPage === $n ? 'selected' : '' }}>{{ $n }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
<span>{{ __('entries') }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<input type="text" name="search" value="{{ $search }}" placeholder="{{ $placeholder ?: __('Search...') }}" class="luxury-input py-2 px-3 text-sm sm:w-72">
|
||||||
|
<button type="submit" class="p-2.5 rounded-xl bg-cyan-500 text-white hover:bg-cyan-600 shadow-lg shadow-cyan-500/25 transition-all active:scale-95" title="{{ __('Search') }}">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg>
|
||||||
|
</button>
|
||||||
|
<a href="{{ $route }}" class="p-2.5 rounded-xl bg-slate-100 dark:bg-slate-800 text-slate-500 hover:bg-slate-200 dark:hover:bg-slate-700 transition-all active:scale-95" title="{{ __('Reset') }}">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" /></svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
Loading…
Reference in New Issue
Block a user