diff --git a/packages/auth/lib/data/common/constant.dart b/packages/auth/lib/data/common/constant.dart index c9a0aba..c0b0982 100644 --- a/packages/auth/lib/data/common/constant.dart +++ b/packages/auth/lib/data/common/constant.dart @@ -1,5 +1,5 @@ enum ApiEnvironment { - dam(url: 'https://api.dam.rasadyar.net'); + dam(url: 'https://api.dam.rasadyar.net/'); const ApiEnvironment({required this.url}); diff --git a/packages/auth/lib/data/common/dio_manager.dart b/packages/auth/lib/data/common/dio_manager.dart index 37f46ee..441485a 100644 --- a/packages/auth/lib/data/common/dio_manager.dart +++ b/packages/auth/lib/data/common/dio_manager.dart @@ -8,9 +8,12 @@ class DioRemoteManager { DioRemote? _currentClient; ApiEnvironment? _currentEnv; - DioRemote setEnvironment(ApiEnvironment env) { + Future setEnvironment([ + ApiEnvironment env = ApiEnvironment.dam, + ]) async { if (_currentEnv != env) { _currentClient = DioRemote(env.baseUrl); + await _currentClient?.init(); _currentEnv = env; } return _currentClient!; @@ -30,10 +33,10 @@ class DioRemoteManager { Future switchAuthEnvironment(ApiEnvironment env) async { final manager = diAuth.get(); - final dioRemote = manager.setEnvironment(env); + final dioRemote = await manager.setEnvironment(env); if (diAuth.isRegistered()) { - await diAuth.unregister(); + await diAuth.unregister(); } diAuth.registerLazySingleton( diff --git a/packages/auth/lib/data/di/auth_di.dart b/packages/auth/lib/data/di/auth_di.dart index 3451b86..391647f 100644 --- a/packages/auth/lib/data/di/auth_di.dart +++ b/packages/auth/lib/data/di/auth_di.dart @@ -12,14 +12,10 @@ Future setupAuthDI() async { diAuth.registerLazySingleton(() => DioRemoteManager()); final manager = diAuth.get(); - final dioRemote = manager.setEnvironment(ApiEnvironment.dam); - - diAuth.registerLazySingleton( + final dioRemote = await manager.setEnvironment(ApiEnvironment.dam); + diAuth.registerCachedFactory( () => AuthRepositoryImpl(dioRemote), ); diAuth.registerLazySingleton(() => AuthService()); diAuth.registerLazySingleton(() => TokenStorageService()); - - //hive - //await diAuth.registerCachedFactoryAsync(() async=>await ,) } diff --git a/packages/auth/lib/data/repositories/auth_repository_imp.dart b/packages/auth/lib/data/repositories/auth_repository_imp.dart index a3bc1ee..523efad 100644 --- a/packages/auth/lib/data/repositories/auth_repository_imp.dart +++ b/packages/auth/lib/data/repositories/auth_repository_imp.dart @@ -34,17 +34,18 @@ class AuthRepositoryImpl implements AuthRepository { @override Future captcha() async { - final response = await safeCall>( + final response = await safeCall( call: () async => await _httpClient.post( - '$_BASE_URL/login/', + 'captcha/', headers: {'Content-Type': 'application/json'}, + fromJson: CaptchaResponseModel.fromJson ), onSuccess: (response) { iLog(response); }, onError: (error, trace) { - throw Exception('Error during sign in: $error'); + throw Exception('Error during captcha : $error'); }, ); diff --git a/packages/auth/lib/presentation/pages/auth/logic.dart b/packages/auth/lib/presentation/pages/auth/logic.dart index 505e224..737c4a3 100644 --- a/packages/auth/lib/presentation/pages/auth/logic.dart +++ b/packages/auth/lib/presentation/pages/auth/logic.dart @@ -1,6 +1,8 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:rasadyar_auth/auth.dart'; +import 'package:rasadyar_auth/data/repositories/auth_repository_imp.dart'; import 'package:rasadyar_core/core.dart'; enum AuthType { useAndPass, otp } @@ -18,8 +20,7 @@ class AuthLogic extends GetxController { Rx phoneOtpNumberController = TextEditingController().obs; Rx otpCodeController = TextEditingController().obs; - CaptchaController captchaController = CaptchaController(); - CaptchaController captchaOtpController = CaptchaController(); + RxnString phoneNumber = RxnString(null); RxnString password = RxnString(null); @@ -32,6 +33,8 @@ class AuthLogic extends GetxController { RxInt secondsRemaining = 120.obs; Timer? _timer; + AuthRepositoryImpl authRepository = diAuth.get(); + void startTimer() { _timer?.cancel(); secondsRemaining.value = 120; @@ -55,6 +58,12 @@ class AuthLogic extends GetxController { return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}'; } + @override + void onInit() { + super.onInit(); + + } + @override void onReady() { // TODO: implement onReady @@ -66,4 +75,6 @@ class AuthLogic extends GetxController { _timer?.cancel(); super.onClose(); } + + } diff --git a/packages/auth/lib/presentation/pages/auth/view.dart b/packages/auth/lib/presentation/pages/auth/view.dart index 9708005..98cc7aa 100644 --- a/packages/auth/lib/presentation/pages/auth/view.dart +++ b/packages/auth/lib/presentation/pages/auth/view.dart @@ -1,12 +1,12 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:rasadyar_auth/presentation/widget/captcha/view.dart'; +import 'package:rasadyar_auth/presentation/widget/clear_button.dart'; import 'package:rasadyar_core/core.dart'; import 'logic.dart'; - - class AuthPage extends GetView { const AuthPage({super.key}); @@ -21,7 +21,7 @@ class AuthPage extends GetView { ObxValue((types) { switch (types.value) { case AuthType.otp: - return otpForm(); + //return otpForm(); case AuthType.useAndPass: return useAndPassFrom(); } @@ -222,7 +222,7 @@ class AuthPage extends GetView { }, controller.passwordController), SizedBox(height: 26), - CaptchaWidget(controller: controller.captchaController), + CaptchaWidget(), SizedBox(height: 23), RElevated( @@ -237,9 +237,6 @@ class AuthPage extends GetView { initialEntryMode: PersianDatePickerEntryMode.calendarOnly, initialDatePickerMode: PersianDatePickerMode.year, ); - - if (data.value.currentState?.validate() == true && - controller.captchaController.validate()) {} }, width: Get.width, height: 48, @@ -251,7 +248,7 @@ class AuthPage extends GetView { }, controller.formKey); } - Widget otpForm() { +/* Widget otpForm() { return ObxValue((status) { switch (status.value) { case OtpStatus.init: @@ -262,7 +259,7 @@ class AuthPage extends GetView { return confirmCodeForm(); } }, controller.otpStatus); - } + }*/ Widget sendCodeForm() { return ObxValue((data) { @@ -335,14 +332,13 @@ class AuthPage extends GetView { SizedBox(height: 26), - CaptchaWidget(controller: controller.captchaOtpController), + CaptchaWidget(), SizedBox(height: 23), RElevated( text: 'ارسال رمز یکبار مصرف', onPressed: () { - if (data.value.currentState?.validate() == true && - controller.captchaOtpController.validate()) { + if (data.value.currentState?.validate() == true) { controller.otpStatus.value = OtpStatus.sent; controller.startTimer(); } @@ -473,7 +469,6 @@ class AuthPage extends GetView { TapGestureRecognizer() ..onTap = () { controller.otpStatus.value = OtpStatus.init; - controller.captchaOtpController.clear(); }, text: ' ویرایش', style: AppFonts.yekan14.copyWith( @@ -489,8 +484,7 @@ class AuthPage extends GetView { text: 'ورود', onPressed: () { if (controller.formKeyOtp.value.currentState?.validate() == - true && - controller.captchaOtpController.validate()) {} + true) {} }, width: Get.width, height: 48, @@ -514,11 +508,4 @@ class AuthPage extends GetView { ], ); } - - Widget clearButton(VoidCallback onTap) { - return GestureDetector( - onTap: onTap, - child: Icon(CupertinoIcons.multiply_circle, size: 24), - ); - } } diff --git a/packages/auth/lib/presentation/widget/clear_button.dart b/packages/auth/lib/presentation/widget/clear_button.dart new file mode 100644 index 0000000..393ebed --- /dev/null +++ b/packages/auth/lib/presentation/widget/clear_button.dart @@ -0,0 +1,8 @@ +import 'package:flutter/cupertino.dart'; + +Widget clearButton(VoidCallback onTap) { + return GestureDetector( + onTap: onTap, + child: Icon(CupertinoIcons.multiply_circle, size: 24), + ); +} diff --git a/packages/core/lib/infrastructure/remote/dio_remote.dart b/packages/core/lib/infrastructure/remote/dio_remote.dart index 9e5a208..9422cc1 100644 --- a/packages/core/lib/infrastructure/remote/dio_remote.dart +++ b/packages/core/lib/infrastructure/remote/dio_remote.dart @@ -1,4 +1,5 @@ import 'package:dio/dio.dart'; +import 'package:flutter/foundation.dart'; import 'package:pretty_dio_logger/pretty_dio_logger.dart'; import 'package:rasadyar_core/infrastructure/remote/interfaces/i_form_data.dart'; @@ -15,7 +16,9 @@ class DioRemote implements IHttpClient { @override Future init() async { final dio = Dio(BaseOptions(baseUrl: baseUrl)); - dio.interceptors.add(PrettyDioLogger()); + if (kDebugMode) { + dio.interceptors.add(PrettyDioLogger()); + } _dio = dio; } @@ -40,6 +43,7 @@ class DioRemote implements IHttpClient { String path, { dynamic data, Map? queryParameters, + T Function(Map json)? fromJson, Map? headers, ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, @@ -52,6 +56,15 @@ class DioRemote implements IHttpClient { onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, ); + + if (fromJson != null) { + final rawData = response.data; + final parsedData = + rawData is Map ? fromJson(rawData) : null; + response.data = parsedData; + return DioResponse(response); + } + return DioResponse(response); } diff --git a/packages/core/lib/presentation/widget/captcha/captcha_widget.dart b/packages/core/lib/presentation/widget/captcha/captcha_widget.dart deleted file mode 100644 index fc20c4e..0000000 --- a/packages/core/lib/presentation/widget/captcha/captcha_widget.dart +++ /dev/null @@ -1,266 +0,0 @@ -import 'dart:math'; - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:rasadyar_core/presentation/common/app_color.dart'; -import 'package:rasadyar_core/presentation/common/app_fonts.dart'; - -class CaptchaController { - int? captchaCode; - TextEditingController textController = TextEditingController(); - GlobalKey formKey = GlobalKey(); - - late Function() refreshCaptcha; - - bool validate() { - if (formKey.currentState?.validate() == true) { - return true; - } - return false; - } - - String get enteredText => textController.text; - - bool isCorrect() { - return textController.text == captchaCode.toString(); - } - - void clear() { - textController.clear(); - } -} - -class RandomLinePainter extends CustomPainter { - final Random random = Random(); - final Paint linePaint; - final List points; - - RandomLinePainter({ - required this.points, - required Color lineColor, - double strokeWidth = 2.0, - }) : linePaint = - Paint() - ..color = lineColor - ..strokeWidth = strokeWidth - ..strokeCap = StrokeCap.round - ..style = PaintingStyle.stroke; - - @override - void paint(Canvas canvas, Size size) { - final path = Path(); - - if (points.isNotEmpty) { - path.moveTo(points[0].dx, points[0].dy); - - for (int i = 1; i < points.length; i++) { - path.lineTo(points[i].dx, points[i].dy); - } - - canvas.drawPath(path, linePaint); - } - } - - @override - bool shouldRepaint(RandomLinePainter oldDelegate) => true; -} - -class CaptchaWidget extends StatefulWidget { - final CaptchaController controller; - final bool autoValidateMode; - - const CaptchaWidget({ - required this.controller, - this.autoValidateMode = false, - super.key, - }); - - @override - _CaptchaWidgetState createState() => _CaptchaWidgetState(); -} - -class _CaptchaWidgetState extends State { - late List points; - late List points1; - late List points2; - bool isOnError = false; - - @override - void initState() { - super.initState(); - generateLines(); - getRandomSixDigitNumber(); - - // Set the refresh function in the controller - widget.controller.refreshCaptcha = () { - getRandomSixDigitNumber(); - generateLines(); - setState(() {}); - }; - } - - void generateLines() { - points = generateRandomLine(); - points1 = generateRandomLine(); - points2 = generateRandomLine(); - setState(() {}); - } - - List generateRandomLine() { - final random = Random(); - int pointCount = random.nextInt(10) + 5; - List points = []; - - double previousY = 0; - - for (int i = 0; i < pointCount; i++) { - double x = (i / (pointCount - 1)) * 135; - - if (i == 0) { - previousY = 24; - } else { - double change = (random.nextDouble() * 20) - 10; - previousY = max(5, min(43, previousY + change)); - } - - points.add(Offset(x, previousY)); - } - - return points; - } - - void getRandomSixDigitNumber() { - final random = Random(); - widget.controller.captchaCode = random.nextInt(900000) + 100000; - setState(() {}); - } - - @override - Widget build(BuildContext context) { - return Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 135, - height: 48, - decoration: BoxDecoration( - color: AppColor.whiteNormalHover, - border: Border.all(color: Colors.grey.shade300), - borderRadius: BorderRadius.circular(8), - ), - child: Stack( - alignment: AlignmentDirectional.center, - children: [ - CustomPaint( - painter: RandomLinePainter( - points: points, - lineColor: Colors.blue, - strokeWidth: 1.0, - ), - size: const Size(double.infinity, double.infinity), - ), - CustomPaint( - painter: RandomLinePainter( - points: points1, - lineColor: Colors.green, - strokeWidth: 1.0, - ), - size: const Size(double.infinity, double.infinity), - ), - CustomPaint( - painter: RandomLinePainter( - points: points2, - lineColor: Colors.red, - strokeWidth: 1.0, - ), - size: const Size(double.infinity, double.infinity), - ), - Text( - widget.controller.captchaCode.toString(), - style: AppFonts.yekan24, - ), - ], - ), - ), - const SizedBox(height: 20), - IconButton( - padding: EdgeInsets.zero, - onPressed: widget.controller.refreshCaptcha, - icon: Icon(CupertinoIcons.refresh, size: 16), - ), - Expanded( - child: Form( - key: widget.controller.formKey, - autovalidateMode: - widget.autoValidateMode - ? AutovalidateMode.onUserInteraction - : AutovalidateMode.disabled, - child: TextFormField( - controller: widget.controller.textController, - decoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - gapPadding: 11, - ), - labelText: 'کد امنیتی', - labelStyle: AppFonts.yekan13, - errorStyle: AppFonts.yekan10.copyWith( - color: AppColor.redNormal, - fontSize: 8, - ), - suffixIconConstraints: BoxConstraints( - maxHeight: 24, - minHeight: 24, - maxWidth: 24, - minWidth: 24, - ), - - suffix: - widget.controller.textController.text.trim().isNotEmpty - ? clearButton(() { - widget.controller.textController.clear(); - setState(() {}); - }) - : null, - counterText: '', - ), - keyboardType: TextInputType.numberWithOptions( - decimal: false, - signed: false, - ), - maxLines: 1, - maxLength: 6, - onChanged: (value) { - if (isOnError) { - isOnError = !isOnError; - widget.controller.formKey.currentState?.reset(); - widget.controller.textController.text = value; - } - setState(() {}); - }, - validator: (value) { - if (value == null || value.isEmpty) { - isOnError = true; - return 'کد امنیتی را وارد کنید'; - } - if (value != widget.controller.captchaCode.toString()) { - isOnError = true; - return '⚠️کد امنیتی وارد شده اشتباه است'; - } - return null; - }, - style: AppFonts.yekan13, - ), - ), - ), - ], - ); - } - - Widget clearButton(VoidCallback onTap) { - return GestureDetector( - onTap: onTap, - child: Icon(CupertinoIcons.multiply_circle, size: 18), - ); - } -} diff --git a/packages/core/lib/presentation/widget/widget.dart b/packages/core/lib/presentation/widget/widget.dart index f61a097..7175a76 100644 --- a/packages/core/lib/presentation/widget/widget.dart +++ b/packages/core/lib/presentation/widget/widget.dart @@ -5,7 +5,6 @@ export 'buttons/elevated.dart'; export 'buttons/outline_elevated.dart'; export 'buttons/outline_elevated_icon.dart'; export 'buttons/text_button.dart'; -export 'captcha/captcha_widget.dart'; export 'draggable_bottom_sheet/draggable_bottom_sheet.dart'; export 'draggable_bottom_sheet/draggable_bottom_sheet_controller.dart'; export 'draggable_bottom_sheet/bottom_sheet_manger.dart';