Initial upload: fin65-mobile

This commit is contained in:
Abderrahim-Mouhcine
2026-08-16 19:59:55 +01:00
commit 46558a5ec8
242 changed files with 16334 additions and 0 deletions
+123
View File
@@ -0,0 +1,123 @@
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.',
),
),
),
],
),
);
}
}