// ignore_for_file: prefer_const_constructors, sort_child_properties_last import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import '../../app/injection_container.dart'; import '../../core/services/stt_service.dart'; import '../../core/services/tts_service.dart'; import '../../core/services/voice_command_handler.dart'; class UserShell extends StatefulWidget { final Widget child; const UserShell({super.key, required this.child}); @override State createState() => _UserShellState(); } class _UserShellState extends State { @override void initState() { super.initState(); sl().startListening(); sl().onCommand = (key) { if (!mounted) return; switch (key) { case VoiceCommandKey.openWalkguide: case VoiceCommandKey.startWalkguide: context.go('/user/walkguide'); break; case VoiceCommandKey.openSos: case VoiceCommandKey.sendSos: context.go('/user/sos'); break; case VoiceCommandKey.openActivity: context.go('/user/activity'); break; case VoiceCommandKey.openNotification: case VoiceCommandKey.readAllNotif: context.go('/user/notifications'); break; case VoiceCommandKey.openNavigation: case VoiceCommandKey.whereAmI: context.go('/user/navigation'); break; case VoiceCommandKey.openSettings: context.go('/user/settings'); break; case VoiceCommandKey.callGuardian: context.go('/user/call'); break; case VoiceCommandKey.repeatLast: case VoiceCommandKey.stopTts: case VoiceCommandKey.stopWalkguide: break; } sl().speak(_spokenRouteName(key)); }; } @override Widget build(BuildContext context) { final location = GoRouterState.of(context).matchedLocation; final items = [ _ShellItem('Guide', Icons.visibility_outlined, Icons.visibility, '/user/walkguide'), _ShellItem('SOS', Icons.warning_amber_outlined, Icons.warning_amber, '/user/sos'), _ShellItem( 'Log', Icons.list_alt_outlined, Icons.list_alt, '/user/activity'), _ShellItem('Notif', Icons.notifications_outlined, Icons.notifications, '/user/notifications'), _ShellItem('Map', Icons.map_outlined, Icons.map, '/user/navigation'), _ShellItem( 'Set', Icons.settings_outlined, Icons.settings, '/user/settings'), ]; return _AppShell(child: widget.child, items: items, location: location); } } class GuardianShell extends StatelessWidget { final Widget child; const GuardianShell({super.key, required this.child}); @override Widget build(BuildContext context) { final location = GoRouterState.of(context).matchedLocation; final items = [ _ShellItem('Home', Icons.dashboard_outlined, Icons.dashboard, '/guardian/dashboard'), _ShellItem('Map', Icons.map_outlined, Icons.map, '/guardian/map'), _ShellItem('Logs', Icons.fact_check_outlined, Icons.fact_check, '/guardian/logs'), _ShellItem( 'Send', Icons.send_outlined, Icons.send, '/guardian/send-notif'), _ShellItem('AI', Icons.tune_outlined, Icons.tune, '/guardian/ai-config'), _ShellItem( 'Set', Icons.settings_outlined, Icons.settings, '/guardian/settings'), ]; return _AppShell(child: child, items: items, location: location); } } class _AppShell extends StatelessWidget { final Widget child; final List<_ShellItem> items; final String location; const _AppShell( {required this.child, required this.items, required this.location}); @override Widget build(BuildContext context) { return Scaffold( body: child, bottomNavigationBar: NavigationBar( selectedIndex: _selectedIndex, onDestinationSelected: (index) => context.go(items[index].route), destinations: [ for (final item in items) NavigationDestination( icon: Icon(item.icon), selectedIcon: Icon(item.selectedIcon), label: item.label, ), ], ), ); } int get _selectedIndex { final index = items.indexWhere((item) => location.startsWith(item.route)); return index < 0 ? 0 : index; } } class _ShellItem { final String label; final IconData icon; final IconData selectedIcon; final String route; const _ShellItem(this.label, this.icon, this.selectedIcon, this.route); } String _spokenRouteName(VoiceCommandKey key) { switch (key) { case VoiceCommandKey.openWalkguide: case VoiceCommandKey.startWalkguide: return 'WalkGuide dibuka'; case VoiceCommandKey.openSos: case VoiceCommandKey.sendSos: return 'SOS dibuka'; case VoiceCommandKey.openActivity: return 'Activity log dibuka'; case VoiceCommandKey.openNotification: case VoiceCommandKey.readAllNotif: return 'Notifikasi dibuka'; case VoiceCommandKey.openNavigation: case VoiceCommandKey.whereAmI: return 'Navigasi dibuka'; case VoiceCommandKey.openSettings: return 'Settings dibuka'; case VoiceCommandKey.callGuardian: return 'Memanggil guardian'; case VoiceCommandKey.repeatLast: case VoiceCommandKey.stopTts: case VoiceCommandKey.stopWalkguide: return ''; } }