import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:ui/views/auth/controllers/auth_controller.dart'; import 'dart:math' as math; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPageState(); } class _LoginPageState extends State with TickerProviderStateMixin { late String role; late String idFieldLabel; final AuthController authController = Get.find(); late AnimationController _controller; late Animation _animation; final Map roleImages = { "siswa": "https://cdn-icons-png.flaticon.com/512/201/201818.png", "guru": "https://cdn-icons-png.flaticon.com/512/1995/1995574.png", "admin": "https://cdn-icons-png.flaticon.com/512/2206/2206368.png", }; @override void initState() { super.initState(); role = (Get.arguments is String) ? Get.arguments as String : "siswa"; idFieldLabel = getIdFieldLabel(role); _initializeAnimation(); } void _initializeAnimation() { if (!mounted) return; _controller = AnimationController( duration: const Duration(seconds: 10), vsync: this, ); _animation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation( parent: _controller, curve: Curves.linear, ), ); if (mounted) { _controller.repeat(); } } @override void dispose() { _controller.dispose(); super.dispose(); } String getIdFieldLabel(String role) { switch (role.toLowerCase()) { case "siswa": return "NIS atau Email Siswa"; case "guru": return "Email atau Nip Guru"; default: return "ID"; } } Widget _buildAnimatedShapes() { return AnimatedBuilder( animation: _animation, builder: (context, child) { if (!mounted) return const SizedBox.shrink(); return Stack( children: [ // Shape 1 Positioned( left: math.sin(_animation.value * 2 * math.pi) * 50 + Get.width * 0.1, top: math.cos(_animation.value * 2 * math.pi) * 50 + Get.height * 0.1, child: Transform.rotate( angle: _animation.value * 2 * math.pi, child: Container( width: 100, height: 100, decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color.fromRGBO(157, 157, 136, 0.1), Color.fromRGBO(33, 198, 41, 0.1), ], ), borderRadius: BorderRadius.circular(20), ), ), ), ), // Shape 2 Positioned( right: math.cos(_animation.value * 2 * math.pi) * 50 + Get.width * 0.1, top: math.sin(_animation.value * 2 * math.pi) * 50 + Get.height * 0.2, child: Transform.rotate( angle: -_animation.value * 2 * math.pi, child: Container( width: 120, height: 120, decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color.fromRGBO(157, 157, 136, 0.1), Color.fromRGBO(33, 198, 41, 0.1), ], ), borderRadius: BorderRadius.circular(25), ), ), ), ), ], ); }, ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFE6F7F4), body: Stack( children: [ // Animated Background Shapes _buildAnimatedShapes(), // Main Content Center( child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 20, spreadRadius: 5, ), ], ), child: Column( children: [ Image.network( roleImages[role.toLowerCase()]!, width: 100, height: 100, ), const SizedBox(height: 16.0), Text( role.capitalizeFirst ?? role, style: const TextStyle( fontSize: 24.0, fontWeight: FontWeight.bold, color: Color(0xFF2E7D32), ), ), const SizedBox(height: 32.0), TextField( controller: authController.loginC, decoration: _inputDecoration(idFieldLabel), ), const SizedBox(height: 24.0), TextField( controller: authController.passwordC, obscureText: true, decoration: _inputDecoration("Kata Sandi"), ), const SizedBox(height: 32.0), Obx(() => authController.isLoading.value ? const CircularProgressIndicator( valueColor: AlwaysStoppedAnimation( Color(0xFF2E7D32)), ) : ElevatedButton( onPressed: () { authController.login(); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF2E7D32), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric( horizontal: 50, vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), ), ), child: const Text( "Masuk", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), )), ], ), ), ], ), ), ), ), ], ), ); } InputDecoration _inputDecoration(String label) { return InputDecoration( labelText: label, filled: true, fillColor: Colors.white, border: OutlineInputBorder( borderRadius: BorderRadius.circular(30.0), borderSide: const BorderSide(color: Color(0xFF2E7D32)), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30.0), borderSide: BorderSide(color: Colors.grey.shade300), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30.0), borderSide: const BorderSide(color: Color(0xFF2E7D32), width: 2), ), labelStyle: TextStyle(color: Colors.grey.shade600), ); } }