138 lines
4.6 KiB
Dart
138 lines
4.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
import '../profile_manager.dart';
|
|
|
|
class ProfileLoginScreen extends StatefulWidget {
|
|
const ProfileLoginScreen({super.key});
|
|
|
|
@override
|
|
State<ProfileLoginScreen> createState() => _ProfileLoginScreenState();
|
|
}
|
|
|
|
class _ProfileLoginScreenState extends State<ProfileLoginScreen> {
|
|
final _pinController = TextEditingController();
|
|
final _confirmController = TextEditingController();
|
|
bool _isCreating = false;
|
|
String _error = '';
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
// Check if we need to create a PIN
|
|
final profile = Provider.of<ProfileManager>(context, listen: false);
|
|
// Note: profile status might update async, so we rely on Consumer in AuthWrapper usually,
|
|
// but here we are inside the screen.
|
|
// Actually, AuthWrapper decides if we show this screen.
|
|
// If we are here, it means !isAuthenticated.
|
|
// We check hasPin to decide mode.
|
|
}
|
|
|
|
void _handleSubmit() async {
|
|
final profile = Provider.of<ProfileManager>(context, listen: false);
|
|
|
|
if (_pinController.text.length < 4) {
|
|
setState(() => _error = 'PIN must be at least 4 digits');
|
|
return;
|
|
}
|
|
|
|
if (!profile.hasPin) {
|
|
// Creating Request
|
|
if (!_isCreating) {
|
|
// Ask for confirmation
|
|
setState(() {
|
|
_isCreating = true;
|
|
_error = '';
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (_pinController.text != _confirmController.text) {
|
|
setState(() => _error = 'PINs do not match');
|
|
return;
|
|
}
|
|
|
|
await profile.setPin(_pinController.text);
|
|
} else {
|
|
// Unlocking
|
|
final success = await profile.unlock(_pinController.text);
|
|
if (!success) {
|
|
setState(() => _error = 'Incorrect PIN');
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// Watch hasPin to react if it changes (rare here but good practice)
|
|
final hasPin = Provider.of<ProfileManager>(context).hasPin;
|
|
|
|
return Scaffold(
|
|
body: Center(
|
|
child: Container(
|
|
constraints: const BoxConstraints(maxWidth: 400),
|
|
padding: const EdgeInsets.all(32),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
const Icon(Icons.lock_outline, size: 64, color: Colors.blue),
|
|
const SizedBox(height: 24),
|
|
Text(
|
|
hasPin ? 'Enter Master PIN' : (_isCreating ? 'Confirm Master PIN' : 'Create Master PIN'),
|
|
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
hasPin
|
|
? 'Unlock your secure profiles'
|
|
: 'Protect your store credentials',
|
|
style: const TextStyle(color: Colors.grey),
|
|
),
|
|
const SizedBox(height: 32),
|
|
TextField(
|
|
controller: _pinController,
|
|
obscureText: true,
|
|
keyboardType: TextInputType.number,
|
|
decoration: const InputDecoration(
|
|
labelText: 'PIN',
|
|
prefixIcon: Icon(Icons.password),
|
|
),
|
|
onSubmitted: (_) => _isCreating ? null : _handleSubmit(), // If confirming, focus next or submit
|
|
),
|
|
if (_isCreating) ...[
|
|
const SizedBox(height: 16),
|
|
TextField(
|
|
controller: _confirmController,
|
|
obscureText: true,
|
|
keyboardType: TextInputType.number,
|
|
decoration: const InputDecoration(
|
|
labelText: 'Confirm PIN',
|
|
prefixIcon: Icon(Icons.check),
|
|
),
|
|
onSubmitted: (_) => _handleSubmit(),
|
|
),
|
|
],
|
|
if (_error.isNotEmpty) ...[
|
|
const SizedBox(height: 16),
|
|
Text(_error, style: const TextStyle(color: Colors.red)),
|
|
],
|
|
const SizedBox(height: 32),
|
|
SizedBox(
|
|
width: double.infinity,
|
|
child: ElevatedButton(
|
|
onPressed: _handleSubmit,
|
|
style: ElevatedButton.styleFrom(
|
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
backgroundColor: Colors.blue,
|
|
foregroundColor: Colors.white,
|
|
),
|
|
child: Text(hasPin ? 'Unlock' : (_isCreating ? 'Save PIN' : 'Next')),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|