diff --git a/lib/screens/control/control_screen.dart b/lib/screens/control/control_screen.dart index 16e8c75..b7c811a 100644 --- a/lib/screens/control/control_screen.dart +++ b/lib/screens/control/control_screen.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import '../../widgets/costum_header.dart'; class ControlScreen extends StatefulWidget { const ControlScreen({super.key}); @@ -26,10 +27,8 @@ class _ControlScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Kontrol Sistem'), - backgroundColor: Colors.green[700], - centerTitle: true, + appBar: const CustomHeader( + deviceName: 'HamaGuard', // ini wajib diisi ), body: Padding( padding: const EdgeInsets.all(20), diff --git a/lib/screens/dashboard/dashboard_screen.dart b/lib/screens/dashboard/dashboard_screen.dart index c741d3a..be0fca1 100644 --- a/lib/screens/dashboard/dashboard_screen.dart +++ b/lib/screens/dashboard/dashboard_screen.dart @@ -1,6 +1,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; import '../../widgets/thermal_grid.dart'; +import '../../widgets/costum_header.dart'; class DashboardScreen extends StatelessWidget { const DashboardScreen({super.key}); @@ -19,6 +20,9 @@ class DashboardScreen extends StatelessWidget { return Scaffold( backgroundColor: Colors.grey[100], + appBar: const CustomHeader( + deviceName: 'HamaGuard', // ini wajib diisi + ), body: SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Column( @@ -26,7 +30,8 @@ class DashboardScreen extends StatelessWidget { // Thermal Sensor dalam Card Card( elevation: 4, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( @@ -84,24 +89,6 @@ class DashboardScreen extends StatelessWidget { icon: Icons.speaker, color: Colors.green, ), - - const SizedBox(height: 20), - - // Tombol pengusir manual - ElevatedButton.icon( - onPressed: () { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Fitur pengusir manual belum tersedia')), - ); - }, - icon: const Icon(Icons.play_arrow), - label: const Text('Aktifkan Pengusir Manual'), - style: ElevatedButton.styleFrom( - backgroundColor: Colors.green[700], - minimumSize: const Size.fromHeight(48), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), - ), - ), ], ), ), diff --git a/lib/widgets/costum_header.dart b/lib/widgets/costum_header.dart new file mode 100644 index 0000000..ab80ba2 --- /dev/null +++ b/lib/widgets/costum_header.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +class CustomHeader extends StatefulWidget implements PreferredSizeWidget { + final String deviceName; + final VoidCallback? onNotificationTap; + + const CustomHeader({ + super.key, + required this.deviceName, + this.onNotificationTap, + }); + + @override + Size get preferredSize => const Size.fromHeight(kToolbarHeight + 24); + + @override + State createState() => _CustomHeaderState(); +} + +class _CustomHeaderState extends State { + late String _dateString; + late final ticker; + + @override + 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(); + } + }); + } + + 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; + }); + } + + @override + void dispose() { + ticker.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + automaticallyImplyLeading: false, + titleSpacing: 16, + title: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // Nama alat dan tanggal di kiri + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + widget.deviceName, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: Colors.black87, + ), + ), + const SizedBox(height: 4), + Text( + _dateString, + style: TextStyle( + fontSize: 12, + color: Colors.grey[600], + height: 1.2, + ), + ), + ], + ), + ), + + const Spacer(), + + // Lonceng dalam lingkaran abu-abu lembut + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Material( + color: Colors.grey.shade200, + 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, + ), + ), + ), + ], + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 6c542ec..4712809 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -75,6 +75,14 @@ packages: description: flutter source: sdk version: "0.0.0" + intl: + dependency: "direct main" + description: + name: intl + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + url: "https://pub.dev" + source: hosted + version: "0.18.1" leak_tracker: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index f5d3879..249cb63 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,6 +31,9 @@ dependencies: flutter: sdk: flutter + intl: ^0.18.0 + + # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8