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.empty') }}
- @else -{{ __('devices.none_match') }}
+