25-7-28-2

This commit is contained in:
Hamza-Ayed
2025-07-28 12:21:28 +03:00
parent 660d60e1f5
commit 83a97baed1
549 changed files with 109870 additions and 0 deletions

View File

@@ -0,0 +1,176 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../controller/auth/captin/opt_token_controller.dart';
class OtpVerificationPage extends StatefulWidget {
final String phone;
final String deviceToken;
final String token;
final String ptoken;
const OtpVerificationPage({
super.key,
required this.phone,
required this.deviceToken,
required this.token,
required this.ptoken,
});
@override
State<OtpVerificationPage> createState() => _OtpVerificationPageState();
}
class _OtpVerificationPageState extends State<OtpVerificationPage> {
late final OtpVerificationController controller;
final List<FocusNode> _focusNodes = List.generate(6, (index) => FocusNode());
final List<TextEditingController> _textControllers =
List.generate(6, (index) => TextEditingController());
@override
void initState() {
super.initState();
controller = Get.put(OtpVerificationController(
phone: widget.phone,
deviceToken: widget.deviceToken,
token: widget.token,
));
}
@override
void dispose() {
for (var node in _focusNodes) {
node.dispose();
}
for (var controller in _textControllers) {
controller.dispose();
}
super.dispose();
}
void _onOtpChanged(String value, int index) {
if (value.isNotEmpty) {
if (index < 5) {
_focusNodes[index + 1].requestFocus();
} else {
_focusNodes[index].unfocus(); // إلغاء التركيز بعد آخر حقل
}
} else if (index > 0) {
_focusNodes[index - 1].requestFocus();
}
// تجميع نصوص كل الحقول لتكوين الرمز النهائي
controller.otpCode.value = _textControllers.map((c) => c.text).join();
}
Widget _buildOtpInputFields() {
return Directionality(
textDirection: TextDirection.ltr, // لضمان ترتيب الحقول من اليسار لليمين
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: List.generate(5, (index) {
return SizedBox(
width: 45,
height: 55,
child: TextFormField(
controller: _textControllers[index],
focusNode: _focusNodes[index],
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
maxLength: 1,
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
decoration: InputDecoration(
counterText: "",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: Theme.of(context).primaryColor, width: 2),
),
),
onChanged: (value) => _onOtpChanged(value, index),
),
);
}),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Verify OTP'.tr),
backgroundColor: Colors.transparent,
elevation: 0,
centerTitle: true,
),
backgroundColor: Colors.grey[50],
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 20),
Icon(Icons.phonelink_lock_rounded,
size: 80, color: Theme.of(context).primaryColor),
const SizedBox(height: 24),
Text(
'Verification Code'.tr,
style:
const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Text(
'${'We have sent a verification code to your mobile number:'.tr} ${widget.phone}',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.grey.shade600, fontSize: 16, height: 1.5),
),
),
const SizedBox(height: 40),
_buildOtpInputFields(),
const SizedBox(height: 40),
Obx(() => SizedBox(
width: double.infinity,
height: 50,
child: controller.isVerifying.value
? const Center(child: CircularProgressIndicator())
: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12))),
onPressed: () =>
controller.verifyOtp(widget.ptoken),
child: Text('Verify'.tr,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w600)),
),
)),
const SizedBox(height: 24),
Obx(
() => controller.canResend.value
? TextButton(
onPressed: controller.sendOtp,
child: Text('Resend Code'.tr),
)
: Text(
'${'You can resend in'.tr} ${controller.countdown.value} ${'seconds'.tr}',
style: const TextStyle(color: Colors.grey),
),
)
],
),
),
),
);
}
}