import 'dart:async'; import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_database/firebase_database.dart'; class TambahUserDialog extends StatefulWidget { const TambahUserDialog({super.key}); @override State createState() => _TambahUserDialogState(); } class _TambahUserDialogState extends State { final FirebaseFirestore firestore = FirebaseFirestore.instance; final FirebaseAuth auth = FirebaseAuth.instance; final DatabaseReference rfidRef = FirebaseDatabase.instance.ref( 'rfid_uid', ); final DatabaseReference usersRef = FirebaseDatabase.instance.ref( 'users', ); StreamSubscription? listener; final namaController = TextEditingController(); final emailController = TextEditingController(); final passwordController = TextEditingController(); final confirmPasswordController = TextEditingController(); final rfidController = TextEditingController(); String role = "user"; bool loading = false; bool hidePassword = true; bool hideConfirmPassword = true; @override void initState() { super.initState(); listener = rfidRef.onValue.listen( (event) { final data = event.snapshot.value; if (data != null && data.toString().isNotEmpty) { rfidController.text = data.toString(); } }, ); } @override void dispose() { listener?.cancel(); namaController.dispose(); emailController.dispose(); passwordController.dispose(); confirmPasswordController.dispose(); rfidController.dispose(); super.dispose(); } Widget buildTextField({ required String label, required IconData icon, required TextEditingController controller, bool readOnly = false, TextInputType keyboardType = TextInputType.text, }) { return Padding( padding: const EdgeInsets.only(bottom: 15), child: TextField( controller: controller, readOnly: readOnly, keyboardType: keyboardType, decoration: InputDecoration( labelText: label, prefixIcon: Icon(icon), filled: true, fillColor: Colors.grey.shade100, border: OutlineInputBorder( borderRadius: BorderRadius.circular( 15), borderSide: BorderSide.none, ), ), ), ); } Widget buildPasswordField({ required String label, required TextEditingController controller, required bool obscureText, required VoidCallback onToggle, }) { return Padding( padding: const EdgeInsets.only(bottom: 15), child: TextField( controller: controller, obscureText: obscureText, decoration: InputDecoration( labelText: label, prefixIcon: const Icon(Icons.lock), suffixIcon: IconButton( icon: Icon( obscureText ? Icons.visibility_off : Icons.visibility, ), onPressed: onToggle, ), filled: true, fillColor: Colors.grey.shade100, border: OutlineInputBorder( borderRadius: BorderRadius.circular( 15), borderSide: BorderSide.none, ), ), ), ); } Future saveUser() async { try { setState(() { loading = true; }); if (namaController.text.isEmpty || emailController.text.isEmpty || passwordController.text.isEmpty) { throw Exception( "Lengkapi semua data"); } if (confirmPasswordController .text.isEmpty) { throw Exception( "Konfirmasi password wajib diisi"); } if (passwordController .text.length < 6) { throw Exception( "Password minimal 6 karakter"); } if (passwordController.text != confirmPasswordController .text) { throw Exception( "Password dan konfirmasi password tidak sama"); } if (role == 'user' && rfidController.text.isEmpty) { throw Exception( "Silakan scan RFID terlebih dahulu"); } if (role == 'user') { final existing = await firestore .collection( 'users') .where( 'rfid_uid', isEqualTo: rfidController.text, ) .get(); if (existing.docs.isNotEmpty) { throw Exception( "RFID sudah digunakan"); } } final credential = await auth .createUserWithEmailAndPassword( email: emailController.text .trim(), password: passwordController.text .trim(), ); await firestore .collection('users') .doc( credential.user!.uid, ) .set({ "nama": namaController.text.trim(), "email": emailController.text.trim(), "role": role, "rfid_uid": role == "user" ? rfidController.text : "", }); if (role == "user") { await usersRef .child( rfidController.text, ) .set({ "nama": namaController.text .trim(), "saldo": 0, "botol_plastik": 0, "botol_kaleng": 0, "botol_kaca": 0, "history": {}, }); } await rfidRef.set(""); if (mounted) { Navigator.pop(context); ScaffoldMessenger.of(context) .showSnackBar( const SnackBar( content: Text( "User berhasil ditambahkan", ), ), ); } } catch (e) { // ignore: use_build_context_synchronously ScaffoldMessenger.of(context) .showSnackBar( SnackBar( content: Text( e.toString().replaceAll( "Exception: ", "", ), ), ), ); } if (mounted) { setState(() { loading = false; }); } } @override Widget build( BuildContext context) { return Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( 25), ), child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, children: [ CircleAvatar( radius: 40, backgroundColor: const Color( 0xFFA5CC36), child: const Icon( Icons.person_add, size: 40, color: Colors.black, ), ), const SizedBox( height: 15), const Text( "Tambah Pengguna", style: TextStyle( fontSize: 22, fontWeight: FontWeight.bold, ), ), const SizedBox( height: 20), buildTextField( label: "Nama", icon: Icons.person, controller: namaController, ), buildTextField( label: "Email", icon: Icons.email, controller: emailController, keyboardType: TextInputType .emailAddress, ), buildPasswordField( label: "Password", controller: passwordController, obscureText: hidePassword, onToggle: () { setState(() { hidePassword = !hidePassword; }); }, ), buildPasswordField( label: "Konfirmasi Password", controller: confirmPasswordController, obscureText: hideConfirmPassword, onToggle: () { setState(() { hideConfirmPassword = !hideConfirmPassword; }); }, ), DropdownButtonFormField( value: role, decoration: InputDecoration( filled: true, fillColor: Colors.grey .shade100, border: OutlineInputBorder( borderRadius: BorderRadius .circular( 15), borderSide: BorderSide .none, ), ), items: const [ DropdownMenuItem( value: "user", child: Text("User"), ), DropdownMenuItem( value: "admin", child: Text("Admin"), ), ], onChanged: (value) { setState(() { role = value!; }); }, ), const SizedBox( height: 15), if (role == "user") Container( padding: const EdgeInsets .all(15), decoration: BoxDecoration( color: Colors .green .shade50, borderRadius: BorderRadius .circular( 15), ), child: Column( children: [ const Row( children: [ Icon( Icons .nfc), SizedBox( width: 10), Text( "Scan RFID", style: TextStyle( fontWeight: FontWeight.bold, ), ), ], ), const SizedBox( height: 10), buildTextField( label: "RFID UID", icon: Icons .credit_card, controller: rfidController, readOnly: true, ), ], ), ), const SizedBox( height: 20), Row( children: [ Expanded( child: OutlinedButton( onPressed: () { Navigator.pop( context); }, child: const Text( "Batal"), ), ), const SizedBox( width: 10), Expanded( child: ElevatedButton.icon( onPressed: loading ? null : saveUser, icon: loading ? const SizedBox( height: 18, width: 18, child: CircularProgressIndicator( strokeWidth: 2, ), ) : const Icon( Icons .save), label: Text( loading ? "Menyimpan..." : "Simpan", ), style: ElevatedButton .styleFrom( backgroundColor: const Color( 0xFFA5CC36), foregroundColor: Colors.black, ), ), ), ], ), ], ), ), ), ); } }