Language Changes
This commit is contained in:
215
lib/features/fund_transfer/screens/tpin_set_screen.dart
Normal file
215
lib/features/fund_transfer/screens/tpin_set_screen.dart
Normal file
@@ -0,0 +1,215 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kmobile/api/services/auth_service.dart';
|
||||
import 'package:kmobile/di/injection.dart';
|
||||
|
||||
enum TPinMode { set, confirm }
|
||||
|
||||
class TpinSetScreen extends StatefulWidget {
|
||||
const TpinSetScreen({super.key});
|
||||
|
||||
@override
|
||||
State<TpinSetScreen> createState() => _TpinSetScreenState();
|
||||
}
|
||||
|
||||
class _TpinSetScreenState extends State<TpinSetScreen> {
|
||||
TPinMode _mode = TPinMode.set;
|
||||
final List<String> _tpin = [];
|
||||
String? _initialTpin;
|
||||
String? _errorText;
|
||||
|
||||
void addDigit(String digit) {
|
||||
if (_tpin.length < 6) {
|
||||
setState(() {
|
||||
_tpin.add(digit);
|
||||
_errorText = null;
|
||||
});
|
||||
if (_tpin.length == 6) {
|
||||
_handleComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deleteDigit() {
|
||||
if (_tpin.isNotEmpty) {
|
||||
setState(() {
|
||||
_tpin.removeLast();
|
||||
_errorText = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _handleComplete() async {
|
||||
final pin = _tpin.join();
|
||||
if (_mode == TPinMode.set) {
|
||||
setState(() {
|
||||
_initialTpin = pin;
|
||||
_tpin.clear();
|
||||
_mode = TPinMode.confirm;
|
||||
});
|
||||
} else if (_mode == TPinMode.confirm) {
|
||||
if (_initialTpin == pin) {
|
||||
final authService = getIt<AuthService>();
|
||||
try {
|
||||
await authService.setTpin(pin);
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_errorText = "Failed to set TPIN. Please try again.";
|
||||
_tpin.clear();
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!mounted) return;
|
||||
// Show success dialog before popping
|
||||
await showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (ctx) => AlertDialog(
|
||||
shape:
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(18)),
|
||||
title: const Column(
|
||||
children: [
|
||||
Icon(Icons.check_circle, color: Colors.green, size: 60),
|
||||
SizedBox(height: 12),
|
||||
Text('Success!', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
],
|
||||
),
|
||||
content: const Text(
|
||||
'Your TPIN was set up successfully.',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(ctx).pop();
|
||||
},
|
||||
child: const Text('OK', style: TextStyle(fontSize: 16)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
} else {
|
||||
setState(() {
|
||||
_errorText = "Pins do not match. Try again.";
|
||||
_tpin.clear();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildPinDots() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: List.generate(6, (index) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.all(8),
|
||||
width: 15,
|
||||
height: 15,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: index < _tpin.length ? Colors.black : Colors.grey[400],
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildNumberPad() {
|
||||
List<List<String>> keys = [
|
||||
['1', '2', '3'],
|
||||
['4', '5', '6'],
|
||||
['7', '8', '9'],
|
||||
['Enter', '0', '<']
|
||||
];
|
||||
|
||||
return Column(
|
||||
children: keys.map((row) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: row.map((key) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (key == '<') {
|
||||
deleteDigit();
|
||||
} else if (key == 'Enter') {
|
||||
if (_tpin.length == 6) {
|
||||
_handleComplete();
|
||||
} else {
|
||||
setState(() {
|
||||
_errorText = "Please enter 6 digits";
|
||||
});
|
||||
}
|
||||
} else if (key.isNotEmpty) {
|
||||
addDigit(key);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: 70,
|
||||
height: 70,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.grey[200],
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: key == 'Enter'
|
||||
? const Icon(Icons.check)
|
||||
: Text(
|
||||
key == '<' ? '⌫' : key,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: key == 'Enter' ? Colors.blue : Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
String getTitle() {
|
||||
switch (_mode) {
|
||||
case TPinMode.set:
|
||||
return "Set your new TPIN";
|
||||
case TPinMode.confirm:
|
||||
return "Confirm your new TPIN";
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Set TPIN')),
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
const Spacer(),
|
||||
const Icon(Icons.lock_outline, size: 60, color: Colors.blue),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
getTitle(),
|
||||
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
buildPinDots(),
|
||||
if (_errorText != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(_errorText!,
|
||||
style: const TextStyle(color: Colors.red)),
|
||||
),
|
||||
const Spacer(),
|
||||
buildNumberPad(),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user