MIF_E31222451/lib/profile.dart

567 lines
20 KiB
Dart

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:ternak/login.dart';
class Profile extends StatefulWidget {
final Map<String, dynamic> docUser;
const Profile({super.key, required this.docUser});
@override
State<Profile> createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
var canUse = 0;
var totalBlok = 0;
User? user = FirebaseAuth.instance.currentUser;
@override
Widget build(BuildContext context) {
return FutureBuilder<DocumentSnapshot>(
future:
FirebaseFirestore.instance.collection('users').doc(user?.uid).get(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator(
color: Color(0xFF1D91AA),
));
}
if (!snapshot.hasData || !snapshot.data!.exists) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.person_off, size: 64, color: Colors.grey[400]),
const SizedBox(height: 16),
const Text(
'Data tidak ditemukan',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
color: Colors.grey,
),
),
],
),
);
}
var userData = snapshot.data!.data() as Map<String, dynamic>;
return ListView(
children: [
Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xFF1D91AA), Color(0xFF25A5C4)],
),
),
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
child: Column(
children: [
const CircleAvatar(
radius: 50,
backgroundColor: Colors.white,
child: Icon(Icons.person, size: 60, color: Color(0xFF1D91AA)),
),
const SizedBox(height: 16),
Text(
userData['nama'],
style: const TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
Text(
user?.email ?? '',
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w300,
),
),
],
),
),
const SizedBox(height: 16),
Container(
margin: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 5),
),
],
),
child: Column(
children: [
ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
title: const Text(
'Nama Peternakan',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: Colors.grey,
),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 5),
Text(
userData['farmName'],
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
const SizedBox(height: 3),
Row(
children: [
const Icon(Icons.location_on, size: 16, color: Color(0xFF1D91AA)),
const SizedBox(width: 4),
Text(
userData['location'],
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
),
],
),
],
),
trailing: Container(
decoration: BoxDecoration(
color: const Color(0xFF1D91AA).withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: IconButton(
icon: const Icon(Icons.edit, color: Color(0xFF1D91AA)),
onPressed: () => showUpdateAccount(context, userData),
),
),
),
],
),
),
const SizedBox(height: 20),
Container(
margin: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 5),
),
],
),
child: Column(
children: [
_buildMenuTile(
icon: Icons.key,
title: 'Ubah Password',
subtitle: 'Perbarui password demi keamanan',
onTap: () => showUpdatePasswordDialog(context),
),
const Divider(height: 1),
_buildMenuTile(
icon: Icons.logout,
title: 'Logout',
subtitle: 'Keluar dari aplikasi',
isLogout: true,
onTap: () => _showLogoutConfirmation(context),
),
],
),
),
const SizedBox(height: 30),
],
);
},
);
}
Widget _buildMenuTile({
required IconData icon,
required String title,
required String subtitle,
bool isLogout = false,
required VoidCallback onTap,
}) {
return ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
leading: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: isLogout
? Colors.red.withOpacity(0.1)
: const Color(0xFF1D91AA).withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(
icon,
color: isLogout ? Colors.red : const Color(0xFF1D91AA),
size: 24,
),
),
title: Text(
title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: isLogout ? Colors.red : Colors.black87,
),
),
subtitle: Text(
subtitle,
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
),
trailing: Icon(
Icons.arrow_forward_ios,
size: 16,
color: isLogout ? Colors.red : Colors.grey,
),
onTap: onTap,
);
}
void _showLogoutConfirmation(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
title: const Text("Konfirmasi Logout"),
content: const Text("Apakah kamu yakin ingin keluar?"),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text(
"Batal",
style: TextStyle(color: Colors.grey),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
onPressed: () {
FirebaseAuth.instance.signOut().then((value) {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => const Login()),
(Route<dynamic> route) =>
false,
);
});
},
child: const Text("Logout"),
),
],
);
},
);
}
void showUpdatePasswordDialog(BuildContext context) {
final TextEditingController passwordController = TextEditingController();
final TextEditingController confirmPasswordController =
TextEditingController();
final FirebaseAuth auth = FirebaseAuth.instance;
bool _obscureText = true;
bool _obscureConfirmText = true;
showDialog(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
title: const Text("Update Password"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: passwordController,
obscureText: _obscureText,
decoration: InputDecoration(
labelText: "Password Baru",
floatingLabelStyle: const TextStyle(
color: Color(0xFF1D91AA),
),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFF1D91AA)),
),
suffixIcon: IconButton(
icon: Icon(
_obscureText
? Icons.visibility
: Icons.visibility_off,
color: const Color(0xFF1D91AA),
),
onPressed: () {
setState(() {
_obscureText = !_obscureText;
});
},
),
),
),
const SizedBox(height: 16),
TextField(
controller: confirmPasswordController,
obscureText: _obscureConfirmText,
decoration: InputDecoration(
labelText: "Konfirmasi Password",
floatingLabelStyle: const TextStyle(
color: Color(0xFF1D91AA),
),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFF1D91AA)),
),
suffixIcon: IconButton(
icon: Icon(
_obscureConfirmText
? Icons.visibility
: Icons.visibility_off,
color: const Color(0xFF1D91AA),
),
onPressed: () {
setState(() {
_obscureConfirmText = !_obscureConfirmText;
});
},
),
),
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text(
"Batal",
style: TextStyle(color: Colors.grey),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF1D91AA),
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
onPressed: () async {
String newPassword = passwordController.text.trim();
String confirmPassword =
confirmPasswordController.text.trim();
if (newPassword.isEmpty || confirmPassword.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text("Password tidak boleh kosong!")));
return;
}
if (newPassword != confirmPassword) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text("Password tidak cocok!")));
return;
}
try {
User? user = auth.currentUser;
if (user != null) {
await user.updatePassword(newPassword);
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text("Password berhasil diperbarui!")));
Navigator.pop(context);
} else {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text("User tidak ditemukan!")));
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Error: $e")));
}
},
child: const Text("Update"),
),
],
);
},
);
},
);
}
void showUpdateAccount(BuildContext context, Map<String, dynamic> userData) {
final TextEditingController farmNameController =
TextEditingController(text: userData['farmName']);
final TextEditingController locationController =
TextEditingController(text: userData['location']);
final TextEditingController namaController =
TextEditingController(text: userData['nama']);
final users = FirebaseFirestore.instance.collection('users');
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
title: const Text("Update Akun"),
content: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: namaController,
decoration: const InputDecoration(
labelText: "Nama",
labelStyle: TextStyle(color: Colors.grey),
floatingLabelStyle: TextStyle(
color: Color(0xFF1D91AA),
),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFF1D91AA)),
),
),
),
const SizedBox(height: 16),
TextField(
controller: farmNameController,
decoration: const InputDecoration(
labelText: "Nama Peternakan",
labelStyle: TextStyle(color: Colors.grey),
floatingLabelStyle: TextStyle(
color: Color(0xFF1D91AA),
),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFF1D91AA)),
),
),
),
const SizedBox(height: 16),
TextField(
controller: locationController,
decoration: const InputDecoration(
labelText: "Lokasi",
labelStyle: TextStyle(color: Colors.grey),
floatingLabelStyle: TextStyle(
color: Color(0xFF1D91AA),
),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFF1D91AA)),
),
),
),
],
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text(
"Batal",
style: TextStyle(color: Colors.grey),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF1D91AA),
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
onPressed: () async {
String farmName = farmNameController.text.trim();
String nama = namaController.text.trim();
String location = locationController.text.trim();
if (farmName.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text("Nama Peternakan tidak boleh kosong!")));
return;
}
if (nama.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text("Nama tidak boleh kosong!")));
return;
}
if (location.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text("Lokasi tidak boleh kosong!")));
return;
}
try {
await users.doc(user?.uid).update({
"farmName": farmName,
"location": location,
"nama": nama,
});
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text("Akun berhasil diperbarui!")));
Navigator.pop(context);
setState(() {});
} catch (e) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Error: $e")));
}
},
child: const Text("Update"),
),
],
);
},
);
}
}