Initial upload: fin65-mobile
This commit is contained in:
@@ -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.',
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user