124 lines
3.5 KiB
Dart
124 lines
3.5 KiB
Dart
import 'package:flutter/material.dart';
|
||
import '../services/api_service.dart';
|
||
import '../services/security_service.dart';
|
||
import 'security_screen.dart';
|
||
|
||
class SettingsScreen extends StatefulWidget {
|
||
const SettingsScreen({super.key, required this.apiService});
|
||
|
||
final ApiService apiService;
|
||
|
||
@override
|
||
State<SettingsScreen> createState() => _SettingsScreenState();
|
||
}
|
||
|
||
class _SettingsScreenState extends State<SettingsScreen> {
|
||
final _controller = TextEditingController();
|
||
bool _testing = false;
|
||
String? _message;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_load();
|
||
}
|
||
|
||
Future<void> _load() async {
|
||
_controller.text = await widget.apiService.getBaseUrl();
|
||
if (mounted) setState(() {});
|
||
}
|
||
|
||
Future<void> _save() async {
|
||
await widget.apiService.setBaseUrl(_controller.text);
|
||
if (mounted) {
|
||
setState(() => _message = 'URL enregistrée localement.');
|
||
}
|
||
}
|
||
|
||
Future<void> _test() async {
|
||
setState(() {
|
||
_testing = true;
|
||
_message = null;
|
||
});
|
||
|
||
try {
|
||
await _save();
|
||
final ok = await widget.apiService.healthCheck();
|
||
setState(() => _message = ok ? 'Connexion OK.' : 'Réponse inattendue du serveur.');
|
||
} catch (e) {
|
||
setState(() => _message = 'Erreur : $e');
|
||
} finally {
|
||
if (mounted) setState(() => _testing = false);
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
appBar: AppBar(
|
||
title: const Text('Paramètres'),
|
||
),
|
||
body: ListView(
|
||
padding: const EdgeInsets.all(16),
|
||
children: [
|
||
const Text(
|
||
'URL du backend FIN65',
|
||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w700),
|
||
),
|
||
const SizedBox(height: 8),
|
||
const Text(
|
||
'Émulateur Android : http://10.0.2.2:8000\nTéléphone réel : http://IP_DU_PC:8000',
|
||
),
|
||
const SizedBox(height: 16),
|
||
TextField(
|
||
controller: _controller,
|
||
decoration: const InputDecoration(
|
||
labelText: 'URL API',
|
||
border: OutlineInputBorder(),
|
||
hintText: 'http://192.168.1.25:8000',
|
||
),
|
||
keyboardType: TextInputType.url,
|
||
),
|
||
const SizedBox(height: 12),
|
||
FilledButton(
|
||
onPressed: _testing ? null : _test,
|
||
child: Text(_testing ? 'Test...' : 'Enregistrer et tester'),
|
||
),
|
||
if (_message != null) ...[
|
||
const SizedBox(height: 16),
|
||
Text(_message!),
|
||
],
|
||
const SizedBox(height: 24),
|
||
Card(
|
||
child: ListTile(
|
||
leading: const Icon(Icons.lock),
|
||
title: const Text('Sécurité'),
|
||
subtitle: const Text('Activer, changer ou désactiver le verrouillage PIN.'),
|
||
trailing: const Icon(Icons.chevron_right),
|
||
onTap: () {
|
||
Navigator.of(context).push(
|
||
MaterialPageRoute(
|
||
builder: (_) => SecurityScreen(
|
||
securityService: SecurityService(),
|
||
),
|
||
),
|
||
);
|
||
},
|
||
),
|
||
),
|
||
const SizedBox(height: 12),
|
||
const Card(
|
||
child: Padding(
|
||
padding: EdgeInsets.all(12),
|
||
child: Text(
|
||
'L’URL est stockée dans la base SQLite locale du mobile. '
|
||
'Elle reste donc disponible même sans backend.',
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|