update badge icon notif

This commit is contained in:
Muhammad Iqbal 2025-05-17 23:17:29 +07:00
parent 946799b30b
commit 8cb669b7b1
5 changed files with 60 additions and 26 deletions

View File

@ -49,6 +49,7 @@ class _ControlScreenState extends State<ControlScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: Colors.grey[100],
appBar: const CustomHeader( appBar: const CustomHeader(
deviceName: 'HamaGuard', deviceName: 'HamaGuard',
), ),

View File

@ -20,9 +20,14 @@ class DashboardScreen extends StatelessWidget {
return Scaffold( return Scaffold(
backgroundColor: Colors.grey[100], backgroundColor: Colors.grey[100],
appBar: const CustomHeader( appBar: CustomHeader(
deviceName: 'HamaGuard', // ini wajib diisi deviceName: 'HamaGuard',
notificationCount: 5,
onNotificationTap: () {
// Aksi saat lonceng ditekan
},
), ),
body: SingleChildScrollView( body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Column( child: Column(
@ -42,7 +47,7 @@ class DashboardScreen extends StatelessWidget {
Icon(Icons.thermostat_outlined, color: Colors.red), Icon(Icons.thermostat_outlined, color: Colors.red),
SizedBox(width: 8), SizedBox(width: 8),
Text( Text(
'Thermal AMG8833 (8x8)', 'Thermal Sensor',
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 16, fontSize: 16,

View File

@ -23,7 +23,6 @@ class SettingScreen extends StatelessWidget {
trailing: Switch( trailing: Switch(
value: true, // sementara default ON, nanti bisa dihubungkan state nyata value: true, // sementara default ON, nanti bisa dihubungkan state nyata
onChanged: (val) { onChanged: (val) {
// TODO: handle perubahan mode
}, },
), ),
), ),
@ -37,7 +36,7 @@ class SettingScreen extends StatelessWidget {
trailing: Switch( trailing: Switch(
value: true, value: true,
onChanged: (val) { onChanged: (val) {
// TODO: handle toggle notifikasi
}, },
), ),
), ),
@ -49,7 +48,6 @@ class SettingScreen extends StatelessWidget {
leading: const Icon(Icons.refresh), leading: const Icon(Icons.refresh),
title: const Text('Reset Data'), title: const Text('Reset Data'),
onTap: () { onTap: () {
// TODO: implement reset data
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Data direset')), const SnackBar(content: Text('Data direset')),
); );

View File

@ -4,11 +4,13 @@ import 'package:intl/intl.dart';
class CustomHeader extends StatefulWidget implements PreferredSizeWidget { class CustomHeader extends StatefulWidget implements PreferredSizeWidget {
final String deviceName; final String deviceName;
final VoidCallback? onNotificationTap; final VoidCallback? onNotificationTap;
final int notificationCount; // Tambahan
const CustomHeader({ const CustomHeader({
super.key, super.key,
required this.deviceName, required this.deviceName,
this.onNotificationTap, this.onNotificationTap,
this.notificationCount = 0,
}); });
@override @override
@ -26,17 +28,13 @@ class _CustomHeaderState extends State<CustomHeader> {
void initState() { void initState() {
super.initState(); super.initState();
_updateDate(); _updateDate();
// Update setiap hari (atau bisa sesuaikan interval jika perlu)
ticker = Stream.periodic(const Duration(minutes: 1)).listen((_) { ticker = Stream.periodic(const Duration(minutes: 1)).listen((_) {
if (mounted) { if (mounted) _updateDate();
_updateDate();
}
}); });
} }
void _updateDate() { void _updateDate() {
final now = DateTime.now(); final now = DateTime.now();
// Format hanya tanggal: Contoh "Fri, 16 May 2025"
final formatted = DateFormat('EEE, dd MMM yyyy').format(now); final formatted = DateFormat('EEE, dd MMM yyyy').format(now);
setState(() { setState(() {
_dateString = formatted; _dateString = formatted;
@ -59,7 +57,7 @@ class _CustomHeaderState extends State<CustomHeader> {
title: Row( title: Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
// Nama alat dan tanggal di kiri // Nama alat dan tanggal
Padding( Padding(
padding: const EdgeInsets.only(right: 8.0), padding: const EdgeInsets.only(right: 8.0),
child: Column( child: Column(
@ -71,7 +69,7 @@ class _CustomHeaderState extends State<CustomHeader> {
style: const TextStyle( style: const TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.black87, color: Color.fromARGB(255, 56, 142, 60),
), ),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
@ -86,25 +84,57 @@ class _CustomHeaderState extends State<CustomHeader> {
], ],
), ),
), ),
const Spacer(), const Spacer(),
// Lonceng dalam lingkaran abu-abu lembut // Icon lonceng + badge notifikasi
Padding( Padding(
padding: const EdgeInsets.only(left: 8.0), padding: const EdgeInsets.only(left: 8.0),
child: Material( child: Material(
color: Colors.grey.shade200, color: const Color.fromARGB(255, 198, 215, 197),
shape: const CircleBorder(), shape: const CircleBorder(),
child: IconButton( child: Stack(
padding: const EdgeInsets.all(8), clipBehavior: Clip.none,
icon: const Icon(Icons.notifications_none, color: Colors.black87, size: 28), children: [
onPressed: widget.onNotificationTap ?? IconButton(
() { padding: const EdgeInsets.all(8),
ScaffoldMessenger.of(context).showSnackBar( icon: const Icon(Icons.notifications_none,
const SnackBar(content: Text('Notifikasi belum tersedia')), color: Colors.black87, size: 28),
); onPressed: widget.onNotificationTap ??
}, () {
splashRadius: 24, 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,
),
),
),
),
],
), ),
), ),
), ),