MIF_E31231027/smart_cycling/lib/screens/register_screen.dart

178 lines
6.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import '../widgets/custom_button.dart';
import '../widgets/custom_text_field.dart';
import '../utils/api_config.dart';
import '../widgets/responsive_layout.dart';
class RegisterScreen extends StatefulWidget {
const RegisterScreen({super.key});
@override
State<RegisterScreen> createState() => _RegisterScreenState();
}
class _RegisterScreenState extends State<RegisterScreen> {
final nameController = TextEditingController();
final usernameController = TextEditingController();
final passwordController = TextEditingController();
final confirmPasswordController = TextEditingController();
bool isLoading = false;
Future<void> registerUser() async {
// 1. Validasi Konfirmasi Password secara lokal di Flutter
if (passwordController.text != confirmPasswordController.text) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Konfirmasi password tidak cocok!')),
);
return;
}
setState(() => isLoading = true);
// Mengambil baseUrl dari pengaturan sentral di utils/api_config.dart
final url = Uri.parse("${ApiConfig.baseUrl}/register.php");
try {
final response = await http.post(url, body: {
'nama': nameController.text,
'username': usernameController.text,
'password': passwordController.text,
});
final data = jsonDecode(response.body);
if (!mounted) return;
if (data['status'] == 'success') {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Registrasi Berhasil! Silakan Login.')),
);
Navigator.pop(context); // Kembali ke halaman Login
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(data['message'])),
);
}
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Gagal terhubung ke server!')),
);
} finally {
if (mounted) setState(() => isLoading = false);
}
}
@override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
return ResponsiveLayout(
child: Scaffold(
backgroundColor: const Color(0xFF3949AB),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: 260,
width: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF3949AB), Color(0xFF00BCD4)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: SafeArea(
bottom: false,
child: Center(
child: Image.asset(
'assets/images/cyclist.png',
height: 140,
fit: BoxFit.contain,
),
),
),
),
Transform.translate(
offset: const Offset(0, -40),
child: Container(
constraints: BoxConstraints(
minHeight: screenHeight - 220,
),
width: double.infinity,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40),
topRight: Radius.circular(40),
),
),
padding: const EdgeInsets.symmetric(horizontal: 32.0, vertical: 40.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'Welcome!',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 26,
fontWeight: FontWeight.w800,
color: Color(0xFF3949AB),
),
),
const SizedBox(height: 32),
CustomTextField(
hintText: 'Nama',
controller: nameController,
prefixIcon: Icons.badge_outlined,
),
const SizedBox(height: 16),
CustomTextField(
hintText: 'Username',
controller: usernameController,
prefixIcon: Icons.person_outline,
),
const SizedBox(height: 16),
CustomTextField(
hintText: 'Password',
obscureText: true,
controller: passwordController,
prefixIcon: Icons.lock_outline,
),
const SizedBox(height: 16),
CustomTextField(
hintText: 'Konfirmasi Password',
obscureText: true,
controller: confirmPasswordController,
prefixIcon: Icons.lock_reset_outlined,
),
const SizedBox(height: 24),
isLoading
? const Center(child: CircularProgressIndicator())
: CustomButton(
text: 'Sign Up',
onPressed: () {
if (nameController.text.isNotEmpty && usernameController.text.isNotEmpty && passwordController.text.isNotEmpty) {
registerUser();
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Data tidak boleh kosong!')),
);
}
},
),
const SizedBox(height: 24),
],
),
),
),
],
),
),
),
);
}
}