From f00a1ac069e5e0dc6fd186516a66c66d9654f468 Mon Sep 17 00:00:00 2001 From: HomeOS Bootstrap Date: Fri, 17 Jul 2026 21:52:57 +0200 Subject: [PATCH] =?UTF-8?q?Warnings=20=E2=86=92=20modal,=20device=20detail?= =?UTF-8?q?=20page,=20stable=20mock=20online=20state?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Warnings no longer clutter the dashboard: a compact "Warnungen (n)" button in the topbar opens a themed wire-elements/modal (R5) listing all messages. Dark modal wrapper overridden; HomeStatus service shared by dashboard + modal. - Device detail page (/devices/{uuid}, UUID route key): edit name, room and active state; view info + live capabilities; Neustart (with confirm modal) and "Update prüfen" as mock commands (Phase 3 routes them through the real driver). Devices index (/devices) added; "Geräte" nav activated; dashboard device rows and index link to the detail. Generic Confirm modal + x-detail component. - Mock devices no longer rot: online is now "active and (no last_seen or seen <10min)", so the demo stays healthy; the one offline device keeps a stale timestamp. Full DE/EN i18n for devices + modal copy. Verified: R12 30/30 in headless Chromium (0 console errors, 0 failed requests); 10 feature tests green. Co-Authored-By: Claude Opus 4.8 --- app/Livewire/Dashboard.php | 76 +---------- app/Livewire/Devices/Index.php | 21 +++ app/Livewire/Devices/Show.php | 77 +++++++++++ app/Livewire/Modals/Confirm.php | 46 +++++++ app/Livewire/Modals/Warnings.php | 23 ++++ app/Models/Device.php | 14 +- app/Services/HomeStatus.php | 84 ++++++++++++ database/seeders/DemoHomeSeeder.php | 6 +- lang/de/common.php | 1 + lang/de/devices.php | 40 ++++++ lang/en/common.php | 1 + lang/en/devices.php | 40 ++++++ resources/css/app.css | 2 + resources/views/components/detail.blade.php | 6 + resources/views/components/sidebar.blade.php | 4 +- resources/views/components/topbar.blade.php | 4 + resources/views/layouts/app.blade.php | 2 + resources/views/livewire/dashboard.blade.php | 70 +++------- .../views/livewire/devices/index.blade.php | 36 +++++ .../views/livewire/devices/show.blade.php | 129 ++++++++++++++++++ .../views/livewire/modals/confirm.blade.php | 30 ++++ .../views/livewire/modals/warnings.blade.php | 57 ++++++++ .../wire-elements-modal/modal.blade.php | 57 ++++++++ routes/web.php | 4 + 24 files changed, 702 insertions(+), 128 deletions(-) create mode 100644 app/Livewire/Devices/Index.php create mode 100644 app/Livewire/Devices/Show.php create mode 100644 app/Livewire/Modals/Confirm.php create mode 100644 app/Livewire/Modals/Warnings.php create mode 100644 app/Services/HomeStatus.php create mode 100644 resources/views/components/detail.blade.php create mode 100644 resources/views/livewire/devices/index.blade.php create mode 100644 resources/views/livewire/devices/show.blade.php create mode 100644 resources/views/livewire/modals/confirm.blade.php create mode 100644 resources/views/livewire/modals/warnings.blade.php create mode 100644 resources/views/vendor/wire-elements-modal/modal.blade.php diff --git a/app/Livewire/Dashboard.php b/app/Livewire/Dashboard.php index 2c8d7b4..d20ca24 100644 --- a/app/Livewire/Dashboard.php +++ b/app/Livewire/Dashboard.php @@ -2,87 +2,21 @@ namespace App\Livewire; -use App\Models\Room; -use App\Services\SystemHealth; -use Illuminate\Support\Collection; +use App\Services\HomeStatus; use Livewire\Attributes\Layout; use Livewire\Component; #[Layout('layouts.app')] class Dashboard extends Component { - private const LOW_BATTERY = 20; - - public function render() + public function render(HomeStatus $home) { - $rooms = Room::query() - ->with(['devices' => fn ($q) => $q->orderBy('name'), 'devices.entities.state']) - ->orderBy('sort')->orderBy('name') - ->get(); - - $devices = $rooms->flatMap->devices; - $entities = $devices->flatMap->entities; - - $summary = [ - 'devices_online' => $devices->filter->isOnline()->count(), - 'devices_total' => $devices->count(), - 'lights_on' => $this->countWhere($entities, fn ($e) => in_array($e->type, ['light', 'switch']) && data_get($e->state, 'state.on') === true), - 'contacts_open' => $this->countWhere($entities, fn ($e) => $e->type === 'contact' && data_get($e->state, 'state.open') === true), - 'low_battery' => $this->countWhere($entities, fn ($e) => $e->type === 'battery' && (int) data_get($e->state, 'state.percent', 100) < self::LOW_BATTERY), - ]; + $rooms = $home->load(); return view('livewire.dashboard', [ 'rooms' => $rooms, - 'summary' => $summary, - 'warnings' => $this->warnings($devices, $entities), + 'summary' => $home->summary($rooms), + 'warningCount' => count($home->warnings($rooms)), ]); } - - /** @return array */ - protected function warnings(Collection $devices, Collection $entities): array - { - $warnings = []; - - foreach ($devices->reject->isOnline() as $device) { - $warnings[] = [ - 'level' => 'offline', 'icon' => 'devices', - 'title' => $device->name, 'meta' => __('devices.offline'), 'link' => null, - ]; - } - - foreach ($entities as $entity) { - if ($entity->type === 'contact' && data_get($entity->state, 'state.open') === true) { - $warnings[] = [ - 'level' => 'warning', 'icon' => 'window', - 'title' => $entity->device->name, 'meta' => __('devices.open'), 'link' => null, - ]; - } - - if ($entity->type === 'battery') { - $percent = (int) data_get($entity->state, 'state.percent', 100); - if ($percent < self::LOW_BATTERY) { - $warnings[] = [ - 'level' => 'warning', 'icon' => 'alert', - 'title' => $entity->device->name, - 'meta' => __('devices.battery').': '.$percent.'%', 'link' => null, - ]; - } - } - } - - if (! app(SystemHealth::class)->allOnline()) { - $warnings[] = [ - 'level' => 'warning', 'icon' => 'activity', - 'title' => __('dashboard.warn_host'), 'meta' => __('dashboard.warn_host_meta'), - 'link' => route('host'), - ]; - } - - return $warnings; - } - - protected function countWhere(Collection $entities, callable $fn): int - { - return $entities->filter($fn)->count(); - } } diff --git a/app/Livewire/Devices/Index.php b/app/Livewire/Devices/Index.php new file mode 100644 index 0000000..0782d9f --- /dev/null +++ b/app/Livewire/Devices/Index.php @@ -0,0 +1,21 @@ + Device::query() + ->with(['room', 'entities.state']) + ->orderBy('name') + ->get(), + ]); + } +} diff --git a/app/Livewire/Devices/Show.php b/app/Livewire/Devices/Show.php new file mode 100644 index 0000000..3adab45 --- /dev/null +++ b/app/Livewire/Devices/Show.php @@ -0,0 +1,77 @@ +device = $device; + $this->name = $device->name; + $this->roomId = $device->room_id; + } + + public function saveName(): void + { + $this->validate(); + $this->device->update(['name' => $this->name]); + $this->flashMessage(__('devices.saved')); + } + + public function saveRoom(): void + { + $this->device->update(['room_id' => $this->roomId ?: null]); + $this->flashMessage(__('devices.saved')); + } + + public function toggleStatus(): void + { + $this->device->update([ + 'status' => $this->device->status === 'active' ? 'ignored' : 'active', + ]); + $this->flashMessage(__('devices.saved')); + } + + // Mock command paths — Phase 3 routes these through DeviceCommandService → driver (H1). + #[On('restartDevice')] + public function restart(): void + { + $this->flashMessage(__('devices.command_sent_demo')); + } + + public function checkUpdate(): void + { + $this->flashMessage(__('devices.no_update_demo')); + } + + protected function flashMessage(string $message): void + { + $this->flash = $message; + } + + public function render() + { + $this->device->load(['entities.state', 'room']); + + return view('livewire.devices.show', [ + 'rooms' => Room::orderBy('sort')->orderBy('name')->get(), + ]); + } +} diff --git a/app/Livewire/Modals/Confirm.php b/app/Livewire/Modals/Confirm.php new file mode 100644 index 0000000..8479379 --- /dev/null +++ b/app/Livewire/Modals/Confirm.php @@ -0,0 +1,46 @@ +dispatch('openModal', component: 'modals.confirm', arguments: [ + * 'title' => ..., 'body' => ..., 'confirmLabel' => ..., 'event' => 'someEvent', 'danger' => true, + * ]); + * On confirm it dispatches `event` (caught by the opener via #[On('someEvent')]) and closes. + */ +class Confirm extends ModalComponent +{ + public string $title = ''; + public string $body = ''; + public string $confirmLabel = ''; + public string $event = ''; + public bool $danger = false; + + public static function modalMaxWidth(): string + { + return 'md'; + } + + public function mount(string $title, string $body, string $confirmLabel, string $event, bool $danger = false): void + { + $this->title = $title; + $this->body = $body; + $this->confirmLabel = $confirmLabel; + $this->event = $event; + $this->danger = $danger; + } + + public function confirm(): void + { + $this->dispatch($this->event); + $this->closeModal(); + } + + public function render() + { + return view('livewire.modals.confirm'); + } +} diff --git a/app/Livewire/Modals/Warnings.php b/app/Livewire/Modals/Warnings.php new file mode 100644 index 0000000..3097b34 --- /dev/null +++ b/app/Livewire/Modals/Warnings.php @@ -0,0 +1,23 @@ + $home->warnings($home->load()), + ]); + } +} diff --git a/app/Models/Device.php b/app/Models/Device.php index aebd28e..c1be7df 100644 --- a/app/Models/Device.php +++ b/app/Models/Device.php @@ -31,11 +31,17 @@ class Device extends Model return $this->hasMany(Entity::class); } - /** Active and seen recently. */ + /** + * Reachable now. Real devices use last_seen recency (kept fresh by MQTT from Phase 3); + * a mock device with no last_seen is treated as reachable so the demo doesn't rot. + */ public function isOnline(): bool { - return $this->status === 'active' - && $this->last_seen_at !== null - && $this->last_seen_at->gt(now()->subMinutes(10)); + if ($this->status !== 'active') { + return false; + } + + return $this->last_seen_at === null + || $this->last_seen_at->gt(now()->subMinutes(10)); } } diff --git a/app/Services/HomeStatus.php b/app/Services/HomeStatus.php new file mode 100644 index 0000000..000825a --- /dev/null +++ b/app/Services/HomeStatus.php @@ -0,0 +1,84 @@ +with(['devices' => fn ($q) => $q->orderBy('name'), 'devices.entities.state']) + ->orderBy('sort')->orderBy('name') + ->get(); + } + + public function summary(Collection $rooms): array + { + $devices = $rooms->flatMap->devices; + $entities = $devices->flatMap->entities; + + return [ + 'devices_online' => $devices->filter->isOnline()->count(), + 'devices_total' => $devices->count(), + 'lights_on' => $entities->filter(fn ($e) => in_array($e->type, ['light', 'switch']) && data_get($e->state, 'state.on') === true)->count(), + 'contacts_open' => $entities->filter(fn ($e) => $e->type === 'contact' && data_get($e->state, 'state.open') === true)->count(), + 'low_battery' => $entities->filter(fn ($e) => $e->type === 'battery' && (int) data_get($e->state, 'state.percent', 100) < self::LOW_BATTERY)->count(), + ]; + } + + /** @return array */ + public function warnings(Collection $rooms): array + { + $devices = $rooms->flatMap->devices; + $entities = $devices->flatMap->entities; + $warnings = []; + + foreach ($devices->reject->isOnline() as $device) { + $warnings[] = [ + 'level' => 'offline', 'icon' => 'devices', + 'title' => $device->name, 'meta' => __('devices.offline'), 'link' => null, + ]; + } + + foreach ($entities as $entity) { + if ($entity->type === 'contact' && data_get($entity->state, 'state.open') === true) { + $warnings[] = [ + 'level' => 'warning', 'icon' => 'window', + 'title' => $entity->device->name, 'meta' => __('devices.open'), 'link' => null, + ]; + } + + if ($entity->type === 'battery') { + $percent = (int) data_get($entity->state, 'state.percent', 100); + if ($percent < self::LOW_BATTERY) { + $warnings[] = [ + 'level' => 'warning', 'icon' => 'alert', + 'title' => $entity->device->name, + 'meta' => __('devices.battery').': '.$percent.'%', 'link' => null, + ]; + } + } + } + + if (! $this->health->allOnline()) { + $warnings[] = [ + 'level' => 'warning', 'icon' => 'activity', + 'title' => __('dashboard.warn_host'), 'meta' => __('dashboard.warn_host_meta'), + 'link' => route('host'), + ]; + } + + return $warnings; + } +} diff --git a/database/seeders/DemoHomeSeeder.php b/database/seeders/DemoHomeSeeder.php index de70e61..6ae4805 100644 --- a/database/seeders/DemoHomeSeeder.php +++ b/database/seeders/DemoHomeSeeder.php @@ -20,7 +20,9 @@ class DemoHomeSeeder extends Seeder { public function run(): void { - $now = now(); + // Online mock devices have no last_seen (treated as reachable, so the demo never + // rots); the one offline device carries a stale timestamp. + $onlineSeen = null; $stale = now()->subHours(2); // room => devices. Each device: [name, model, online, entities[]] @@ -88,7 +90,7 @@ class DemoHomeSeeder extends Seeder 'model' => $model, 'protocol' => 'mqtt', 'status' => 'active', - 'last_seen_at' => $online ? $now : $stale, + 'last_seen_at' => $online ? $onlineSeen : $stale, ], ); diff --git a/lang/de/common.php b/lang/de/common.php index 1956dab..e6538da 100644 --- a/lang/de/common.php +++ b/lang/de/common.php @@ -14,4 +14,5 @@ return [ 'logout' => 'Abmelden', 'menu' => 'Menü', 'close' => 'Schließen', + 'cancel' => 'Abbrechen', ]; diff --git a/lang/de/devices.php b/lang/de/devices.php index e9cdcd5..91b8e5d 100644 --- a/lang/de/devices.php +++ b/lang/de/devices.php @@ -1,6 +1,7 @@ 'An', 'off' => 'Aus', 'open' => 'Offen', @@ -10,4 +11,43 @@ return [ 'no_motion' => 'Ruhe', 'online' => 'Online', 'offline' => 'Nicht erreichbar', + + // index + 'index_subtitle' => 'Alle Geräte im Haus.', + 'empty' => 'Noch keine Geräte.', + + // detail + 'device' => 'Gerät', + 'name' => 'Name', + 'save' => 'Speichern', + 'saved' => 'Gespeichert.', + 'vendor' => 'Hersteller', + 'model' => 'Modell', + 'protocol' => 'Protokoll', + 'room' => 'Raum', + 'no_room' => 'Kein Raum', + 'last_seen' => 'Zuletzt gesehen', + 'uuid' => 'UUID', + 'capabilities' => 'Fähigkeiten', + 'no_capabilities' => 'Keine Fähigkeiten gemeldet.', + + 'status_active' => 'Aktiv', + 'status_ignored' => 'Ignoriert', + 'status_discovered' => 'Neu erkannt', + + // settings + 'settings' => 'Einstellungen', + 'active' => 'Aktiv', + 'active_hint' => 'Deaktivierte Geräte werden ausgeblendet.', + + // actions (mock until Phase 3 / DeviceCommandService) + 'actions' => 'Aktionen', + 'actions_demo_hint' => 'Demo — Befehle laufen ab Phase 3 über den echten Treiber.', + 'restart' => 'Neustart', + 'check_update' => 'Update prüfen', + 'command_sent_demo' => 'Neustart-Befehl gesendet (Demo).', + 'no_update_demo' => 'Kein Update verfügbar (Demo).', + + 'restart_confirm_title' => 'Gerät neu starten?', + 'restart_confirm_body' => ':name wird neu gestartet und ist kurz nicht erreichbar.', ]; diff --git a/lang/en/common.php b/lang/en/common.php index 2e7a9e7..3b58d0a 100644 --- a/lang/en/common.php +++ b/lang/en/common.php @@ -14,4 +14,5 @@ return [ 'logout' => 'Sign out', 'menu' => 'Menu', 'close' => 'Close', + 'cancel' => 'Cancel', ]; diff --git a/lang/en/devices.php b/lang/en/devices.php index 0e1b562..88a9741 100644 --- a/lang/en/devices.php +++ b/lang/en/devices.php @@ -1,6 +1,7 @@ 'On', 'off' => 'Off', 'open' => 'Open', @@ -10,4 +11,43 @@ return [ 'no_motion' => 'Idle', 'online' => 'Online', 'offline' => 'Unreachable', + + // index + 'index_subtitle' => 'All devices in the home.', + 'empty' => 'No devices yet.', + + // detail + 'device' => 'Device', + 'name' => 'Name', + 'save' => 'Save', + 'saved' => 'Saved.', + 'vendor' => 'Vendor', + 'model' => 'Model', + 'protocol' => 'Protocol', + 'room' => 'Room', + 'no_room' => 'No room', + 'last_seen' => 'Last seen', + 'uuid' => 'UUID', + 'capabilities' => 'Capabilities', + 'no_capabilities' => 'No capabilities reported.', + + 'status_active' => 'Active', + 'status_ignored' => 'Ignored', + 'status_discovered' => 'Discovered', + + // settings + 'settings' => 'Settings', + 'active' => 'Active', + 'active_hint' => 'Disabled devices are hidden.', + + // actions (mock until Phase 3 / DeviceCommandService) + 'actions' => 'Actions', + 'actions_demo_hint' => 'Demo — commands route through the real driver from Phase 3.', + 'restart' => 'Restart', + 'check_update' => 'Check for update', + 'command_sent_demo' => 'Restart command sent (demo).', + 'no_update_demo' => 'No update available (demo).', + + 'restart_confirm_title' => 'Restart device?', + 'restart_confirm_body' => ':name will restart and be briefly unavailable.', ]; diff --git a/resources/css/app.css b/resources/css/app.css index d7fe370..27ee635 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -3,6 +3,8 @@ /* Scan Blade sources for utility classes */ @source '../views'; @source '../../app/Livewire'; +/* wire-elements/modal builds width classes in PHP — force-generate them */ +@source inline("sm:max-w-md md:max-w-lg md:max-w-xl lg:max-w-2xl lg:max-w-3xl"); @source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php'; @source '../../storage/framework/views/*.php'; diff --git a/resources/views/components/detail.blade.php b/resources/views/components/detail.blade.php new file mode 100644 index 0000000..e0fd9bf --- /dev/null +++ b/resources/views/components/detail.blade.php @@ -0,0 +1,6 @@ +@props(['label', 'mono' => false]) + +
+
{{ $label }}
+
merge(['class' => 'text-[13px] text-ink-2 '.($mono ? 'font-mono' : '')]) }}>{{ $slot }}
+
diff --git a/resources/views/components/sidebar.blade.php b/resources/views/components/sidebar.blade.php index 9395795..1a1e2f6 100644 --- a/resources/views/components/sidebar.blade.php +++ b/resources/views/components/sidebar.blade.php @@ -3,7 +3,7 @@ 'nav.section_overview' => [ ['key' => 'dashboard', 'icon' => 'dashboard', 'route' => 'dashboard', 'lock' => false], ['key' => 'rooms', 'icon' => 'rooms', 'route' => null, 'lock' => false], - ['key' => 'devices', 'icon' => 'devices', 'route' => null, 'lock' => false], + ['key' => 'devices', 'icon' => 'devices', 'route' => 'devices.index', 'active' => 'devices.*', 'lock' => false], ], 'nav.section_persons' => [ ['key' => 'persons', 'icon' => 'persons', 'route' => null, 'lock' => false], @@ -39,7 +39,7 @@
{{ __($label) }}
@foreach ($items as $item) - @php $active = $item['route'] && request()->routeIs($item['route']); @endphp + @php $active = $item['route'] && request()->routeIs($item['active'] ?? $item['route']); @endphp @if ($item['route'])
+ @isset($actions) + {{ $actions }} + @endisset +
+ @livewire('wire-elements-modal') + @livewireScripts diff --git a/resources/views/livewire/dashboard.blade.php b/resources/views/livewire/dashboard.blade.php index 516f1a5..eb73d70 100644 --- a/resources/views/livewire/dashboard.blade.php +++ b/resources/views/livewire/dashboard.blade.php @@ -1,53 +1,23 @@
- + + + + +
- {{-- warnings — only what needs attention --}} - @if (count($warnings) > 0) - - - {{ count($warnings) }} - - - - @else -
- -
- - - -
-

{{ __('dashboard.all_clear_title') }}

-

{{ __('dashboard.all_clear_body') }}

-
-
-
- @endif - {{-- home summary --}}
@@ -64,18 +34,20 @@ diff --git a/resources/views/livewire/devices/index.blade.php b/resources/views/livewire/devices/index.blade.php new file mode 100644 index 0000000..37c85d8 --- /dev/null +++ b/resources/views/livewire/devices/index.blade.php @@ -0,0 +1,36 @@ +
+ + +
+ + + {{ $devices->count() }} + + + @if ($devices->isEmpty()) +

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

+ @else + + @endif +
+
+
diff --git a/resources/views/livewire/devices/show.blade.php b/resources/views/livewire/devices/show.blade.php new file mode 100644 index 0000000..8d42820 --- /dev/null +++ b/resources/views/livewire/devices/show.blade.php @@ -0,0 +1,129 @@ +
+ + + + + + + + + +
+ @if ($flash) +
+ + {{ $flash }} + +
+ @endif + +
+ {{-- main --}} +
+ {{-- identity + name edit --}} + +
+
+ + + {{ $device->isOnline() ? __('devices.online') : __('devices.offline') }} + + @if ($device->status !== 'active') + {{ __('devices.status_'.$device->status) }} + @endif +
+ +
+ +
+ + +
+ @error('name')

{{ $message }}

@enderror +
+ +
+ {{ $device->vendor ?? '—' }} + {{ $device->model ?? '—' }} + {{ $device->protocol ?? '—' }} + {{ $device->room?->name ?? '—' }} + {{ $device->last_seen_at?->diffForHumans() ?? '—' }} + {{ \Illuminate\Support\Str::limit($device->uuid, 13, '…') }} +
+
+
+ + {{-- capabilities / entities --}} + + @if ($device->entities->isEmpty()) +

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

+ @else +
+ @foreach ($device->entities as $entity) +
+ {{ $entity->name ?? $entity->key }} + {{ $entity->type }} + +
+ @endforeach +
+ @endif +
+
+ + {{-- rail: actions + settings --}} +
+ +
+ + +
+

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

+
+ + +
+
+ +
+ + +
+
+ +
+
+
{{ __('devices.active') }}
+
{{ __('devices.active_hint') }}
+
+ +
+
+
+
+
+
+
diff --git a/resources/views/livewire/modals/confirm.blade.php b/resources/views/livewire/modals/confirm.blade.php new file mode 100644 index 0000000..8b94f97 --- /dev/null +++ b/resources/views/livewire/modals/confirm.blade.php @@ -0,0 +1,30 @@ +
+
+ $danger, + 'bg-accent/10 text-accent' => ! $danger, + ])> + + +
+

{{ $title }}

+

{{ $body }}

+
+
+ +
+ + +
+
diff --git a/resources/views/livewire/modals/warnings.blade.php b/resources/views/livewire/modals/warnings.blade.php new file mode 100644 index 0000000..966087d --- /dev/null +++ b/resources/views/livewire/modals/warnings.blade.php @@ -0,0 +1,57 @@ +
+
+ + + +

+ {{ __('dashboard.warnings_title') }} + @if (count($warnings) > 0) + {{ count($warnings) }} + @endif +

+ +
+ +
+ @if (count($warnings) > 0) +
+ @foreach ($warnings as $w) +
+ $w['level'] === 'offline', + 'text-warning bg-warning/10' => $w['level'] !== 'offline', + ])> + + +
+
{{ $w['title'] }}
+ @if ($w['meta']) +
{{ $w['meta'] }}
+ @endif +
+ @if ($w['link']) + + + + @endif +
+ @endforeach +
+ @else +
+ + + +
+
{{ __('dashboard.all_clear_title') }}
+
{{ __('dashboard.all_clear_body') }}
+
+
+ @endif +
+
diff --git a/resources/views/vendor/wire-elements-modal/modal.blade.php b/resources/views/vendor/wire-elements-modal/modal.blade.php new file mode 100644 index 0000000..9a0e172 --- /dev/null +++ b/resources/views/vendor/wire-elements-modal/modal.blade.php @@ -0,0 +1,57 @@ +
+ @isset($jsPath) + + @endisset + @isset($cssPath) + + @endisset + + +
diff --git a/routes/web.php b/routes/web.php index 8c15887..32d7d0e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -2,6 +2,8 @@ use App\Livewire\Auth\Login; use App\Livewire\Dashboard; +use App\Livewire\Devices\Index as DeviceIndex; +use App\Livewire\Devices\Show as DeviceShow; use App\Livewire\Host; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Route; @@ -14,6 +16,8 @@ Route::middleware('guest')->group(function () { Route::middleware('auth')->group(function () { Route::get('/dashboard', Dashboard::class)->name('dashboard'); + Route::get('/devices', DeviceIndex::class)->name('devices.index'); + Route::get('/devices/{device}', DeviceShow::class)->name('devices.show'); Route::get('/host', Host::class)->name('host'); Route::post('/logout', function () {