diff --git a/frontend/lib/devices/device_detail.dart b/frontend/lib/devices/device_detail.dart index 939486a..2e15ef0 100644 --- a/frontend/lib/devices/device_detail.dart +++ b/frontend/lib/devices/device_detail.dart @@ -2,22 +2,12 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import '../model/device.dart'; +import '../model/device_type.dart'; import '../utils/friendly_date_formatter.dart'; import '../utils/oott_api.dart'; import '../utils/ui_snackbars.dart'; import '../widgets/status_badge.dart'; -const _deviceTypes = [ - 'phone', - 'laptop', - 'tablet', - 'server', - 'router', - 'tv', - 'printer', - 'unknown', -]; - class DeviceDetail extends StatefulWidget { final String macAddress; @@ -99,9 +89,7 @@ class _DeviceDetailState extends State { Future _showRegisterDialog(Device device) async { final formKey = GlobalKey(); String owner = ''; - String deviceType = _deviceTypes.contains(device.deviceType) - ? device.deviceType - : 'unknown'; + DeviceType deviceType = device.deviceType; final saved = await showDialog( context: context, @@ -123,12 +111,15 @@ class _DeviceDetailState extends State { const SizedBox(height: 16), InputDecorator( decoration: const InputDecoration(labelText: 'Device Type'), - child: DropdownButton( + child: DropdownButton( value: deviceType, isExpanded: true, underline: const SizedBox(), - items: _deviceTypes - .map((t) => DropdownMenuItem(value: t, child: Text(t))) + items: DeviceType.values + .map( + (t) => + DropdownMenuItem(value: t, child: Text(t.label)), + ) .toList(), onChanged: (value) => setDialogState(() => deviceType = value ?? deviceType), @@ -162,7 +153,7 @@ class _DeviceDetailState extends State { await BackendAPI.instance.registerDevice( device.macAddress, owner, - deviceType, + deviceType.name, ); if (!mounted) return; UISnackbars.showSuccess(context, 'Device registered'); @@ -173,27 +164,6 @@ class _DeviceDetailState extends State { } } - IconData _deviceIcon(String deviceType) { - switch (deviceType.toLowerCase()) { - case 'phone': - return Icons.phone_android; - case 'laptop': - return Icons.laptop; - case 'tablet': - return Icons.tablet_android; - case 'server': - return Icons.dns; - case 'router': - return Icons.router; - case 'tv': - return Icons.tv; - case 'printer': - return Icons.print; - default: - return Icons.device_unknown; - } - } - @override Widget build(BuildContext context) { final device = _device; @@ -248,10 +218,7 @@ class _DeviceDetailState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _DeviceHeader( - device: device, - deviceIcon: _deviceIcon(device.deviceType), - ), + _DeviceHeader(device: device), const SizedBox(height: 24), _DeviceInfoCard(device: device), ], @@ -263,16 +230,15 @@ class _DeviceDetailState extends State { class _DeviceHeader extends StatelessWidget { final Device device; - final IconData deviceIcon; - const _DeviceHeader({required this.device, required this.deviceIcon}); + const _DeviceHeader({required this.device}); @override Widget build(BuildContext context) { final theme = Theme.of(context); return Row( children: [ - Icon(deviceIcon, size: 48), + Icon(device.deviceType.icon, size: 48), const SizedBox(width: 16), Expanded( child: Column( @@ -321,12 +287,7 @@ class _DeviceInfoCard extends StatelessWidget { value: formatter.format(device.lastSeen), ), const Divider(height: 1), - _InfoRow( - label: 'Device Type', - value: device.deviceType.isEmpty || device.deviceType == 'unknown' - ? 'Unknown' - : device.deviceType, - ), + _InfoRow(label: 'Device Type', value: device.deviceType.label), const Divider(height: 1), _InfoRow( label: 'Owner', diff --git a/frontend/lib/devices/device_list.dart b/frontend/lib/devices/device_list.dart index 800be39..790110e 100644 --- a/frontend/lib/devices/device_list.dart +++ b/frontend/lib/devices/device_list.dart @@ -2,22 +2,12 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import '../model/device.dart'; +import '../model/device_type.dart'; import '../utils/friendly_date_formatter.dart'; import '../utils/oott_api.dart'; import '../utils/ui_snackbars.dart'; import '../widgets/status_badge.dart'; -const _deviceTypes = [ - 'phone', - 'laptop', - 'tablet', - 'server', - 'router', - 'tv', - 'printer', - 'unknown', -]; - enum _DeviceFilter { newDevices, registered, all } class DeviceList extends StatefulWidget { @@ -111,9 +101,7 @@ class _DeviceListState extends State { Future _showRegisterDialog(Device device) async { final formKey = GlobalKey(); String owner = ''; - String deviceType = _deviceTypes.contains(device.deviceType) - ? device.deviceType - : 'unknown'; + DeviceType deviceType = device.deviceType; final saved = await showDialog( context: context, @@ -135,12 +123,15 @@ class _DeviceListState extends State { const SizedBox(height: 16), InputDecorator( decoration: const InputDecoration(labelText: 'Device Type'), - child: DropdownButton( + child: DropdownButton( value: deviceType, isExpanded: true, underline: const SizedBox(), - items: _deviceTypes - .map((t) => DropdownMenuItem(value: t, child: Text(t))) + items: DeviceType.values + .map( + (t) => + DropdownMenuItem(value: t, child: Text(t.label)), + ) .toList(), onChanged: (value) => setDialogState(() => deviceType = value ?? deviceType), @@ -174,7 +165,7 @@ class _DeviceListState extends State { await BackendAPI.instance.registerDevice( device.macAddress, owner, - deviceType, + deviceType.name, ); if (!mounted) return; UISnackbars.showSuccess(context, 'Device registered'); @@ -185,27 +176,6 @@ class _DeviceListState extends State { } } - IconData _deviceIcon(String deviceType) { - switch (deviceType.toLowerCase()) { - case 'phone': - return Icons.phone_android; - case 'laptop': - return Icons.laptop; - case 'tablet': - return Icons.tablet_android; - case 'server': - return Icons.dns; - case 'router': - return Icons.router; - case 'tv': - return Icons.tv; - case 'printer': - return Icons.print; - default: - return Icons.device_unknown; - } - } - String _emptyMessage() { switch (_filter) { case _DeviceFilter.newDevices: @@ -281,12 +251,10 @@ class _DeviceListState extends State { onTap: () => context.push('/devices/${device.macAddress}'), leading: Tooltip( - message: - device.deviceType.isEmpty || - device.deviceType == 'unknown' + message: device.deviceType == DeviceType.unknown ? 'Device type unknown' - : device.deviceType, - child: Icon(_deviceIcon(device.deviceType)), + : device.deviceType.label, + child: Icon(device.deviceType.icon), ), title: Row( children: [ diff --git a/frontend/lib/model/device.dart b/frontend/lib/model/device.dart index 4fa80fa..88df80c 100644 --- a/frontend/lib/model/device.dart +++ b/frontend/lib/model/device.dart @@ -1,3 +1,5 @@ +import 'device_type.dart'; + class Device { final String macAddress; final String ipv4Address; @@ -5,7 +7,7 @@ class Device { final DateTime lastSeen; final bool isRegistered; final String owner; - final String deviceType; + final DeviceType deviceType; Device({ required this.macAddress, @@ -24,5 +26,5 @@ class Device { lastSeen = DateTime.parse(json['last_seen'] as String), isRegistered = json['is_registered'] as bool, owner = json['owner'] as String, - deviceType = json['device_type'] as String; + deviceType = DeviceType.fromString(json['device_type'] as String); } diff --git a/frontend/lib/model/device_type.dart b/frontend/lib/model/device_type.dart new file mode 100644 index 0000000..0c224ca --- /dev/null +++ b/frontend/lib/model/device_type.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; + +enum DeviceType { + phone, + laptop, + tablet, + server, + router, + tv, + printer, + unknown; + + IconData get icon => switch (this) { + phone => Icons.phone_android, + laptop => Icons.laptop, + tablet => Icons.tablet_android, + server => Icons.dns, + router => Icons.router, + tv => Icons.tv, + printer => Icons.print, + unknown => Icons.device_unknown, + }; + + String get label => + this == unknown ? 'Unknown' : name[0].toUpperCase() + name.substring(1); + + static DeviceType fromString(String value) => switch (value.toLowerCase()) { + 'phone' => phone, + 'laptop' => laptop, + 'tablet' => tablet, + 'server' => server, + 'router' => router, + 'tv' => tv, + 'printer' => printer, + _ => unknown, + }; +}