added wallet functionality

This commit is contained in:
Prince
2026-06-11 23:48:26 +02:00
parent ad79bf2af8
commit 2bcee59fd7
17 changed files with 1309 additions and 292 deletions

View File

@@ -165,7 +165,10 @@ class ConfirmController extends ChangeNotifier {
"Network error. Please try again or contact support",
);
} catch (e, s) {
logger.e(s);
if (kDebugMode) {
logger.e(e);
logger.e(s);
}
model.isLoading = false;
notifyListeners();
return ApiResponse.failure(

View File

@@ -134,94 +134,167 @@ class _ConfirmScreenState extends State<ConfirmScreen>
}
}
Future<String?> _showOtpBottomSheet() {
Future<String?> _showOtpBottomSheet() async {
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
final otpController = TextEditingController();
final formKey = GlobalKey<FormState>();
return showModalBottomSheet<String>(
context: context,
isDismissible: false,
enableDrag: false,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
builder: (context) {
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (sheetContext) {
return Padding(
padding: EdgeInsets.only(
left: 24,
right: 24,
top: 24,
bottom: MediaQuery.of(context).viewInsets.bottom + 24,
bottom: MediaQuery.of(sheetContext).viewInsets.bottom,
),
child: Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Container(
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(2),
),
),
),
const SizedBox(height: 20),
Text(
'OTP Verification',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary,
),
),
const SizedBox(height: 8),
Text(
'Please enter the OTP sent to your mobile/email',
style: TextStyle(fontSize: 14, color: Colors.grey.shade600),
),
const SizedBox(height: 20),
TextFormField(
controller: otpController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Enter OTP',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
),
validator: (value) {
if (value == null || value.trim().isEmpty) {
return 'Please enter the OTP';
}
return null;
},
),
const SizedBox(height: 20),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
if (formKey.currentState!.validate()) {
Navigator.of(context).pop(otpController.text.trim());
}
},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
child: Container(
decoration: BoxDecoration(
color: isDark ? const Color(0xFF1A1A2E) : Colors.white,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(24),
),
),
padding: const EdgeInsets.fromLTRB(20, 12, 20, 24),
child: Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Container(
width: 40,
height: 4,
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(2),
),
),
child: const Text(
'Submit OTP',
style: TextStyle(fontSize: 16),
),
Center(
child: Container(
width: 56,
height: 56,
decoration: BoxDecoration(
color: theme.colorScheme.primary.withValues(alpha: 0.1),
shape: BoxShape.circle,
),
child: Icon(
Icons.verified_user_rounded,
size: 28,
color: theme.colorScheme.primary,
),
),
),
),
],
const SizedBox(height: 16),
Text(
'OTP Verification',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
color: isDark ? Colors.white : Colors.black87,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
'An OTP has been sent to your registered mobile number/email. Please enter it below to proceed.',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w500,
color: Colors.grey.shade500,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 20),
TextFormField(
controller: otpController,
keyboardType: TextInputType.number,
textAlign: TextAlign.center,
maxLength: 6,
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w700,
letterSpacing: 8,
color: isDark ? Colors.white : Colors.black87,
),
decoration: InputDecoration(
counterText: '',
hintText: '------',
hintStyle: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w700,
letterSpacing: 8,
color: Colors.grey.shade400,
),
filled: true,
fillColor: isDark
? Colors.white.withValues(alpha: 0.06)
: Colors.grey.shade50,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide(
color: theme.colorScheme.primary,
width: 2,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide(color: Colors.red.shade400),
),
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 14,
),
),
validator: (value) {
if (value == null || value.trim().isEmpty) {
return 'Please enter the OTP';
}
if (value.trim().length < 4) {
return 'OTP must be at least 4 digits';
}
return null;
},
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
if (formKey.currentState?.validate() ?? false) {
Navigator.of(
sheetContext,
).pop(otpController.text.trim());
}
},
style: ElevatedButton.styleFrom(
backgroundColor: theme.colorScheme.primary,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
elevation: 0,
),
child: const Text(
'Submit',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w700,
),
),
),
),
],
),
),
),
);