bonpoint/mobile/lib/features/parent/widgets/pin_entry_card.dart
Julien Martin b8faf3b4df Ajoute l'espace parent : PIN, grille de règles, historique et annulation.
Phase 2 du MVP Flutter : vérification PIN locale, application des règles par famille, suivi des mouvements et correction avec plancher à 0.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 12:24:42 +02:00

92 lines
2.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class PinEntryCard extends StatelessWidget {
const PinEntryCard({
super.key,
required this.pinController,
required this.obscurePin,
required this.isLoading,
required this.onToggleObscure,
required this.onSubmit,
this.error,
});
final TextEditingController pinController;
final bool obscurePin;
final bool isLoading;
final VoidCallback onToggleObscure;
final VoidCallback onSubmit;
final String? error;
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const CircleAvatar(
radius: 36,
backgroundColor: Color(0xFF667EEA),
child: Icon(Icons.family_restroom, color: Colors.white, size: 36),
),
const SizedBox(height: 16),
Text(
'Entrez votre code PIN',
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 20),
TextField(
controller: pinController,
obscureText: obscurePin,
keyboardType: TextInputType.number,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 24, letterSpacing: 8),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(8),
],
decoration: InputDecoration(
hintText: '••••',
suffixIcon: IconButton(
icon: Icon(
obscurePin ? Icons.visibility : Icons.visibility_off,
),
onPressed: onToggleObscure,
),
),
onSubmitted: (_) => onSubmit(),
),
if (error != null) ...[
const SizedBox(height: 12),
Text(
error!,
style: TextStyle(color: Colors.red.shade700),
textAlign: TextAlign.center,
),
],
const SizedBox(height: 20),
SizedBox(
width: double.infinity,
child: FilledButton(
onPressed: isLoading ? null : onSubmit,
child: isLoading
? const SizedBox(
width: 22,
height: 22,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Text('Connexion'),
),
),
],
),
),
);
}
}