showStylizedOtpDialog function

Future<String?> showStylizedOtpDialog(
  1. BuildContext context
)

Implementation

Future<String?> showStylizedOtpDialog(BuildContext context) async {
  final List<TextEditingController> controllers =
      List.generate(5, (_) => TextEditingController());
  final List<FocusNode> focusNodes = List.generate(5, (_) => FocusNode());
  String otp = '';

  return showDialog<String>(
    context: context,
    barrierDismissible: false,
    builder: (context) => AlertDialog(
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
      title: const Text("Entrez le code OTP"),
      content: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          const Text("Un code OTP vous a été envoyé."),
          const SizedBox(height: 12),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: List.generate(5, (index) {
              return SizedBox(
                width: 45,
                child: Focus(
                  onKeyEvent: (FocusNode node, KeyEvent event) {
                    if (event is KeyDownEvent) {
                      if (event.logicalKey == LogicalKeyboardKey.arrowLeft &&
                          index > 0) {
                        FocusScope.of(context)
                            .requestFocus(focusNodes[index - 1]);
                        return KeyEventResult.handled;
                      }

                      if (event.logicalKey == LogicalKeyboardKey.arrowRight &&
                          index < 4) {
                        FocusScope.of(context)
                            .requestFocus(focusNodes[index + 1]);
                        return KeyEventResult.handled;
                      }

                      if (event.logicalKey == LogicalKeyboardKey.backspace &&
                          controllers[index].text.isEmpty &&
                          index > 0) {
                        FocusScope.of(context)
                            .requestFocus(focusNodes[index - 1]);
                        controllers[index - 1].clear();
                        return KeyEventResult.handled;
                      }
                    }
                    return KeyEventResult.ignored;
                  },
                  child: TextFormField(
                    controller: controllers[index],
                    focusNode: focusNodes[index],
                    maxLength: 1,
                    textAlign: TextAlign.center,
                    keyboardType: TextInputType.number,
                    inputFormatters: [
                      FilteringTextInputFormatter.digitsOnly,
                    ],
                    style: const TextStyle(fontSize: 20),
                    decoration: InputDecoration(
                      counterText: "",
                      enabledBorder: OutlineInputBorder(
                        borderSide: const BorderSide(
                            color: Color(0xFFD45D00), width: 2),
                        borderRadius: BorderRadius.circular(8),
                      ),
                      focusedBorder: OutlineInputBorder(
                        borderSide: const BorderSide(
                            color: Color(0xFFD45D00), width: 2),
                        borderRadius: BorderRadius.circular(8),
                      ),
                    ),
                    onChanged: (value) {
                      if (value.isNotEmpty) {
                        controllers[index].text = value.characters.last;
                        controllers[index].selection =
                            TextSelection.collapsed(offset: 1);

                        if (index < 4) {
                          FocusScope.of(context)
                              .requestFocus(focusNodes[index + 1]);
                        } else {
                          FocusScope.of(context).unfocus();
                        }
                      }
                    },
                  ),
                ),
              );
            }),
          ),
        ],
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.of(context).pop(null),
          child: const Text("Annuler"),
        ),
        ElevatedButton(
          style: ElevatedButton.styleFrom(
            backgroundColor: const Color(0xFFD45D00),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(12),
            ),
          ),
          onPressed: () {
            otp = controllers.map((c) => c.text).join();
            Navigator.of(context).pop(otp);
          },
          child: const Text("Valider", style: TextStyle(color: Colors.white)),
        ),
      ],
    ),
  );
}