diff --git a/lib/screens/control/control_screen.dart b/lib/screens/control/control_screen.dart index 546c2fc..d206b81 100644 --- a/lib/screens/control/control_screen.dart +++ b/lib/screens/control/control_screen.dart @@ -49,6 +49,7 @@ class _ControlScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: Colors.grey[100], appBar: const CustomHeader( deviceName: 'HamaGuard', ), diff --git a/lib/screens/dashboard/dashboard_screen.dart b/lib/screens/dashboard/dashboard_screen.dart index be0fca1..ec4c5d1 100644 --- a/lib/screens/dashboard/dashboard_screen.dart +++ b/lib/screens/dashboard/dashboard_screen.dart @@ -20,9 +20,14 @@ class DashboardScreen extends StatelessWidget { return Scaffold( backgroundColor: Colors.grey[100], - appBar: const CustomHeader( - deviceName: 'HamaGuard', // ini wajib diisi + appBar: CustomHeader( + deviceName: 'HamaGuard', + notificationCount: 5, + onNotificationTap: () { + // Aksi saat lonceng ditekan + }, ), + body: SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Column( @@ -42,7 +47,7 @@ class DashboardScreen extends StatelessWidget { Icon(Icons.thermostat_outlined, color: Colors.red), SizedBox(width: 8), Text( - 'Thermal AMG8833 (8x8)', + 'Thermal Sensor', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, diff --git a/lib/screens/notification/notification_screen.dart b/lib/screens/notification/notification_screen.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/screens/setting/setting_screen.dart b/lib/screens/setting/setting_screen.dart index b237da5..dfc8ea1 100644 --- a/lib/screens/setting/setting_screen.dart +++ b/lib/screens/setting/setting_screen.dart @@ -23,7 +23,6 @@ class SettingScreen extends StatelessWidget { trailing: Switch( value: true, // sementara default ON, nanti bisa dihubungkan state nyata onChanged: (val) { - // TODO: handle perubahan mode }, ), ), @@ -37,7 +36,7 @@ class SettingScreen extends StatelessWidget { trailing: Switch( value: true, onChanged: (val) { - // TODO: handle toggle notifikasi + }, ), ), @@ -49,7 +48,6 @@ class SettingScreen extends StatelessWidget { leading: const Icon(Icons.refresh), title: const Text('Reset Data'), onTap: () { - // TODO: implement reset data ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Data direset')), ); diff --git a/lib/widgets/costum_header.dart b/lib/widgets/costum_header.dart index ab80ba2..73f8260 100644 --- a/lib/widgets/costum_header.dart +++ b/lib/widgets/costum_header.dart @@ -4,11 +4,13 @@ import 'package:intl/intl.dart'; class CustomHeader extends StatefulWidget implements PreferredSizeWidget { final String deviceName; final VoidCallback? onNotificationTap; + final int notificationCount; // Tambahan const CustomHeader({ super.key, required this.deviceName, this.onNotificationTap, + this.notificationCount = 0, }); @override @@ -26,17 +28,13 @@ class _CustomHeaderState extends State { void initState() { super.initState(); _updateDate(); - // Update setiap hari (atau bisa sesuaikan interval jika perlu) ticker = Stream.periodic(const Duration(minutes: 1)).listen((_) { - if (mounted) { - _updateDate(); - } + if (mounted) _updateDate(); }); } void _updateDate() { final now = DateTime.now(); - // Format hanya tanggal: Contoh "Fri, 16 May 2025" final formatted = DateFormat('EEE, dd MMM yyyy').format(now); setState(() { _dateString = formatted; @@ -59,7 +57,7 @@ class _CustomHeaderState extends State { title: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - // Nama alat dan tanggal di kiri + // Nama alat dan tanggal Padding( padding: const EdgeInsets.only(right: 8.0), child: Column( @@ -71,7 +69,7 @@ class _CustomHeaderState extends State { style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w600, - color: Colors.black87, + color: Color.fromARGB(255, 56, 142, 60), ), ), const SizedBox(height: 4), @@ -86,25 +84,57 @@ class _CustomHeaderState extends State { ], ), ), - const Spacer(), - // Lonceng dalam lingkaran abu-abu lembut + // Icon lonceng + badge notifikasi Padding( padding: const EdgeInsets.only(left: 8.0), child: Material( - color: Colors.grey.shade200, + color: const Color.fromARGB(255, 198, 215, 197), shape: const CircleBorder(), - child: IconButton( - padding: const EdgeInsets.all(8), - icon: const Icon(Icons.notifications_none, color: Colors.black87, size: 28), - onPressed: widget.onNotificationTap ?? - () { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Notifikasi belum tersedia')), - ); - }, - splashRadius: 24, + child: Stack( + clipBehavior: Clip.none, + children: [ + IconButton( + padding: const EdgeInsets.all(8), + icon: const Icon(Icons.notifications_none, + color: Colors.black87, size: 28), + onPressed: widget.onNotificationTap ?? + () { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Notifikasi belum tersedia')), + ); + }, + splashRadius: 24, + ), + + // Badge jika notificationCount > 0 + if (widget.notificationCount > 0) + Positioned( + right: 4, + top: 4, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: Colors.red, + borderRadius: BorderRadius.circular(12), + ), + constraints: const BoxConstraints(minWidth: 16), + child: Text( + widget.notificationCount > 99 + ? '99+' + : '${widget.notificationCount}', + style: const TextStyle( + color: Colors.white, + fontSize: 10, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], ), ), ),