import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'signin_page.dart'; class ProfilePage extends StatefulWidget { const ProfilePage({super.key}); @override State createState() => _ProfilePageState(); } class _ProfilePageState extends State { String name = ""; String email = ""; bool isLoading = true; @override void initState() { super.initState(); getUserData(); } /// GET USER DATA Future getUserData() async { try { String uid = FirebaseAuth.instance.currentUser!.uid; DocumentSnapshot userDoc = await FirebaseFirestore.instance .collection("users") .doc(uid) .get(); setState(() { name = userDoc["username"]; email = userDoc["email"]; isLoading = false; }); } catch (e) { debugPrint( "Get User Error: $e", ); } } /// RESET PASSWORD Future showResetPasswordDialog() async { showDialog( context: context, barrierDismissible: false, builder: (context) { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), ), title: const Text( "Reset Password", style: TextStyle( fontWeight: FontWeight.bold, ), ), content: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon( Icons.lock_reset, size: 65, color: Color(0xFF6F4E37), ), const SizedBox(height: 20), const Text( "Link reset password akan dikirim ke email:", textAlign: TextAlign.center, ), const SizedBox(height: 12), Text( email, textAlign: TextAlign.center, style: const TextStyle( fontWeight: FontWeight.bold, color: Color(0xFF6F4E37), fontSize: 15, ), ), const SizedBox(height: 15), const Text( "Password lama masih aktif sampai Anda mengganti password baru melalui email.", textAlign: TextAlign.center, style: TextStyle( fontSize: 12, color: Colors.grey, ), ), ], ), actions: [ TextButton( onPressed: () { Navigator.pop(context); }, child: const Text( "Batal", ), ), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF6F4E37), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), onPressed: () async { try { /// SEND RESET PASSWORD await FirebaseAuth.instance .sendPasswordResetEmail( email: email, ); debugPrint( "Reset password email berhasil dikirim ke $email", ); /// LOGOUT await FirebaseAuth.instance .signOut(); if (mounted) { Navigator.pop(context); /// SHOW SUCCESS INFO showDialog( context: context, barrierDismissible: false, builder: (context) { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), ), title: const Text( "Cek Email", ), content: Text( "Link reset password berhasil dikirim ke:\n\n$email\n\nSilakan ubah password terlebih dahulu melalui email.", ), actions: [ ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF6F4E37), ), onPressed: () { Navigator.pushAndRemoveUntil( context, MaterialPageRoute( builder: (context) => const SigninPage(), ), (route) => false, ); }, child: const Text( "OK", style: TextStyle( color: Colors.white, ), ), ) ], ); }, ); } } on FirebaseAuthException catch (e) { debugPrint( "Reset Password Error: $e", ); String message = "Gagal mengirim reset password"; if (e.code == 'user-not-found') { message = "Email tidak ditemukan"; } if (e.code == 'invalid-email') { message = "Format email tidak valid"; } ScaffoldMessenger.of(context) .showSnackBar( SnackBar( backgroundColor: Colors.red, content: Text(message), ), ); } }, child: const Text( "Kirim Reset", style: TextStyle( color: Colors.white, ), ), ), ], ); }, ); } /// ABOUT APP void showAboutApp() { showAboutDialog( context: context, applicationName: "Coffee Dryer", applicationVersion: "Version 1.0.0", applicationIcon: const Icon( Icons.coffee, size: 50, color: Color(0xFF6F4E37), ), children: [ const SizedBox(height: 10), const Text( "Coffee Dryer adalah aplikasi monitoring dan kontrol alat pengering kopi berbasis IoT.", textAlign: TextAlign.justify, ), const SizedBox(height: 15), const Text( "Fitur Utama:", style: TextStyle( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), const Text( "• Monitoring suhu realtime\n" "• Monitoring kelembapan\n" "• Kontrol heater dan fan\n" "• Sistem otomatis pengering kopi\n" "• Integrasi Firebase Realtime Database", ), const SizedBox(height: 15), const Text( "Developed by Ahid Ilmi Arslan", style: TextStyle( fontStyle: FontStyle.italic, ), ), ], ); } /// LOGOUT Future logout() async { try { await FirebaseAuth.instance.signOut(); if (mounted) { Navigator.pushAndRemoveUntil( context, MaterialPageRoute( builder: (context) => const SigninPage(), ), (route) => false, ); } } catch (e) { debugPrint( "Logout Error: $e", ); ScaffoldMessenger.of(context) .showSnackBar( const SnackBar( content: Text( "Logout gagal", ), ), ); } } @override Widget build(BuildContext context) { if (isLoading) { return const Scaffold( backgroundColor: Color(0xFFF6F1EE), body: Center( child: CircularProgressIndicator( color: Color(0xFF6F4E37), ), ), ); } return Scaffold( backgroundColor: const Color(0xFFF6F1EE), body: SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( children: [ /// HEADER (gaya sama dengan HomePage: padding 20, /// gradient coklat, radius 30, shadow coklat) Container( width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: const LinearGradient( colors: [Color(0xFF6F4E37), Color(0xFF8D6E63)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(30), boxShadow: [ BoxShadow( color: Colors.brown.withOpacity(0.2), blurRadius: 15, offset: const Offset(0, 8), ), ], ), child: Column( children: [ Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: Colors.white.withOpacity(0.5), width: 3, ), ), child: Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), shape: BoxShape.circle, ), child: const Icon( Icons.person, size: 55, color: Colors.white, ), ), ), const SizedBox(height: 15), Text( name, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 5), Text( email, style: const TextStyle( color: Colors.white70, fontSize: 14, ), ), ], ), ), const SizedBox(height: 25), /// SECTION HEADER (gaya sama dengan "Kontrol Mesin" / /// "Informasi Alat" di HomePage) Align( alignment: Alignment.centerLeft, child: Text( "Pengaturan Akun", style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.brown.shade800, ), ), ), const SizedBox(height: 15), buildMenu( icon: Icons.info_outline, title: "Tentang Aplikasi", subtitle: "Informasi Coffee Dryer", color: Colors.orange, onTap: () { showAboutApp(); }, ), buildMenu( icon: Icons.help_outline, title: "Bantuan", subtitle: "Reset password akun", color: Colors.green, onTap: () { showResetPasswordDialog(); }, ), const SizedBox(height: 15), /// LOGOUT (gaya sama dengan controlButton di HomePage: /// ikon di atas, teks bold putih, radius 20, shadow warna) GestureDetector( onTap: logout, child: Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 18), decoration: BoxDecoration( color: Colors.red, borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: Colors.red.withOpacity(0.3), blurRadius: 10, offset: const Offset(0, 5), ), ], ), child: const Column( children: [ Icon(Icons.logout, color: Colors.white, size: 26), SizedBox(height: 8), Text( "Logout", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16, ), ), ], ), ), ), const SizedBox(height: 20), ], ), ), ), ); } /// MENU CARD - gaya sama dengan sensorCard/buildControlCard di /// HomePage: radius 25, shadow black 0.05 blur 15 offset(0,8) Widget buildMenu({ required IconData icon, required String title, required String subtitle, required Color color, required VoidCallback onTap, }) { return Container( margin: const EdgeInsets.only(bottom: 15), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(25), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 15, offset: const Offset(0, 8), ), ], ), child: Material( color: Colors.transparent, borderRadius: BorderRadius.circular(25), child: InkWell( borderRadius: BorderRadius.circular(25), onTap: onTap, child: Padding( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 10, ), child: Row( children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(15), ), child: Icon(icon, color: color), ), const SizedBox(width: 15), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), const SizedBox(height: 3), Text( subtitle, style: TextStyle( color: Colors.grey.shade600, fontSize: 13, ), ), ], ), ), Icon( Icons.arrow_forward_ios_rounded, size: 16, color: Colors.grey.shade400, ), ], ), ), ), ), ); } }