feat : login api call
This commit is contained in:
@@ -30,10 +30,13 @@ export 'package:rasadyar_core/presentation/common/common.dart';
|
||||
export 'package:rasadyar_core/presentation/utils/utils.dart';
|
||||
export 'package:rasadyar_core/presentation/widget/widget.dart';
|
||||
|
||||
export 'infrastructure/remote/dio_form_data.dart';
|
||||
|
||||
//network
|
||||
export 'infrastructure/remote/dio_form_data.dart';
|
||||
export 'infrastructure/remote/dio_remote.dart';
|
||||
export 'infrastructure/remote/dio_response.dart';
|
||||
export 'package:dio/dio.dart' show DioException;
|
||||
|
||||
//utils
|
||||
export 'utils/logger_utils.dart';
|
||||
export 'utils/safe_call_utils.dart';
|
||||
|
||||
@@ -16,7 +16,11 @@ class DioRemote implements IHttpClient {
|
||||
Future<void> init() async {
|
||||
final dio = Dio(BaseOptions(baseUrl: baseUrl));
|
||||
if (kDebugMode) {
|
||||
dio.interceptors.add(PrettyDioLogger());
|
||||
dio.interceptors.add(PrettyDioLogger(
|
||||
requestHeader: true,
|
||||
responseHeader: true,
|
||||
requestBody: true
|
||||
));
|
||||
}
|
||||
_dio = dio;
|
||||
}
|
||||
|
||||
@@ -3,51 +3,65 @@ import 'package:rasadyar_core/presentation/common/app_color.dart';
|
||||
import 'package:rasadyar_core/presentation/common/app_fonts.dart';
|
||||
|
||||
class RElevated extends StatelessWidget {
|
||||
RElevated({
|
||||
const RElevated({
|
||||
super.key,
|
||||
required this.text,
|
||||
required this.onPressed,
|
||||
this.foregroundColor,
|
||||
this.backgroundColor,
|
||||
this.foregroundColor = Colors.white,
|
||||
this.backgroundColor = AppColor.blueNormal,
|
||||
this.disabledBackgroundColor,
|
||||
this.disabledForegroundColor,
|
||||
this.radius,
|
||||
this.disabledForegroundColor = Colors.white,
|
||||
this.radius = 8.0,
|
||||
this.textStyle,
|
||||
this.width = 150.0,
|
||||
this.height = 56.0,
|
||||
this.isFullWidth,
|
||||
this.isFullWidth = false,
|
||||
this.isLoading = false,
|
||||
});
|
||||
|
||||
final String text;
|
||||
final VoidCallback? onPressed;
|
||||
final double width;
|
||||
final double height;
|
||||
final bool? isFullWidth;
|
||||
Color? foregroundColor;
|
||||
Color? backgroundColor;
|
||||
Color? disabledForegroundColor;
|
||||
Color? disabledBackgroundColor;
|
||||
double? radius;
|
||||
TextStyle? textStyle;
|
||||
final bool isFullWidth;
|
||||
final Color foregroundColor;
|
||||
final Color backgroundColor;
|
||||
final Color? disabledForegroundColor;
|
||||
final Color? disabledBackgroundColor;
|
||||
final double radius;
|
||||
final TextStyle? textStyle;
|
||||
final bool isLoading;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bool isEnabled = onPressed != null && !isLoading;
|
||||
|
||||
return ElevatedButton(
|
||||
onPressed: onPressed,
|
||||
onPressed: isEnabled ? onPressed : null,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: backgroundColor ?? AppColor.blueNormal,
|
||||
foregroundColor: foregroundColor ?? Colors.white,
|
||||
backgroundColor: backgroundColor,
|
||||
foregroundColor: foregroundColor,
|
||||
disabledBackgroundColor:
|
||||
disabledBackgroundColor ?? AppColor.blueNormal.withAlpha(38),
|
||||
disabledForegroundColor: disabledForegroundColor ?? Colors.white,
|
||||
disabledBackgroundColor ?? backgroundColor.withAlpha(38),
|
||||
disabledForegroundColor: disabledForegroundColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(radius ?? 8),
|
||||
borderRadius: BorderRadius.circular(radius),
|
||||
),
|
||||
minimumSize: Size((isFullWidth ??false) ? double.infinity : width, height),
|
||||
minimumSize: Size(isFullWidth ? double.infinity : width, height),
|
||||
padding: EdgeInsets.zero,
|
||||
textStyle: textStyle ?? AppFonts.yekan24,
|
||||
),
|
||||
child: Text(text),
|
||||
child:
|
||||
isLoading
|
||||
? SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2.5,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(foregroundColor),
|
||||
),
|
||||
)
|
||||
: Text(text),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,164 +2,106 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
@immutable
|
||||
enum RTextFieldVariant {
|
||||
normal,
|
||||
noBorder,
|
||||
password,
|
||||
passwordNoBorder,
|
||||
}
|
||||
|
||||
class RTextField extends StatefulWidget {
|
||||
RTextField({
|
||||
super.key,
|
||||
this.maxLines,
|
||||
this.maxLength,
|
||||
this.hintText,
|
||||
this.padding,
|
||||
this.onChanged,
|
||||
this.onSubmitted,
|
||||
this.keyboardType,
|
||||
this.showCounter = false,
|
||||
this.isDense,
|
||||
this.initText,
|
||||
this.isForNumber = false,
|
||||
this.style,
|
||||
this.hintStyle,
|
||||
this.suffixIcon,
|
||||
this.prefixIcon,
|
||||
this.validator,
|
||||
this.readonly = false,
|
||||
this.boxConstraints,
|
||||
this.minLines,
|
||||
this.radius,
|
||||
this.filled,
|
||||
this.filledColor,
|
||||
this.enabled,
|
||||
this.errorStyle,
|
||||
this.labelStyle,
|
||||
this.label,
|
||||
}) {
|
||||
filled = filled ?? false;
|
||||
obscure = false;
|
||||
_inputBorder = OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(radius ?? 8),
|
||||
);
|
||||
}
|
||||
|
||||
RTextField.noBorder({
|
||||
super.key,
|
||||
this.maxLines,
|
||||
this.maxLength,
|
||||
this.hintText,
|
||||
this.padding,
|
||||
this.onChanged,
|
||||
this.onSubmitted,
|
||||
this.keyboardType,
|
||||
this.showCounter = false,
|
||||
this.isDense,
|
||||
this.initText,
|
||||
this.style,
|
||||
this.hintStyle,
|
||||
this.suffixIcon,
|
||||
this.radius,
|
||||
this.validator,
|
||||
this.boxConstraints,
|
||||
this.minLines,
|
||||
this.isForNumber = false,
|
||||
this.readonly = false,
|
||||
this.label,
|
||||
this.filled,
|
||||
this.filledColor,
|
||||
this.errorStyle,
|
||||
this.labelStyle,
|
||||
this.enabled,
|
||||
}) {
|
||||
_inputBorder = OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
borderRadius: BorderRadius.circular(radius ?? 16),
|
||||
);
|
||||
obscure = false;
|
||||
filled = filled ?? true;
|
||||
}
|
||||
|
||||
RTextField.password({
|
||||
super.key,
|
||||
this.maxLines = 1,
|
||||
this.maxLength,
|
||||
this.hintText,
|
||||
this.padding,
|
||||
this.onChanged,
|
||||
this.onSubmitted,
|
||||
this.keyboardType,
|
||||
this.showCounter = false,
|
||||
this.isDense,
|
||||
this.initText,
|
||||
this.style,
|
||||
this.hintStyle,
|
||||
this.suffixIcon,
|
||||
this.prefixIcon,
|
||||
this.radius,
|
||||
this.validator,
|
||||
this.boxConstraints,
|
||||
this.minLines,
|
||||
this.isForNumber = false,
|
||||
this.readonly = false,
|
||||
this.label,
|
||||
this.filled,
|
||||
this.filledColor,
|
||||
this.errorStyle,
|
||||
this.labelStyle,
|
||||
this.enabled,
|
||||
}) {
|
||||
_inputBorder = OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
borderRadius: BorderRadius.circular(radius ?? 16),
|
||||
);
|
||||
filled = filled ?? true;
|
||||
obscure = true;
|
||||
_isPassword = true;
|
||||
prefixIcon = prefixIcon ?? const Icon(CupertinoIcons.person);
|
||||
}
|
||||
|
||||
final int? maxLines;
|
||||
final int? minLines;
|
||||
final int? maxLength;
|
||||
final String? hintText;
|
||||
final TextEditingController controller;
|
||||
final String? label;
|
||||
final EdgeInsets? padding;
|
||||
final String? hintText;
|
||||
final String? initText;
|
||||
final bool obscure;
|
||||
final bool readonly;
|
||||
final bool enabled;
|
||||
final int? maxLength;
|
||||
final int? minLines;
|
||||
final int? maxLines;
|
||||
final Widget? suffixIcon;
|
||||
final Widget? prefixIcon;
|
||||
final BoxConstraints? boxConstraints;
|
||||
final RTextFieldVariant variant;
|
||||
final bool filled;
|
||||
final Color? filledColor;
|
||||
final bool showCounter;
|
||||
final bool isDense;
|
||||
final TextInputType? keyboardType;
|
||||
final TextStyle? style;
|
||||
final TextStyle? errorStyle;
|
||||
final TextStyle? hintStyle;
|
||||
final TextStyle? labelStyle;
|
||||
final bool showCounter;
|
||||
final bool? isDense;
|
||||
final bool? isForNumber;
|
||||
final bool readonly;
|
||||
bool? obscure;
|
||||
final bool? enabled;
|
||||
final double? radius;
|
||||
final TextInputType? keyboardType;
|
||||
final Function(String)? onChanged;
|
||||
final Function(String)? onSubmitted;
|
||||
final FormFieldValidator? validator;
|
||||
final String? initText;
|
||||
Widget? suffixIcon;
|
||||
Widget? prefixIcon;
|
||||
bool? filled;
|
||||
Color? filledColor;
|
||||
bool _isPassword = false;
|
||||
final TextStyle? errorStyle;
|
||||
final EdgeInsets? padding;
|
||||
final FormFieldValidator<String>? validator;
|
||||
final void Function(String)? onChanged;
|
||||
final void Function(String)? onSubmitted;
|
||||
|
||||
const RTextField({
|
||||
super.key,
|
||||
required this.controller,
|
||||
this.label,
|
||||
this.hintText,
|
||||
this.initText,
|
||||
this.obscure = false,
|
||||
this.readonly = false,
|
||||
this.enabled = true,
|
||||
this.maxLength,
|
||||
this.minLines,
|
||||
this.maxLines = 1,
|
||||
this.suffixIcon,
|
||||
this.prefixIcon,
|
||||
this.boxConstraints,
|
||||
this.variant = RTextFieldVariant.normal,
|
||||
this.filled = false,
|
||||
this.filledColor,
|
||||
this.showCounter = false,
|
||||
this.isDense = false,
|
||||
this.keyboardType,
|
||||
this.style,
|
||||
this.hintStyle,
|
||||
this.labelStyle,
|
||||
this.errorStyle,
|
||||
this.padding,
|
||||
this.validator,
|
||||
this.onChanged,
|
||||
this.onSubmitted,
|
||||
});
|
||||
|
||||
final BoxConstraints? boxConstraints;
|
||||
late final InputBorder? _inputBorder;
|
||||
|
||||
@override
|
||||
State<RTextField> createState() => _RTextFieldState();
|
||||
|
||||
bool get _isPassword => variant == RTextFieldVariant.password;
|
||||
bool get _noBorder => variant == RTextFieldVariant.noBorder;
|
||||
bool get _passwordNoBorder => variant == RTextFieldVariant.passwordNoBorder;
|
||||
|
||||
|
||||
InputBorder get _inputBorder =>
|
||||
_noBorder || _passwordNoBorder ? InputBorder.none : OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: AppColor.lightGreyDarkActive,
|
||||
width: 1,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
class _RTextFieldState extends State<RTextField> {
|
||||
final TextEditingController _controller = TextEditingController();
|
||||
bool? obscure;
|
||||
late bool obscure;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.initText != null) {
|
||||
_controller.text = widget.initText!;
|
||||
widget.controller.text = widget.initText!;
|
||||
}
|
||||
obscure = widget.obscure;
|
||||
}
|
||||
@@ -167,51 +109,56 @@ class _RTextFieldState extends State<RTextField> {
|
||||
@override
|
||||
void didUpdateWidget(covariant RTextField oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.initText != oldWidget.initText) {
|
||||
_controller.text = widget.initText ?? '';
|
||||
if (widget.initText != null && widget.initText != oldWidget.initText) {
|
||||
widget.controller.text = widget.initText!;
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildSuffixIcon() {
|
||||
if (widget.suffixIcon != null) return widget.suffixIcon!;
|
||||
if (!widget._isPassword) return const SizedBox.shrink();
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
obscure = !obscure;
|
||||
});
|
||||
},
|
||||
child: Icon(
|
||||
obscure ? CupertinoIcons.eye : CupertinoIcons.eye_slash,
|
||||
color: AppColor.darkGreyDarkActive,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: widget.padding ?? EdgeInsets.zero,
|
||||
child: TextFormField(
|
||||
controller: _controller,
|
||||
controller: widget.controller,
|
||||
readOnly: widget.readonly,
|
||||
minLines: widget.minLines,
|
||||
maxLines: widget.maxLines,
|
||||
onChanged: widget.onChanged,
|
||||
validator: widget.validator,
|
||||
enabled: widget.enabled,
|
||||
obscureText: obscure ?? false,
|
||||
onTapOutside: (event) {
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
obscureText: obscure,
|
||||
onTapOutside: (_) => FocusScope.of(context).unfocus(),
|
||||
onFieldSubmitted: widget.onSubmitted,
|
||||
maxLength: widget.maxLength,
|
||||
textDirection: TextDirection.rtl,
|
||||
style: widget.style,
|
||||
keyboardType: widget.keyboardType,
|
||||
decoration: InputDecoration(
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
errorStyle: widget.errorStyle,
|
||||
errorMaxLines: 1,
|
||||
isDense: widget.isDense,
|
||||
suffixIcon:
|
||||
widget.suffixIcon ??
|
||||
(widget._isPassword
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
obscure = !obscure!;
|
||||
});
|
||||
},
|
||||
icon: Icon(
|
||||
!obscure! ? CupertinoIcons.eye_slash : CupertinoIcons.eye,
|
||||
),
|
||||
)
|
||||
: null),
|
||||
suffixIcon: _buildSuffixIcon(),
|
||||
suffixIconConstraints: widget.boxConstraints,
|
||||
prefixIcon: widget.prefixIcon,
|
||||
prefixIconConstraints: widget.boxConstraints,
|
||||
@@ -221,7 +168,7 @@ class _RTextFieldState extends State<RTextField> {
|
||||
labelStyle: AppFonts.yekan14
|
||||
.copyWith(color: AppColor.lightGreyDarkActive)
|
||||
.merge(widget.labelStyle),
|
||||
filled: widget.filled,
|
||||
filled: widget.filled || widget._noBorder || widget._passwordNoBorder,
|
||||
fillColor: widget.filledColor,
|
||||
counter: widget.showCounter ? null : const SizedBox(),
|
||||
hintStyle: widget.hintStyle,
|
||||
@@ -232,4 +179,4 @@ class _RTextFieldState extends State<RTextField> {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
@@ -6,7 +7,7 @@ typedef ErrorCallback = void Function(dynamic error, StackTrace? stackTrace);
|
||||
typedef VoidCallback = void Function();
|
||||
|
||||
// تعریف دقیق تابع safeCall
|
||||
Future<T?> safeCall<T>({
|
||||
Future<void> safeCall<T>({
|
||||
required AsyncCallback<T> call,
|
||||
Function(T result)? onSuccess,
|
||||
ErrorCallback? onError,
|
||||
@@ -33,7 +34,7 @@ Future<T?> safeCall<T>({
|
||||
}
|
||||
|
||||
onSuccess?.call(result);
|
||||
return result;
|
||||
|
||||
|
||||
} catch (error, stackTrace) {
|
||||
if (showError) {
|
||||
@@ -45,7 +46,6 @@ Future<T?> safeCall<T>({
|
||||
print('safeCall error: $error\n$stackTrace');
|
||||
}
|
||||
|
||||
return null;
|
||||
} finally {
|
||||
if (showLoading) {
|
||||
(onHideLoading ?? _defaultHideLoading)();
|
||||
|
||||
Reference in New Issue
Block a user