import 'dart:async'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../core/theme.dart'; import '../providers/notification_provider.dart'; import '../providers/home_provider.dart'; import '../providers/pengajuan_provider.dart'; import '../providers/attendance_provider.dart'; import '../providers/poin_provider.dart'; import '../services/fcm_service.dart'; import '../services/websocket_service.dart'; import 'home/home_screen.dart'; import 'profile/profile_screen.dart'; import 'presensi/presensi_screen.dart'; import 'pengajuan/pengajuan_screen.dart'; class MainScreen extends StatefulWidget { const MainScreen({Key? key}) : super(key: key); @override State createState() => _MainScreenState(); } class _MainScreenState extends State with WidgetsBindingObserver { int _currentIndex = 0; final List _screens = const [ HomeScreen(), PresensiScreen(), PengajuanScreen(), ProfileScreen(), ]; StreamSubscription? _wsSubscription; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); WidgetsBinding.instance.addPostFrameCallback((_) { context.read().fetchUnreadCount(); FcmService().initialize(context); _initWebSocket(); }); } void _initWebSocket() { final ws = WebSocketService(); ws.connect(); _wsSubscription = ws.eventStream.listen((event) { final eventName = event['event'] as String? ?? ''; if (eventName.contains('Notifikasi')) { context.read().fetchUnreadCount(); } if (eventName.contains('Pengajuan') || eventName.contains('Lembur') || eventName.contains('Poin') || eventName.contains('Cuti') || eventName.contains('Surat')) { context.read().fetchPengajuan(); context.read().fetchDashboardData(force: true); } if (eventName.contains('Presensi')) { context.read().fetchHistory(force: true); context.read().fetchDashboardData(force: true); } if (eventName.contains('Jadwal') || eventName.contains('TukarShift')) { context.read().fetchDashboardData(force: true); } if (eventName.contains('Pengumuman')) { context.read().fetchDashboardData(force: true); } if (eventName.contains('FaceEnrollment')) { context.read().fetchDashboardData(force: true); } }); } @override void dispose() { _wsSubscription?.cancel(); WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { context.read().fetchUnreadCount(); } } @override Widget build(BuildContext context) { return Scaffold( extendBody: true, body: IndexedStack( index: _currentIndex, children: _screens, ), bottomNavigationBar: Container( margin: EdgeInsets.fromLTRB(AppTheme.spacingMd, 0, AppTheme.spacingMd, MediaQuery.of(context).padding.bottom + AppTheme.spacingSm), decoration: BoxDecoration( color: AppTheme.bgCard.withOpacity(0.85), borderRadius: BorderRadius.circular(AppTheme.radiusXl), boxShadow: AppTheme.shadowLg, ), child: ClipRRect( borderRadius: BorderRadius.circular(AppTheme.radiusXl), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), child: MediaQuery.removePadding( context: context, removeBottom: true, child: BottomNavigationBar( currentIndex: _currentIndex, onTap: (index) { setState(() { _currentIndex = index; }); }, backgroundColor: Colors.transparent, selectedItemColor: AppTheme.primaryOrange, unselectedItemColor: AppTheme.textTertiary, showUnselectedLabels: false, showSelectedLabels: true, selectedLabelStyle: const TextStyle(fontSize: 12, fontWeight: FontWeight.w700), type: BottomNavigationBarType.fixed, elevation: 0, items: [ BottomNavigationBarItem( icon: const Padding(padding: EdgeInsets.only(bottom: 4), child: Icon(Icons.grid_view_rounded, size: 24)), activeIcon: const Padding(padding: EdgeInsets.only(bottom: 4), child: Icon(Icons.grid_view_rounded, size: 26)), label: 'Beranda', ), BottomNavigationBarItem( icon: const Padding(padding: EdgeInsets.only(bottom: 4), child: Icon(Icons.fingerprint, size: 24)), activeIcon: const Padding(padding: EdgeInsets.only(bottom: 4), child: Icon(Icons.fingerprint, size: 26)), label: 'Presensi', ), BottomNavigationBarItem( icon: const Padding(padding: EdgeInsets.only(bottom: 4), child: Icon(Icons.insert_page_break_outlined, size: 24)), activeIcon: const Padding(padding: EdgeInsets.only(bottom: 4), child: Icon(Icons.insert_page_break_rounded, size: 26)), label: 'Pengajuan', ), BottomNavigationBarItem( icon: const Padding(padding: EdgeInsets.only(bottom: 4), child: Icon(Icons.person_outline, size: 24)), activeIcon: const Padding(padding: EdgeInsets.only(bottom: 4), child: Icon(Icons.person_rounded, size: 26)), label: 'Profil', ), ], ), ), ), ), ), ); } }