TKK_E32231279/lib/widgets/tambah_user.dart

552 lines
14 KiB
Dart

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<TambahUserDialog> createState() =>
_TambahUserDialogState();
}
class _TambahUserDialogState
extends State<TambahUserDialog> {
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<void> 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,
),
),
),
],
),
],
),
),
),
);
}
}