import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter/services.dart'; import 'package:siopas/theme.dart'; import '../../models/ip_domain_model.dart'; import '../../models/user_model.dart'; import '../../providers/auth_provider.dart'; import '../../widget/loading_button.dart'; import 'controller/loginController.dart'; class SignInPage extends StatefulWidget { @override State createState() => _SignInPageState(); } class _SignInPageState extends State { TextEditingController emailController = TextEditingController(text: ''); TextEditingController passwordController = TextEditingController(text: ''); bool isLoading = false; bool _isPasswordVisible = false; // Create controllers for IP Address and Port TextEditingController ipAddressController = TextEditingController(); TextEditingController portController = TextEditingController(); @override Widget build(BuildContext context) { final bool isSmallScreen = MediaQuery.of(context).size.width < 600; AuthProvider authProvider = Provider.of(context); UserModel user = authProvider.user; // Function to show the SettingsModal void _showSettingsModal(BuildContext context) { showDialog( context: context, builder: (BuildContext context) { return SettingsModal(); }, ); } return Scaffold( body: Center( child: isSmallScreen ? SingleChildScrollView( reverse: true, scrollDirection: Axis.vertical, // Tambahkan ini child: Column( mainAxisSize: MainAxisSize.min, children: const [ _Logo(), _FormContent(), ], ), ) : Container( padding: const EdgeInsets.all(30.0), constraints: const BoxConstraints(maxWidth: 800), child: Row( children: [ Expanded(child: _Logo()), Expanded( child: Center(child: _FormContent()), ), ], ), ), ), bottomNavigationBar: BottomAppBar( color: Colors.grey[50], elevation: 0, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ TextButton( onPressed: () { _showSettingsModal(context); // Show the modal }, child: Text('Pengaturan'), ), ], ), ), ); } } class _Logo extends StatelessWidget { const _Logo({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final bool isSmallScreen = MediaQuery.of(context).size.width < 600; return Column( mainAxisSize: MainAxisSize.min, children: [ Container( // margin: EdgeInsets.only(top: 30), child: Image.asset( 'assets/img/siopas_apps.png', height: isSmallScreen ? 135 : 200, ), ), Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ Text( "Siopas ISTW", textAlign: TextAlign.center, style: TextStyle( fontSize: isSmallScreen ? 18 : 22, fontWeight: semiBold, color: Colors.black, ), ), SizedBox( height: 8.0), // Berikan sedikit jarak antara teks "Siopas ISTW" dan versi Text( "Version 1.0.0", // Gantilah dengan versi aktual textAlign: TextAlign.center, style: TextStyle( fontSize: isSmallScreen ? 14 : 16, color: Colors.grey, ), ), ], ), ), ], ); } } class _FormContent extends StatefulWidget { const _FormContent({Key? key}) : super(key: key); @override State<_FormContent> createState() => __FormContentState(); } class __FormContentState extends State<_FormContent> { TextEditingController emailController = TextEditingController(text: ''); TextEditingController passwordController = TextEditingController(text: ''); final GlobalKey _formKey = GlobalKey(); bool isLoading = false; bool _isPasswordVisible = false; @override Widget build(BuildContext context) { AuthProvider authProvider = Provider.of(context); UserModel user = authProvider.user; handleSignIn() async { setState(() { isLoading = true; }); if (await authProvider.login( email: emailController.text, password: passwordController.text, )) { UserModel user = authProvider.user; // Simpan token pengguna ke SharedPreferences SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.setString('token', user.token!); // Pastikan user.token tidak null print('token dapat login: ${user.token}'); if (user != null) { String roleName = user.role!.name!.toLowerCase(); if (roleName == 'operator' || roleName == 'Operator') { print('Berhasil login HALAMAN USER'); if (context != null) { Navigator.pushReplacementNamed(context, '/home'); } else { print('Context is null'); } } else { print('Tidak ada informasi peran (roles) yang tersedia'); } } else { print('User tidak valid'); } } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( backgroundColor: alertColor, content: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.warning, color: Colors.white, ), SizedBox(width: 8), // Jarak antara ikon dan teks Text( 'Gagal Login, Email dan Password anda salah', textAlign: TextAlign.center, ), ], ), ), ); Future.delayed(Duration(seconds: 3), () { ScaffoldMessenger.of(context).hideCurrentSnackBar(); }); } setState(() { isLoading = false; }); } return Container( constraints: const BoxConstraints(maxWidth: 300), child: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, // mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ _gap(), TextFormField( validator: (value) { // add email validation if (value == null || value.isEmpty) { return 'Silakan masukkan email anda'; } bool emailValid = RegExp( r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+") .hasMatch(value); if (!emailValid) { return 'Tolong masukkan email yang benar'; } return null; }, controller: emailController, decoration: const InputDecoration( hintText: 'Masukkan email Anda', prefixIcon: Icon(Icons.email_outlined), border: OutlineInputBorder(), ), keyboardType: TextInputType.emailAddress, ), _gap(), TextFormField( validator: (value) { if (value == null || value.isEmpty) { return 'Silakan masukkan password anda'; } if (value.length < 6) { return 'Kata sandi minimal harus 6 karakter'; } return null; }, obscureText: !_isPasswordVisible, controller: passwordController, decoration: InputDecoration( hintText: 'Masukkan kata sandi Anda', prefixIcon: const Icon(Icons.lock_outline_rounded), border: const OutlineInputBorder(), suffixIcon: IconButton( icon: Icon(_isPasswordVisible ? Icons.visibility_off : Icons.visibility), onPressed: () { setState(() { _isPasswordVisible = !_isPasswordVisible; }); }, )), ), _gap(), SizedBox( width: double.infinity, child: ElevatedButton( style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4), ), primary: Colors.indigo, // Ganti warna tombol menjadi indigo alignment: Alignment.center, // Menyusun isi tombol ke tengah ), child: Padding( padding: const EdgeInsets.all(10.0), child: Row( mainAxisAlignment: MainAxisAlignment.center, // Tengahkan teks 'Login' children: [ Icon(Icons.login), SizedBox( width: 8.0), // Berikan sedikit jarak antara ikon dan teks Text( 'Masuk', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold), ), ], ), ), onPressed: () { if (_formKey.currentState!.validate()) { if (emailController.text.isEmpty || passwordController.text.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( backgroundColor: alertColor, content: Row( children: [ Icon( Icons.warning, color: Colors.white, ), SizedBox(width: 8), // Jarak antara ikon dan teks Text( 'Email dan Password tidak boleh kosong', textAlign: TextAlign.center, ), ], ), ), ); Future.delayed(Duration(seconds: 2), () { ScaffoldMessenger.of(context).hideCurrentSnackBar(); }); } else { handleSignIn(); } } }, ), ), ], ), ), ); } Widget _gap() => const SizedBox(height: 14); } class SettingsModal extends StatefulWidget { const SettingsModal({Key? key}) : super(key: key); @override State createState() => _SettingsModalState(); } class _SettingsModalState extends State { TextEditingController ipDomainController = TextEditingController(); List? getIpDomainList; bool loading = true; @override void initState() { super.initState(); ipDomainList(); } Future ipDomainList() async { await ControllerLogin().fetchData().then((value) { setState(() { getIpDomainList = value; loading = false; // Set nilai ipDomainController dengan ID terbaru jika ada data if (getIpDomainList != null && getIpDomainList!.isNotEmpty) { ipDomainController.text = getIpDomainList![0]['ipOrDomain'].toString(); } }); }); } @override Widget build(BuildContext context) { return AlertDialog( title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Pengaturan'), GestureDetector( onTap: () { Navigator.of(context).pop(); // Close the modal }, child: Icon(Icons.close), ), ], ), actions: [ ElevatedButton( onPressed: () async { IpDomain ipDomainModel = IpDomain( id: null, ipOrDomain: ipDomainController.text, ); // Panggil fungsi deleteAllData untuk menghapus data sebelumnya await ControllerLogin().deleteAllData(); // Panggil fungsi addData untuk menyimpan data baru int result = await ControllerLogin().addData(ipDomainModel); if (result > 0) { print("Success"); // Gunakan setState untuk memicu pembaruan widget setelah data disimpan setState(() { loading = true; // Sinyal bahwa sedang memuat }); // Panggil fungsi ipDomainList untuk mengambil ulang data await ipDomainList(); // Setelah data diambil ulang, nonaktifkan loading setState(() { loading = false; }); // Setelah data disimpan dan diambil ulang, lakukan Navigator.pop Navigator.pop(context); // Kembali ke halaman sebelumnya } else { print("Failed"); } }, child: Text("Save"), ), ], content: Column( mainAxisSize: MainAxisSize.min, children: [ TextFormField( controller: ipDomainController, inputFormatters: [ FilteringTextInputFormatter.allow( RegExp(r'[a-zA-Z0-9@#$%^&*()_+={}|\[\]\\:;"<>,.?/~`-]'), ), ], decoration: InputDecoration(labelText: 'Domain atau IP:Port'), ), ], ), ); } }