From aceb140aacb233d0f08a434fa8ab92ef8a685bfb Mon Sep 17 00:00:00 2001 From: HomeOS Bootstrap Date: Fri, 17 Jul 2026 23:30:15 +0200 Subject: [PATCH] Fix mobile sidebar readability; rework device list for scale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Sidebar drawer is now opaque (.sidebar-tint solid), so on mobile the bright content no longer bleeds through and it stays readable. - Devices index reworked for ~50 devices: live search (name/model/vendor), room + online/offline filters (URL-persisted), grouped by room with counts — scannable instead of one long list. Co-Authored-By: Claude Opus 4.8 --- app/Livewire/Devices/Index.php | 39 +++++++++-- lang/de/devices.php | 6 ++ lang/en/devices.php | 6 ++ resources/css/app.css | 3 +- .../views/livewire/devices/index.blade.php | 64 ++++++++++++------- 5 files changed, 90 insertions(+), 28 deletions(-) diff --git a/app/Livewire/Devices/Index.php b/app/Livewire/Devices/Index.php index 0782d9f..b709672 100644 --- a/app/Livewire/Devices/Index.php +++ b/app/Livewire/Devices/Index.php @@ -3,19 +3,50 @@ namespace App\Livewire\Devices; use App\Models\Device; +use App\Models\Room; use Livewire\Attributes\Layout; +use Livewire\Attributes\Url; use Livewire\Component; #[Layout('layouts.app')] class Index extends Component { + #[Url(as: 'q')] + public string $search = ''; + + #[Url] + public string $room = ''; + + #[Url] + public string $status = ''; + + public function clearFilters(): void + { + $this->reset('search', 'room', 'status'); + } + public function render() { + $devices = Device::query() + ->with(['room', 'entities.state']) + ->when($this->search, fn ($q) => $q->where(fn ($w) => $w + ->where('name', 'ilike', "%{$this->search}%") + ->orWhere('model', 'ilike', "%{$this->search}%") + ->orWhere('vendor', 'ilike', "%{$this->search}%"))) + ->when($this->room, fn ($q) => $q->whereHas('room', fn ($r) => $r->where('uuid', $this->room))) + ->orderBy('name') + ->get(); + + if ($this->status === 'online') { + $devices = $devices->filter->isOnline()->values(); + } elseif ($this->status === 'offline') { + $devices = $devices->reject->isOnline()->values(); + } + return view('livewire.devices.index', [ - 'devices' => Device::query() - ->with(['room', 'entities.state']) - ->orderBy('name') - ->get(), + 'groups' => $devices->groupBy(fn ($d) => $d->room?->name ?? __('devices.no_room')), + 'total' => $devices->count(), + 'rooms' => Room::orderBy('sort')->orderBy('name')->get(), ]); } } diff --git a/lang/de/devices.php b/lang/de/devices.php index 61dae00..73f3cfc 100644 --- a/lang/de/devices.php +++ b/lang/de/devices.php @@ -15,6 +15,12 @@ return [ // index 'index_subtitle' => 'Alle Geräte im Haus.', 'empty' => 'Noch keine Geräte.', + 'search_placeholder' => 'Geräte suchen…', + 'all_rooms' => 'Alle Räume', + 'all_status' => 'Alle Zustände', + 'clear' => 'Zurücksetzen', + 'none_match' => 'Keine Geräte gefunden.', + 'count' => '{0}Keine Geräte|{1}1 Gerät|[2,*]:count Geräte', // detail 'device' => 'Gerät', diff --git a/lang/en/devices.php b/lang/en/devices.php index 6331115..e873a01 100644 --- a/lang/en/devices.php +++ b/lang/en/devices.php @@ -15,6 +15,12 @@ return [ // index 'index_subtitle' => 'All devices in the home.', 'empty' => 'No devices yet.', + 'search_placeholder' => 'Search devices…', + 'all_rooms' => 'All rooms', + 'all_status' => 'All states', + 'clear' => 'Clear', + 'none_match' => 'No devices found.', + 'count' => '{0}No devices|{1}1 device|[2,*]:count devices', // detail 'device' => 'Device', diff --git a/resources/css/app.css b/resources/css/app.css index 27ee635..0c713cc 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -104,7 +104,8 @@ background: color-mix(in srgb, var(--color-base) 85%, transparent); backdrop-filter: blur(14px); } - .sidebar-tint { background: color-mix(in srgb, #0A101E 72%, transparent); } + /* Opaque — the mobile drawer overlays bright content, so it must be fully readable. */ + .sidebar-tint { background: #0A101E; } .pulse-live { animation: pulse 2.2s ease-in-out infinite; } .reveal { opacity: 0; transform: translateY(10px); animation: reveal .5s cubic-bezier(.2,.7,.3,1) forwards; } diff --git a/resources/views/livewire/devices/index.blade.php b/resources/views/livewire/devices/index.blade.php index 37c85d8..17230f9 100644 --- a/resources/views/livewire/devices/index.blade.php +++ b/resources/views/livewire/devices/index.blade.php @@ -2,35 +2,53 @@
- - - {{ $devices->count() }} - + {{-- filters --}} +
+
+ + +
+ + + @if ($search || $room || $status) + + @endif +
- @if ($devices->isEmpty()) -

{{ __('devices.empty') }}

- @else -
+
{{ trans_choice('devices.count', $total, ['count' => $total]) }}
+ + @forelse ($groups as $roomName => $devices) + + {{ $devices->count() }} + - @endif - + + @empty + +

{{ __('devices.none_match') }}

+
+ @endforelse