marco.pms.mobileapp/lib/view/auth/mpin_screen.dart
Vaibhav Surve 25dfcf3e08 feat: Add MPIN authentication and OTP login screens
- Implemented MPINAuthScreen for generating and entering MPIN.
- Created MPINScreen for user interaction with MPIN input.
- Developed OTPLoginScreen for OTP verification process.
- Added request demo bottom sheet with organization form.
- Enhanced DashboardScreen to check MPIN status and prompt user to generate MPIN if not set.
2025-06-10 10:04:18 +05:30

151 lines
4.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:marco/controller/auth/mpin_controller.dart';
import 'package:marco/helpers/theme/app_theme.dart';
import 'package:marco/helpers/widgets/my_button.dart';
import 'package:marco/helpers/widgets/my_spacing.dart';
import 'package:marco/helpers/widgets/my_text.dart';
import 'package:marco/helpers/widgets/my_text_style.dart';
class MPINScreen extends StatelessWidget {
const MPINScreen({super.key});
@override
Widget build(BuildContext context) {
final controller = Get.put(MPINController());
return Obx(() {
final isNewUser = controller.isNewUser.value;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MyText.titleMedium(
isNewUser ? 'Generate MPIN' : 'Enter MPIN',
fontWeight: 600,
),
MySpacing.height(4),
MyText.bodySmall(
isNewUser
? 'Set your 6-digit MPIN for quick login.'
: 'Enter your 6-digit MPIN to continue.',
),
MySpacing.height(24),
_buildMPINForm(controller, isNewUser),
MySpacing.height(32),
_buildSubmitButton(controller, isNewUser),
MySpacing.height(16),
_buildFooterOptions(controller, isNewUser),
],
);
});
}
Widget _buildMPINForm(MPINController controller, bool isNewUser) {
return Form(
key: controller.formKey,
child: Column(
children: [
_buildDigitRow(controller, isRetype: false),
if (isNewUser) ...[
MySpacing.height(20),
MyText.bodySmall(
'Retype MPIN',
fontWeight: 600,
color: theme.colorScheme.onBackground.withOpacity(0.7),
),
MySpacing.height(8),
_buildDigitRow(controller, isRetype: true),
],
],
),
);
}
Widget _buildDigitRow(MPINController controller, {required bool isRetype}) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(6, (index) {
return _buildDigitBox(controller, index, isRetype);
}),
);
}
Widget _buildDigitBox(MPINController controller, int index, bool isRetype) {
final textController = isRetype
? controller.retypeControllers[index]
: controller.digitControllers[index];
final focusNode = isRetype
? controller.retypeFocusNodes[index]
: controller.focusNodes[index];
return Container(
margin: MySpacing.x(4),
width: 40,
child: TextFormField(
controller: textController,
focusNode: focusNode,
obscureText: true,
maxLength: 1,
textAlign: TextAlign.center,
style: MyTextStyle.titleLarge(fontWeight: 700),
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
onChanged: (value) =>
controller.onDigitChanged(value, index, isRetype: isRetype),
decoration: InputDecoration(
counterText: '',
filled: true,
fillColor: theme.cardColor,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide.none,
),
),
),
);
}
Widget _buildSubmitButton(MPINController controller, bool isNewUser) {
return Center(
child: Obx(() {
return MyButton.rounded(
onPressed:
controller.isLoading.value ? null : controller.onSubmitMPIN,
elevation: 2,
padding: MySpacing.xy(24, 16),
borderRadiusAll: 16,
backgroundColor: Colors.blueAccent,
child: controller.isLoading.value
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
color: Colors.white, strokeWidth: 2),
)
: MyText.labelMedium(
isNewUser ? 'Generate MPIN' : 'Submit MPIN',
fontWeight: 600,
color: theme.colorScheme.onPrimary,
),
);
}),
);
}
Widget _buildFooterOptions(MPINController controller, bool isNewUser) {
return Center(
child: TextButton(
onPressed:
isNewUser ? controller.switchToEnterMPIN : controller.onForgotMPIN,
child: MyText.bodySmall(
isNewUser ? 'Back to Enter MPIN' : 'Generate MPIN?',
color: Colors.blueAccent,
fontWeight: 600,
),
),
);
}
}