import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../controllers/auth_controller.dart'; import '../../../theme/app_colors.dart'; class LoginView extends GetView { const LoginView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ // Background gradient Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ AppColors.primaryLight.withOpacity(0.1), AppColors.background, AppColors.accentLight.withOpacity(0.1), ], ), ), ), // Pattern overlay Opacity( opacity: 0.03, child: Container( decoration: BoxDecoration( color: Colors.blue[50], // Temporary solid color ), ), ), // Accent circles Positioned( top: -40, right: -20, child: Container( width: 150, height: 150, decoration: BoxDecoration( shape: BoxShape.circle, gradient: RadialGradient( colors: [ AppColors.primary.withOpacity(0.2), Colors.transparent, ], ), ), ), ), Positioned( bottom: -50, left: -30, child: Container( width: 180, height: 180, decoration: BoxDecoration( shape: BoxShape.circle, gradient: RadialGradient( colors: [ AppColors.accent.withOpacity(0.2), Colors.transparent, ], ), ), ), ), // Main content SafeArea( child: SingleChildScrollView( physics: const BouncingScrollPhysics(), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: 50), _buildHeader(), const SizedBox(height: 40), _buildLoginCard(), _buildRegisterLink(), const SizedBox(height: 30), ], ), ), ), ), ], ), ); } Widget _buildHeader() { return Center( child: Hero( tag: 'logo', child: Image.asset( 'assets/images/logo.png', width: 220, height: 220, errorBuilder: (context, error, stackTrace) { return Icon( Icons.apartment_rounded, size: 180, color: AppColors.primary, ); }, ), ), ); } Widget _buildLoginCard() { return Card( elevation: 4, shadowColor: AppColors.shadow, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), child: Padding( padding: const EdgeInsets.all(28.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Welcome text Text( 'Selamat Datang', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: AppColors.textPrimary, ), ), const SizedBox(height: 8), Text( 'Masuk untuk melanjutkan ke akun Anda', style: TextStyle( fontSize: 14, color: AppColors.textSecondary, fontWeight: FontWeight.w400, ), ), const SizedBox(height: 32), // Email field _buildInputLabel('Email'), const SizedBox(height: 8), _buildTextField( controller: controller.emailController, hintText: 'Masukkan email Anda', prefixIcon: Icons.email_outlined, keyboardType: TextInputType.emailAddress, ), const SizedBox(height: 12), // Password field _buildInputLabel('Password'), const SizedBox(height: 8), Obx( () => _buildTextField( controller: controller.passwordController, hintText: 'Masukkan password Anda', prefixIcon: Icons.lock_outline, obscureText: !controller.isPasswordVisible.value, suffixIcon: IconButton( icon: Icon( controller.isPasswordVisible.value ? Icons.visibility : Icons.visibility_off, color: AppColors.iconGrey, ), onPressed: controller.togglePasswordVisibility, ), ), ), // Forgot password Align( alignment: Alignment.centerRight, child: TextButton( onPressed: () => controller.goToForgotPassword(), style: TextButton.styleFrom( padding: const EdgeInsets.symmetric( horizontal: 0, vertical: 8, ), ), child: Text( 'Lupa sandi?', style: TextStyle( color: AppColors.primary, fontWeight: FontWeight.w500, ), ), ), ), // Login button Obx( () => SizedBox( width: double.infinity, height: 56, child: ElevatedButton( onPressed: controller.isLoading.value ? null : controller.login, style: ElevatedButton.styleFrom( backgroundColor: AppColors.primary, foregroundColor: AppColors.buttonText, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), elevation: controller.isLoading.value ? 0 : 2, shadowColor: AppColors.primary.withOpacity(0.4), ), child: controller.isLoading.value ? const SizedBox( height: 24, width: 24, child: CircularProgressIndicator( color: Colors.white, strokeWidth: 2, ), ) : Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'Masuk', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, letterSpacing: 0.5, ), ), const SizedBox(width: 8), const Icon(Icons.arrow_forward, size: 18), ], ), ), ), ), // Error message Obx( () => controller.errorMessage.value.isNotEmpty ? Container( margin: const EdgeInsets.only(top: 16), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppColors.errorLight, borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Icon( Icons.error_outline, color: AppColors.error, size: 20, ), const SizedBox(width: 8), Expanded( child: Text( controller.errorMessage.value, style: TextStyle( color: AppColors.error, fontSize: 13, ), ), ), ], ), ) : const SizedBox.shrink(), ), ], ), ), ); } Widget _buildInputLabel(String label) { return Text( label, style: TextStyle( fontWeight: FontWeight.w600, color: AppColors.textPrimary, fontSize: 15, ), ); } Widget _buildTextField({ required TextEditingController controller, required String hintText, required IconData prefixIcon, TextInputType keyboardType = TextInputType.text, bool obscureText = false, Widget? suffixIcon, }) { return TextField( controller: controller, keyboardType: keyboardType, obscureText: obscureText, style: TextStyle(fontSize: 16, color: AppColors.textPrimary), decoration: InputDecoration( hintText: hintText, hintStyle: TextStyle(color: AppColors.textLight), prefixIcon: Icon(prefixIcon, color: AppColors.iconGrey, size: 22), suffixIcon: suffixIcon, filled: true, fillColor: AppColors.inputBackground, contentPadding: const EdgeInsets.symmetric(vertical: 16), border: OutlineInputBorder( borderRadius: BorderRadius.circular(14), borderSide: BorderSide.none, ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(14), borderSide: BorderSide.none, ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(14), borderSide: BorderSide(color: AppColors.primary, width: 1.5), ), ), ); } Widget _buildRegisterLink() { return Center( child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( "Belum punya akun?", style: TextStyle(color: AppColors.textSecondary), ), TextButton( onPressed: controller.goToSignUp, style: TextButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), ), child: Text( 'Daftar', style: TextStyle( fontWeight: FontWeight.bold, color: AppColors.primary, ), ), ), ], ), ); } }