fix: register page

This commit is contained in:
akhdanre 2025-05-23 15:04:04 +07:00
parent bfd959a5df
commit bfa253ceec
11 changed files with 264 additions and 51 deletions

View File

@ -1,12 +1,14 @@
import 'package:get/get.dart';
import 'package:quiz_app/data/controllers/user_controller.dart';
import 'package:quiz_app/data/providers/dio_client.dart';
import 'package:quiz_app/data/services/connection_service.dart';
import 'package:quiz_app/data/services/user_storage_service.dart';
class InitialBindings extends Bindings {
@override
void dependencies() {
Get.put<UserStorageService>(UserStorageService());
Get.put(ConnectionService());
Get.putAsync(() => ApiClient().init());
Get.put<UserController>(UserController(Get.find<UserStorageService>()));
}

View File

@ -0,0 +1,17 @@
import 'package:quiz_app/core/utils/custom_notification.dart';
class ConnectionNotification {
static void internetConnected() {
CustomNotification.success(
title: "Terkoneksi kembali",
message: "Terhubugn dengan koneksi",
);
}
static void noInternedConnection() {
CustomNotification.error(
title: "Tidak ada internet",
message: "cek kembali koneksi internet kamu",
);
}
}

View File

@ -0,0 +1,56 @@
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:get/get.dart';
/// [ConnectionService] is a GetX Service that monitors internet connectivity status.
///
/// It utilizes the [Connectivity] class from the `connectivity_plus` package.
class ConnectionService extends GetxService {
final Connectivity _connectivity = Connectivity();
/// Subscription to the connectivity change stream.
late StreamSubscription<List<ConnectivityResult>> _subscription;
/// Reactive boolean to indicate the current internet connection status.
/// `true` means the device is connected to the internet via Wi-Fi, mobile data, or other means.
final RxBool isConnected = true.obs;
bool get isCurrentlyConnected => isConnected.value;
/// Called when the service is first initialized.
@override
void onInit() {
super.onInit();
_initConnectivity();
_subscription = _connectivity.onConnectivityChanged.listen(_updateConnectionStatus);
}
/// Checks the initial connectivity status when the service is initialized.
Future<void> _initConnectivity() async {
try {
final result = await _connectivity.checkConnectivity();
_updateConnectionStatus(result); // Wrap in a list for consistency
} catch (e) {
isConnected.value = false;
}
}
/// Callback function to handle changes in connectivity status.
/// @param results A list of [ConnectivityResult] representing all active network connections.
void _updateConnectionStatus(List<ConnectivityResult> results) {
// If all results are `none`, the device is considered offline.
isConnected.value = results.any((result) => result != ConnectivityResult.none);
}
Future<bool> checkConnection() async {
final result = await _connectivity.checkConnectivity();
return !result.contains(ConnectivityResult.none);
}
/// Cancels the connectivity subscription when the service is closed.
@override
void onClose() {
_subscription.cancel();
super.onClose();
}
}

View File

@ -2,6 +2,7 @@ import 'package:get/get_core/get_core.dart';
import 'package:get/get_instance/get_instance.dart';
import 'package:quiz_app/data/controllers/user_controller.dart';
import 'package:quiz_app/data/services/auth_service.dart';
import 'package:quiz_app/data/services/connection_service.dart';
import 'package:quiz_app/data/services/google_auth_service.dart';
import 'package:quiz_app/data/services/user_storage_service.dart';
import 'package:quiz_app/feature/login/controllers/login_controller.dart';
@ -11,6 +12,14 @@ class LoginBinding extends Bindings {
void dependencies() {
Get.lazyPut<GoogleAuthService>(() => GoogleAuthService());
Get.lazyPut(() => AuthService());
Get.lazyPut(() => LoginController(Get.find<AuthService>(), Get.find<UserStorageService>(), Get.find<UserController>(), Get.find<GoogleAuthService>()));
Get.lazyPut(
() => LoginController(
Get.find<AuthService>(),
Get.find<UserStorageService>(),
Get.find<UserController>(),
Get.find<GoogleAuthService>(),
Get.find<ConnectionService>(),
),
);
}
}

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:quiz_app/app/routes/app_pages.dart';
import 'package:quiz_app/component/global_button.dart';
import 'package:quiz_app/core/helper/connection_check.dart';
import 'package:quiz_app/core/utils/custom_notification.dart';
import 'package:quiz_app/core/utils/logger.dart';
import 'package:quiz_app/data/controllers/user_controller.dart';
@ -9,6 +10,7 @@ import 'package:quiz_app/data/entity/user/user_entity.dart';
import 'package:quiz_app/data/models/login/login_request_model.dart';
import 'package:quiz_app/data/models/login/login_response_model.dart';
import 'package:quiz_app/data/services/auth_service.dart';
import 'package:quiz_app/data/services/connection_service.dart';
import 'package:quiz_app/data/services/google_auth_service.dart';
import 'package:quiz_app/data/services/user_storage_service.dart';
@ -17,12 +19,14 @@ class LoginController extends GetxController {
final UserStorageService _userStorageService;
final UserController _userController;
final GoogleAuthService _googleAuthService;
final ConnectionService _connectionService;
LoginController(
this._authService,
this._userStorageService,
this._userController,
this._googleAuthService,
this._connectionService,
);
final TextEditingController emailController = TextEditingController();
@ -37,7 +41,25 @@ class LoginController extends GetxController {
super.onInit();
emailController.addListener(validateFields);
passwordController.addListener(validateFields);
ever(_connectionService.isConnected, (value) {
if (!value) {
ConnectionNotification.noInternedConnection();
} else {
ConnectionNotification.internetConnected();
}
});
}
@override
void onReady() {
if (!_connectionService.isCurrentlyConnected) {
ConnectionNotification.noInternedConnection();
}
super.onReady();
}
void checkConnection() async {}
void validateFields() {
final isEmailNotEmpty = emailController.text.trim().isNotEmpty;
@ -59,6 +81,10 @@ class LoginController extends GetxController {
return;
}
if (!_connectionService.isCurrentlyConnected) {
ConnectionNotification.noInternedConnection();
return;
}
try {
isLoading.value = true;
@ -81,8 +107,11 @@ class LoginController extends GetxController {
}
}
/// **🔹 Login via Google**
Future<void> loginWithGoogle() async {
if (!_connectionService.isCurrentlyConnected) {
ConnectionNotification.noInternedConnection();
return;
}
try {
final user = await _googleAuthService.signIn();
if (user == null) {
@ -112,7 +141,6 @@ class LoginController extends GetxController {
void goToRegsPage() => Get.toNamed(AppRoutes.registerPage);
/// Helper untuk convert LoginResponseModel ke UserEntity
UserEntity _convertLoginResponseToUserEntity(LoginResponseModel response) {
logC.i("user id : ${response.id}");
return UserEntity(

View File

@ -16,7 +16,7 @@ class LoginView extends GetView<LoginController> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.background, // background soft clean
backgroundColor: AppColors.background,
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),

View File

@ -1,11 +1,17 @@
import 'package:get/get.dart';
import 'package:quiz_app/data/services/auth_service.dart';
import 'package:quiz_app/data/services/connection_service.dart';
import 'package:quiz_app/feature/register/controller/register_controller.dart';
class RegisterBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => AuthService());
Get.lazyPut(() => RegisterController(Get.find<AuthService>()));
Get.lazyPut(
() => RegisterController(
Get.find<AuthService>(),
Get.find<ConnectionService>(),
),
);
}
}

View File

@ -1,14 +1,20 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:quiz_app/core/helper/connection_check.dart';
import 'package:quiz_app/core/utils/custom_floating_loading.dart';
import 'package:quiz_app/core/utils/custom_notification.dart';
import 'package:quiz_app/data/models/register/register_request.dart';
import 'package:quiz_app/data/services/auth_service.dart';
import 'package:quiz_app/data/services/connection_service.dart';
class RegisterController extends GetxController {
final AuthService _authService;
final ConnectionService _connectionService;
RegisterController(this._authService);
RegisterController(
this._authService,
this._connectionService,
);
final TextEditingController nameController = TextEditingController();
final TextEditingController bDateController = TextEditingController();
@ -20,6 +26,14 @@ class RegisterController extends GetxController {
var isPasswordHidden = true.obs;
var isConfirmPasswordHidden = true.obs;
@override
void onReady() {
if (!_connectionService.isCurrentlyConnected) {
ConnectionNotification.noInternedConnection();
}
super.onReady();
}
void togglePasswordVisibility() {
isPasswordHidden.value = !isPasswordHidden.value;
}
@ -29,6 +43,11 @@ class RegisterController extends GetxController {
}
Future<void> onRegister() async {
if (!_connectionService.isCurrentlyConnected) {
ConnectionNotification.noInternedConnection();
return;
}
String email = emailController.text.trim();
String name = nameController.text.trim();
String birthDate = bDateController.text.trim();

View File

@ -18,12 +18,16 @@ class RegisterView extends GetView<RegisterController> {
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: ListView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 40),
child: AppName(),
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
buildBackHeader(),
const SizedBox(height: 30),
AppName(),
const SizedBox(height: 40),
LabelTextField(
label: context.tr('register_title'),
fontSize: 24,
@ -65,7 +69,11 @@ class RegisterView extends GetView<RegisterController> {
onToggleVisibility: controller.toggleConfirmPasswordVisibility,
),
),
const SizedBox(height: 40),
],
),
),
),
const SizedBox(height: 20),
GlobalButton(
onPressed: controller.onRegister,
text: context.tr('register_button'),
@ -76,4 +84,23 @@ class RegisterView extends GetView<RegisterController> {
),
);
}
Widget buildBackHeader({String title = ""}) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Get.back(),
),
Text(
title,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
],
);
}
}

View File

@ -49,6 +49,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.19.0"
connectivity_plus:
dependency: "direct main"
description:
name: connectivity_plus
sha256: "051849e2bd7c7b3bc5844ea0d096609ddc3a859890ec3a9ac4a65a2620cc1f99"
url: "https://pub.dev"
source: hosted
version: "6.1.4"
connectivity_plus_platform_interface:
dependency: transitive
description:
name: connectivity_plus_platform_interface
sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
crypto:
dependency: transitive
description:
@ -65,6 +81,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.8"
dbus:
dependency: transitive
description:
name: dbus
sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c"
url: "https://pub.dev"
source: hosted
version: "0.7.11"
dio:
dependency: "direct main"
description:
@ -333,6 +357,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.4"
nm:
dependency: transitive
description:
name: nm
sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254"
url: "https://pub.dev"
source: hosted
version: "0.5.0"
path:
dependency: transitive
description:
@ -397,6 +429,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.2.5"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
version: "6.0.2"
platform:
dependency: transitive
description:
@ -578,6 +618,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.0"
xml:
dependency: transitive
description:
name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
version: "6.5.0"
sdks:
dart: ">=3.6.0 <4.0.0"
flutter: ">=3.27.0"

View File

@ -45,6 +45,7 @@ dependencies:
socket_io_client: ^3.1.2
easy_localization: ^3.0.7+1
percent_indicator: ^4.2.5
connectivity_plus: ^6.1.4
dev_dependencies:
flutter_test: