import 'dart:async'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:tuuli_api/tuuli_api.dart'; import 'package:tuuli_app/api_controller.dart'; class LoginPageController extends GetxController { final _endpoint = ApiController.to.endPoint.obs; String get endpoint => _endpoint.value; set endpoint(String value) => _endpoint.value = value; final _username = "".obs; String get username => _username.value; set username(String value) => _username.value = value; final _password = "".obs; String get password => _password.value; set password(String value) => _password.value = value; final _submitted = false.obs; bool get submitted => _submitted.value; set submitted(bool value) => _submitted.value = value; bool get isFormValid => endpoint.isNotEmpty && username.isNotEmpty && password.isNotEmpty; Future submitForm() async { submitted = true; if (isFormValid) { try { ApiController.to.endPoint = endpoint; final resp = await ApiController.to.apiClient.getAccessToken( authModel: AuthModel( username: username, password: password, ), ); final respData = resp.data; if (resp.statusCode == 200 && respData != null) { final accessToken = respData.accessToken; Get.find().token = accessToken; WidgetsBinding.instance.addPostFrameCallback((_) { Get.offAllNamed("/home"); }); } else { Get.snackbar( "Login failed", resp.statusMessage ?? "Unknown error", ); } } on DioError catch (e) { final errorData = e.response?.data; if (errorData != null) { final error = errorData["error"]; if (error != null) { Get.snackbar( "Login failed", "$error", ); } } else { Get.snackbar( "Login failed", "$e", ); } } catch (e) { Get.snackbar( "Login failed", "$e", ); } } submitted = false; } } class LoginPage extends GetView { const LoginPage({super.key}); @override Widget build(BuildContext context) { final screenSize = Get.mediaQuery.size; final formWidth = screenSize.width <= 600 ? screenSize.width : 300.0; return Scaffold( body: Stack( children: [ const SizedBox.square( dimension: 0, ), Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ LimitedBox( maxWidth: formWidth, child: Obx( () => Container( color: Colors.black.withAlpha(100), padding: const EdgeInsets.all(16), child: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ TextFormField( enabled: !controller.submitted, decoration: const InputDecoration( labelText: 'Endpoint', hintText: 'Enter Tuuli Endpoint', ), initialValue: ApiController.to.endPoint, onChanged: (value) => controller.endpoint = value, validator: (value) { if (value == null || value.isEmpty) { return 'Please enter Tuuli Endpoint'; } return null; }, ), TextFormField( enabled: !controller.submitted, decoration: const InputDecoration( labelText: 'Login', hintText: 'Enter your username', ), onChanged: (value) => controller.username = value, validator: (value) { if (value == null || value.isEmpty) { return 'Please enter your Login'; } return null; }, ), TextFormField( obscureText: true, enabled: !controller.submitted, decoration: const InputDecoration( labelText: 'Password', hintText: 'Enter your password', ), onChanged: (value) => controller.password = value, validator: (value) { if (value == null || value.isEmpty) { return 'Please enter your password'; } return null; }, ), const SizedBox(height: 16), ElevatedButton( onPressed: !controller.isFormValid || controller.submitted ? null : () => controller.submitForm(), child: const Text('Login'), ), ], ), ), ), ), ], ), ], ), ); } }