Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Hoàng Văn Đạt
mypoint_flutter_app
Commits
7d37c9c6
Commit
7d37c9c6
authored
Mar 04, 2025
by
DatHV
Browse files
update otp follow
parent
1257980d
Changes
11
Hide whitespace changes
Inline
Side-by-side
lib/configs/api_paths.dart
View file @
7d37c9c6
...
@@ -4,4 +4,9 @@ class APIPaths {
...
@@ -4,4 +4,9 @@ class APIPaths {
static
const
String
checkUpdate
=
"/version-management-service/api/v1.0/check-customer-software-update"
;
static
const
String
checkUpdate
=
"/version-management-service/api/v1.0/check-customer-software-update"
;
static
const
String
getOnboardingInfo
=
"/resource/api/v2.0/intro-screen"
;
static
const
String
getOnboardingInfo
=
"/resource/api/v2.0/intro-screen"
;
static
const
String
checkPhoneNumber
=
"/user/api/v2.0/account/users/checkPhoneNumber"
;
static
const
String
checkPhoneNumber
=
"/user/api/v2.0/account/users/checkPhoneNumber"
;
static
const
String
verifyOtpWithAction
=
"/iam/v2/authentication/otp/verifyWithAction"
;
static
const
String
retryOtpWithAction
=
"/iam/v2/authentication/otp/retry"
;
}
}
lib/networking/restful_api_request.dart
View file @
7d37c9c6
...
@@ -7,6 +7,7 @@ import '../configs/device_info.dart';
...
@@ -7,6 +7,7 @@ import '../configs/device_info.dart';
import
'../model/update_response_object.dart'
;
import
'../model/update_response_object.dart'
;
import
'../screen/onboarding/model/check_phone_response_model.dart'
;
import
'../screen/onboarding/model/check_phone_response_model.dart'
;
import
'../screen/onboarding/model/onboarding_info_model.dart'
;
import
'../screen/onboarding/model/onboarding_info_model.dart'
;
import
'../screen/otp/otp_verify_response_model.dart'
;
import
'model_maker.dart'
;
import
'model_maker.dart'
;
extension
RestfullAPIClientAllApi
on
RestfulAPIClient
{
extension
RestfullAPIClientAllApi
on
RestfulAPIClient
{
...
@@ -41,4 +42,24 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
...
@@ -41,4 +42,24 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
(
data
)
=>
CheckPhoneResponseModel
.
fromJson
(
data
as
Json
),
(
data
)
=>
CheckPhoneResponseModel
.
fromJson
(
data
as
Json
),
);
);
}
}
Future
<
BaseResponseModel
<
OTPVerifyResponseModel
>>
verifyOTP
(
String
otp
,
String
mfaToken
)
async
{
final
body
=
{
"otp"
:
otp
,
"mfaToken"
:
mfaToken
,};
return
requestNormal
(
APIPaths
.
verifyOtpWithAction
,
Method
.
POST
,
body
,
(
data
)
=>
OTPVerifyResponseModel
.
fromJson
(
data
as
Json
),
);
}
Future
<
BaseResponseModel
<
OTPResendResponseModel
>>
resendOTP
(
String
mfaToken
)
async
{
final
body
=
{
"mfaToken"
:
mfaToken
,};
return
requestNormal
(
APIPaths
.
retryOtpWithAction
,
Method
.
POST
,
body
,
(
data
)
=>
OTPResendResponseModel
.
fromJson
(
data
as
Json
),
);
}
}
}
lib/screen/onboarding/onboarding_screen.dart
View file @
7d37c9c6
...
@@ -9,7 +9,7 @@ import '../../configs/constants.dart';
...
@@ -9,7 +9,7 @@ import '../../configs/constants.dart';
import
'../../resouce/base_color.dart'
;
import
'../../resouce/base_color.dart'
;
import
'../login/login_screen.dart'
;
import
'../login/login_screen.dart'
;
import
'../otp/otp_screen.dart'
;
import
'../otp/otp_screen.dart'
;
import
'../
signup/signup
_otp_repository.dart'
;
import
'../
otp/verify
_otp_repository.dart'
;
import
'model/check_phone_response_model.dart'
;
import
'model/check_phone_response_model.dart'
;
import
'onboarding_view_model.dart'
;
import
'onboarding_view_model.dart'
;
...
@@ -22,7 +22,6 @@ class OnboardingScreen extends BaseScreen {
...
@@ -22,7 +22,6 @@ class OnboardingScreen extends BaseScreen {
class
_OnboardingScreenState
extends
BaseState
<
OnboardingScreen
>
with
BasicState
{
class
_OnboardingScreenState
extends
BaseState
<
OnboardingScreen
>
with
BasicState
{
final
OnboardingViewModel
_viewModel
=
Get
.
find
<
OnboardingViewModel
>();
final
OnboardingViewModel
_viewModel
=
Get
.
find
<
OnboardingViewModel
>();
final
FocusNode
_focusNode
=
FocusNode
();
final
FocusNode
_focusNode
=
FocusNode
();
@override
@override
...
@@ -34,8 +33,13 @@ class _OnboardingScreenState extends BaseState<OnboardingScreen> with BasicState
...
@@ -34,8 +33,13 @@ class _OnboardingScreenState extends BaseState<OnboardingScreen> with BasicState
hideKeyboard
();
hideKeyboard
();
// Get.to(() => const LoginScreen());
// Get.to(() => const LoginScreen());
Get
.
to
(()
=>
OtpScreen
(
Get
.
to
(()
=>
OtpScreen
(
repository:
SignUpOtpRepository
(
_viewModel
.
phoneNumber
.
value
),
repository:
VerifyOtpRepository
(
));
_viewModel
.
phoneNumber
.
value
,
response
.
data
?.
otpTtl
??
0
,
response
.
data
?.
mfaToken
??
""
,
),
),
);
});
});
// _handleResponseCheckPhoneNumber(response.data);
// _handleResponseCheckPhoneNumber(response.data);
// _handleResponseError(response);
// _handleResponseError(response);
...
@@ -128,9 +132,7 @@ class _OnboardingScreenState extends BaseState<OnboardingScreen> with BasicState
...
@@ -128,9 +132,7 @@ class _OnboardingScreenState extends BaseState<OnboardingScreen> with BasicState
/// 📌 Ô nhập số điện thoại
/// 📌 Ô nhập số điện thoại
TextField
(
TextField
(
inputFormatters:
[
inputFormatters:
[
LengthLimitingTextInputFormatter
(
10
)],
LengthLimitingTextInputFormatter
(
10
)
],
// maxLength: 10,
// maxLength: 10,
focusNode:
_focusNode
,
focusNode:
_focusNode
,
keyboardType:
TextInputType
.
phone
,
keyboardType:
TextInputType
.
phone
,
...
@@ -144,7 +146,7 @@ class _OnboardingScreenState extends BaseState<OnboardingScreen> with BasicState
...
@@ -144,7 +146,7 @@ class _OnboardingScreenState extends BaseState<OnboardingScreen> with BasicState
borderRadius:
BorderRadius
.
circular
(
10
),
borderRadius:
BorderRadius
.
circular
(
10
),
borderSide:
BorderSide
.
none
,
borderSide:
BorderSide
.
none
,
),
),
prefixIcon:
const
Icon
(
Icons
.
phone
,
color:
Color
(
0xFF9DA4AE
))
prefixIcon:
const
Icon
(
Icons
.
phone
,
color:
Color
(
0xFF9DA4AE
))
,
),
),
onChanged:
_viewModel
.
updatePhoneNumber
,
onChanged:
_viewModel
.
updatePhoneNumber
,
),
),
...
@@ -158,7 +160,7 @@ class _OnboardingScreenState extends BaseState<OnboardingScreen> with BasicState
...
@@ -158,7 +160,7 @@ class _OnboardingScreenState extends BaseState<OnboardingScreen> with BasicState
onPressed:
onPressed:
_viewModel
.
isButtonEnabled
_viewModel
.
isButtonEnabled
?
()
{
?
()
{
_viewModel
.
checkPhoneNumber
();
_viewModel
.
checkPhoneNumber
();
}
}
:
null
,
:
null
,
style:
ElevatedButton
.
styleFrom
(
style:
ElevatedButton
.
styleFrom
(
...
@@ -178,6 +180,7 @@ class _OnboardingScreenState extends BaseState<OnboardingScreen> with BasicState
...
@@ -178,6 +180,7 @@ class _OnboardingScreenState extends BaseState<OnboardingScreen> with BasicState
),
),
),
),
const
SizedBox
(
height:
16
),
const
SizedBox
(
height:
16
),
/// 📌 Checkbox + Điều khoản sử dụng + Chính sách bảo mật
/// 📌 Checkbox + Điều khoản sử dụng + Chính sách bảo mật
Row
(
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
center
,
crossAxisAlignment:
CrossAxisAlignment
.
center
,
...
...
lib/screen/otp/otp_claim_verify_response_model.dart
0 → 100644
View file @
7d37c9c6
import
'package:json_annotation/json_annotation.dart'
;
part
'otp_claim_verify_response_model.g.dart'
;
@JsonSerializable
()
class
OTPClaimVerifyResponseModel
{
String
?
action
;
String
?
username
;
OTPClaimVerifyResponseModel
({
required
this
.
action
,
required
this
.
username
,
});
factory
OTPClaimVerifyResponseModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$OTPClaimVerifyResponseModelFromJson
(
json
);
Map
<
String
,
dynamic
>
toJson
()
=>
_$OTPClaimVerifyResponseModelToJson
(
this
);
}
lib/screen/otp/otp_claim_verify_response_model.g.dart
0 → 100644
View file @
7d37c9c6
// GENERATED CODE - DO NOT MODIFY BY HAND
part of
'otp_claim_verify_response_model.dart'
;
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
OTPClaimVerifyResponseModel
_$OTPClaimVerifyResponseModelFromJson
(
Map
<
String
,
dynamic
>
json
,
)
=>
OTPClaimVerifyResponseModel
(
action:
json
[
'action'
]
as
String
?,
username:
json
[
'username'
]
as
String
?,
);
Map
<
String
,
dynamic
>
_$OTPClaimVerifyResponseModelToJson
(
OTPClaimVerifyResponseModel
instance
,
)
=>
<
String
,
dynamic
>{
'action'
:
instance
.
action
,
'username'
:
instance
.
username
,
};
lib/screen/otp/otp_screen.dart
View file @
7d37c9c6
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:pin_code_fields/pin_code_fields.dart'
;
import
'package:pin_code_fields/pin_code_fields.dart'
;
import
'../../base/base_screen.dart'
;
import
'../../base/basic_state.dart'
;
import
'../../resouce/base_color.dart'
;
import
'../../resouce/base_color.dart'
;
import
'otp_view_model.dart'
;
import
'otp_view_model.dart'
;
class
OtpScreen
extends
StatefulWidget
{
class
OtpScreen
extends
BaseScreen
{
final
IOtpRepository
repository
;
final
IOtpRepository
repository
;
const
OtpScreen
({
super
.
key
,
required
this
.
repository
});
const
OtpScreen
({
super
.
key
,
required
this
.
repository
});
@override
@override
State
<
OtpScreen
>
createState
()
=>
_OtpScreenState
();
State
<
OtpScreen
>
createState
()
=>
_OtpScreenState
();
}
}
class
_OtpScreenState
extends
State
<
OtpScreen
>
{
class
_OtpScreenState
extends
BaseState
<
OtpScreen
>
with
BasicState
{
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
createBody
(
)
{
final
otpVM
=
Get
.
put
(
OtpViewModel
(
widget
.
repository
));
final
otpVM
=
Get
.
put
(
OtpViewModel
(
widget
.
repository
));
return
Scaffold
(
return
Scaffold
(
appBar:
AppBar
(
appBar:
AppBar
(
centerTitle:
true
,
centerTitle:
true
,
...
@@ -31,7 +32,7 @@ class _OtpScreenState extends State<OtpScreen> {
...
@@ -31,7 +32,7 @@ class _OtpScreenState extends State<OtpScreen> {
child:
Column
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
children:
[
children:
[
const
Text
(
"Nhập mã xác thực OTP"
,
style:
TextStyle
(
fontSize:
2
4
,
fontWeight:
FontWeight
.
bold
)),
const
Text
(
"Nhập mã xác thực OTP"
,
style:
TextStyle
(
fontSize:
3
2
,
fontWeight:
FontWeight
.
bold
)),
const
SizedBox
(
height:
12
),
const
SizedBox
(
height:
12
),
_buildWelcomeText
(
otpVM
),
_buildWelcomeText
(
otpVM
),
const
SizedBox
(
height:
32
),
const
SizedBox
(
height:
32
),
...
@@ -71,10 +72,11 @@ class _OtpScreenState extends State<OtpScreen> {
...
@@ -71,10 +72,11 @@ class _OtpScreenState extends State<OtpScreen> {
),
),
onChanged:
(
value
)
{
onChanged:
(
value
)
{
vm
.
otpCode
.
value
=
value
;
vm
.
otpCode
.
value
=
value
;
vm
.
errorMessage
.
value
=
""
;
// clear lỗi khi gõ
vm
.
errorMessage
.
value
=
"
1111111
"
;
// clear lỗi khi gõ
},
},
onCompleted:
(
value
)
{
onCompleted:
(
value
)
{
vm
.
otpCode
.
value
=
value
;
vm
.
otpCode
.
value
=
value
;
vm
.
onSubmitOtp
;
},
},
);
);
// });
// });
...
...
lib/screen/otp/otp_verify_response_model.dart
0 → 100644
View file @
7d37c9c6
import
'package:json_annotation/json_annotation.dart'
;
import
'otp_claim_verify_response_model.dart'
;
part
'otp_verify_response_model.g.dart'
;
@JsonSerializable
()
class
OTPVerifyResponseModel
{
OTPClaimVerifyResponseModel
?
claim
;
OTPVerifyResponseModel
({
this
.
claim
,
});
factory
OTPVerifyResponseModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$OTPVerifyResponseModelFromJson
(
json
);
Map
<
String
,
dynamic
>
toJson
()
=>
_$OTPVerifyResponseModelToJson
(
this
);
}
@JsonSerializable
()
class
OTPResendResponseModel
{
@JsonKey
(
name:
"otp_ttl"
)
int
?
otpTtl
;
OTPResendResponseModel
({
this
.
otpTtl
,
});
factory
OTPResendResponseModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$OTPResendResponseModelFromJson
(
json
);
Map
<
String
,
dynamic
>
toJson
()
=>
_$OTPResendResponseModelToJson
(
this
);
}
\ No newline at end of file
lib/screen/otp/otp_verify_response_model.g.dart
0 → 100644
View file @
7d37c9c6
// GENERATED CODE - DO NOT MODIFY BY HAND
part of
'otp_verify_response_model.dart'
;
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
OTPVerifyResponseModel
_$OTPVerifyResponseModelFromJson
(
Map
<
String
,
dynamic
>
json
,
)
=>
OTPVerifyResponseModel
(
claim:
json
[
'claim'
]
==
null
?
null
:
OTPClaimVerifyResponseModel
.
fromJson
(
json
[
'claim'
]
as
Map
<
String
,
dynamic
>,
),
);
Map
<
String
,
dynamic
>
_$OTPVerifyResponseModelToJson
(
OTPVerifyResponseModel
instance
,
)
=>
<
String
,
dynamic
>{
'claim'
:
instance
.
claim
};
OTPResendResponseModel
_$OTPResendResponseModelFromJson
(
Map
<
String
,
dynamic
>
json
,
)
=>
OTPResendResponseModel
(
otpTtl:
json
[
'otp_ttl'
]
as
int
?);
Map
<
String
,
dynamic
>
_$OTPResendResponseModelToJson
(
OTPResendResponseModel
instance
,
)
=>
<
String
,
dynamic
>{
'otp_ttl'
:
instance
.
otpTtl
};
lib/screen/otp/otp_view_model.dart
View file @
7d37c9c6
import
'dart:async'
;
import
'dart:async'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get_state_manager/src/simple/get_controllers.dart'
;
import
'package:mypoint_flutter_app/base/base_response_model.dart'
;
import
'otp_verify_response_model.dart'
;
// i_otp_repository.dart
// i_otp_repository.dart
abstract
class
IOtpRepository
{
abstract
class
IOtpRepository
{
Future
<
void
>
sendOtp
();
Future
<
void
>
sendOtp
();
Future
<
bool
>
verifyOtp
(
String
otpCode
);
Future
<
BaseResponseModel
<
OTPVerifyResponseModel
>
>
verifyOtp
(
String
otpCode
);
Future
<
void
>
resendOtp
();
Future
<
void
>
resendOtp
();
late
String
phoneNumber
;
}
}
class
OtpViewModel
extends
GetxController
{
class
OtpViewModel
extends
GetxController
{
final
IOtpRepository
repository
;
final
IOtpRepository
repository
;
// Mã OTP người dùng nhập
var
otpCode
=
""
.
obs
;
var
otpCode
=
""
.
obs
;
// Lỗi (nếu OTP sai)
var
errorMessage
=
""
.
obs
;
var
errorMessage
=
""
.
obs
;
// Đếm ngược thời gian resend
final
int
_maxCountdown
=
150
;
// 2 phút 30 giây
var
currentCountdown
=
0
.
obs
;
var
currentCountdown
=
0
.
obs
;
final
int
_maxCountdown
=
150
;
// 2 phút 30 giây
Timer
?
_timer
;
Timer
?
_timer
;
OtpViewModel
(
this
.
repository
);
OtpViewModel
(
this
.
repository
);
...
@@ -28,7 +24,6 @@ class OtpViewModel extends GetxController {
...
@@ -28,7 +24,6 @@ class OtpViewModel extends GetxController {
@override
@override
void
onInit
()
{
void
onInit
()
{
super
.
onInit
();
super
.
onInit
();
// Gửi OTP ngay khi vào màn hình (tuỳ logic)
sendOtp
();
sendOtp
();
startCountdown
();
startCountdown
();
}
}
...
@@ -39,18 +34,15 @@ class OtpViewModel extends GetxController {
...
@@ -39,18 +34,15 @@ class OtpViewModel extends GetxController {
super
.
onClose
();
super
.
onClose
();
}
}
/// Gửi OTP (lần đầu)
Future
<
void
>
sendOtp
()
async
{
Future
<
void
>
sendOtp
()
async
{
try
{
try
{
await
repository
.
sendOtp
();
await
repository
.
sendOtp
();
// Reset countdown
startCountdown
();
startCountdown
();
}
catch
(
e
)
{
}
catch
(
e
)
{
errorMessage
.
value
=
"Gửi OTP thất bại. Vui lòng thử lại."
;
errorMessage
.
value
=
"Gửi OTP thất bại. Vui lòng thử lại."
;
}
}
}
}
// Đếm ngược 2:30
void
startCountdown
()
{
void
startCountdown
()
{
currentCountdown
.
value
=
_maxCountdown
;
currentCountdown
.
value
=
_maxCountdown
;
_timer
?.
cancel
();
_timer
?.
cancel
();
...
@@ -70,39 +62,31 @@ class OtpViewModel extends GetxController {
...
@@ -70,39 +62,31 @@ class OtpViewModel extends GetxController {
return
"
$m
:
$sStr
"
;
return
"
$m
:
$sStr
"
;
}
}
// User nhập OTP
void
onOtpChanged
(
String
value
)
{
void
onOtpChanged
(
String
value
)
{
otpCode
.
value
=
value
;
otpCode
.
value
=
value
;
errorMessage
.
value
=
""
;
// clear lỗi cũ
errorMessage
.
value
=
""
;
}
}
// Submit OTP
Future
<
void
>
onSubmitOtp
()
async
{
Future
<
void
>
onSubmitOtp
()
async
{
if
(
otpCode
.
value
.
length
<
6
)
{
if
(
otpCode
.
value
.
length
<
6
)
{
errorMessage
.
value
=
"
Vui lòng n
hập đủ 6 ký tự"
;
errorMessage
.
value
=
"
N
hập đủ 6 ký tự"
;
return
;
return
;
}
}
try
{
try
{
final
success
=
await
repository
.
verifyOtp
(
otpCode
.
value
);
final
response
=
await
repository
.
verifyOtp
(
otpCode
.
value
);
if
(
success
)
{
if
(
response
.
isSuccess
)
{
errorMessage
.
value
=
""
;
errorMessage
.
value
=
"response.isSuccess"
;
// TODO: Navigate or do something
// Example: Get.offAllNamed("/home");
print
(
"OTP chính xác! Điều hướng tiếp..."
);
}
else
{
}
else
{
errorMessage
.
value
=
"Mã OTP không chính xác
"
;
errorMessage
.
value
=
response
.
errorMessage
??
"
"
;
}
}
}
catch
(
e
)
{
}
catch
(
e
)
{
errorMessage
.
value
=
"Xác thực OTP thất bại. Thử lại."
;
// Bắt lỗi do repository throw
errorMessage
.
value
=
"Xác thực thất bại:
$e
"
;
}
}
}
}
// Bấm "Gửi lại OTP"
Future
<
void
>
onResendOtp
()
async
{
Future
<
void
>
onResendOtp
()
async
{
if
(
currentCountdown
.
value
>
0
)
{
if
(
currentCountdown
.
value
>
0
)
return
;
// Chưa hết thời gian => return
return
;
}
try
{
try
{
await
repository
.
resendOtp
();
await
repository
.
resendOtp
();
startCountdown
();
startCountdown
();
...
...
lib/screen/otp/verify_otp_repository.dart
0 → 100644
View file @
7d37c9c6
// sign_up_otp_repository.dart
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_request.dart'
;
import
'../../base/base_response_model.dart'
;
import
'../../base/restful_api_viewmodel.dart'
;
import
'otp_verify_response_model.dart'
;
import
'otp_view_model.dart'
;
class
VerifyOtpRepository
extends
RestfulApiViewModel
implements
IOtpRepository
{
int
otpTtl
;
final
String
mfaToken
;
var
otpVerifyResponse
=
BaseResponseModel
<
OTPVerifyResponseModel
>().
obs
;
VerifyOtpRepository
(
this
.
phoneNumber
,
this
.
otpTtl
,
this
.
mfaToken
);
@override
String
phoneNumber
;
@override
Future
<
void
>
sendOtp
()
async
{}
@override
Future
<
BaseResponseModel
<
OTPVerifyResponseModel
>>
verifyOtp
(
String
otpCode
)
async
{
showLoading
();
return
client
.
verifyOTP
(
otpCode
,
mfaToken
).
then
((
value
)
{
hideLoading
();
return
value
;
});
}
@override
Future
<
void
>
resendOtp
()
async
{
showLoading
();
return
client
.
resendOTP
(
mfaToken
).
then
((
value
)
{
otpTtl
=
value
.
data
?.
otpTtl
??
0
;
hideLoading
();
});
}
}
lib/screen/signup/signup_otp_repository.dart
deleted
100644 → 0
View file @
1257980d
// sign_up_otp_repository.dart
import
'package:flutter/material.dart'
;
import
'../otp/otp_view_model.dart'
;
class
SignUpOtpRepository
implements
IOtpRepository
{
final
String
phoneNumber
;
SignUpOtpRepository
(
this
.
phoneNumber
);
@override
Future
<
void
>
sendOtp
()
async
{
debugPrint
(
"[SignUpOtpRepository] Gọi API gửi OTP cho luồng đăng ký"
);
// TODO: call API real
await
Future
.
delayed
(
const
Duration
(
seconds:
1
));
}
@override
Future
<
bool
>
verifyOtp
(
String
otpCode
)
async
{
debugPrint
(
"[SignUpOtpRepository] Gọi API verify OTP cho luồng đăng ký"
);
// TODO: call API real, giả lập OTP "123456" mới đúng
await
Future
.
delayed
(
const
Duration
(
seconds:
1
));
return
otpCode
==
"123456"
;
}
@override
Future
<
void
>
resendOtp
()
async
{
debugPrint
(
"[SignUpOtpRepository] Gọi API resend OTP đăng ký"
);
// TODO: call API real
await
Future
.
delayed
(
const
Duration
(
seconds:
1
));
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment