Siopas Inventory PETI for ISTW Mobile
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

437 lines
14 KiB

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/user_model.dart';
import '../providers/auth_provider.dart';
import '../widget/loading_button.dart';
class SignInPage extends StatefulWidget {
@override
State<SignInPage> createState() => _SignInPageState();
}
class _SignInPageState extends State<SignInPage> {
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<AuthProvider>(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<FormState> _formKey = GlobalKey<FormState>();
bool isLoading = false;
bool _isPasswordVisible = false;
@override
Widget build(BuildContext context) {
AuthProvider authProvider = Provider.of<AuthProvider>(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<SettingsModal> createState() => _SettingsModalState();
}
class _SettingsModalState extends State<SettingsModal> {
TextEditingController inputController = TextEditingController();
@override
void initState() {
super.initState();
// Load saved IP Address or Port when the modal is initialized
loadSettings();
}
void loadSettings() async {
String savedValue = await getSavedValue();
setState(() {
inputController.text = savedValue;
});
}
@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),
),
],
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
controller: inputController,
inputFormatters: [
FilteringTextInputFormatter.allow(
RegExp(r'[a-zA-Z0-9@#$%^&*()_+={}|\[\]\\:;"<>,.?/~`-]'))
],
decoration: InputDecoration(labelText: 'Domain atau IP:Port'),
),
],
),
actions: [
ElevatedButton(
onPressed: () {
// Save value to SharedPreferences
saveSettings(inputController.text);
Navigator.of(context).pop(); // Close the modal
},
child: Text('Simpan'),
),
],
);
}
Future<void> saveSettings(String value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('savedValue', value);
// Print the saved data
print('Value saved: $value');
}
Future<void> clearSettings() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.remove('savedValue');
print('Value cleared');
}
}
Future<String> getSavedValue() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String savedValue = prefs.getString('savedValue') ?? '';
return savedValue;
}