- Onglet Paramètres dans l'admin avec 3 sections (Email, Personnalisation, Avancé) - Service ConfigurationService (GET config, PATCH bulk, POST test-smtp) - Bouton Sauvegarder et bouton Tester SMTP (sauvegarde avant test) - Endpoints api_config pour configuration Closes #15 Co-authored-by: Cursor <cursoragent@cursor.com>
140 lines
4.6 KiB
Dart
140 lines
4.6 KiB
Dart
import 'dart:convert';
|
|
import 'package:http/http.dart' as http;
|
|
import 'api/api_config.dart';
|
|
import 'api/tokenService.dart';
|
|
|
|
/// Réponse GET /configuration (liste complète)
|
|
class ConfigItem {
|
|
final String cle;
|
|
final String? valeur;
|
|
final String type;
|
|
final String? categorie;
|
|
final String? description;
|
|
|
|
ConfigItem({
|
|
required this.cle,
|
|
this.valeur,
|
|
required this.type,
|
|
this.categorie,
|
|
this.description,
|
|
});
|
|
|
|
factory ConfigItem.fromJson(Map<String, dynamic> json) {
|
|
return ConfigItem(
|
|
cle: json['cle'] as String,
|
|
valeur: json['valeur'] as String?,
|
|
type: json['type'] as String? ?? 'string',
|
|
categorie: json['categorie'] as String?,
|
|
description: json['description'] as String?,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Réponse GET /configuration/:category (objet clé -> { value, type, description })
|
|
class ConfigValueItem {
|
|
final dynamic value;
|
|
final String type;
|
|
final String? description;
|
|
|
|
ConfigValueItem({required this.value, required this.type, this.description});
|
|
|
|
factory ConfigValueItem.fromJson(Map<String, dynamic> json) {
|
|
return ConfigValueItem(
|
|
value: json['value'],
|
|
type: json['type'] as String? ?? 'string',
|
|
description: json['description'] as String?,
|
|
);
|
|
}
|
|
}
|
|
|
|
class ConfigurationService {
|
|
static Future<Map<String, String>> _headers() async {
|
|
final token = await TokenService.getToken();
|
|
return token != null
|
|
? ApiConfig.authHeaders(token)
|
|
: Map<String, String>.from(ApiConfig.headers);
|
|
}
|
|
|
|
/// GET /api/v1/configuration/setup/status
|
|
static Future<bool> getSetupStatus() async {
|
|
final response = await http.get(
|
|
Uri.parse('${ApiConfig.baseUrl}${ApiConfig.configurationSetupStatus}'),
|
|
headers: await _headers(),
|
|
);
|
|
if (response.statusCode != 200) return true;
|
|
final data = jsonDecode(response.body);
|
|
return data['data']?['setupCompleted'] as bool? ?? true;
|
|
}
|
|
|
|
/// GET /api/v1/configuration (toutes les configs)
|
|
static Future<List<ConfigItem>> getAll() async {
|
|
final response = await http.get(
|
|
Uri.parse('${ApiConfig.baseUrl}${ApiConfig.configuration}'),
|
|
headers: await _headers(),
|
|
);
|
|
if (response.statusCode != 200) {
|
|
throw Exception(
|
|
(jsonDecode(response.body) as Map)['message'] ?? 'Erreur chargement configuration',
|
|
);
|
|
}
|
|
final data = jsonDecode(response.body);
|
|
final list = data['data'] as List<dynamic>? ?? [];
|
|
return list.map((e) => ConfigItem.fromJson(e as Map<String, dynamic>)).toList();
|
|
}
|
|
|
|
/// GET /api/v1/configuration/:category
|
|
static Future<Map<String, ConfigValueItem>> getByCategory(String category) async {
|
|
final response = await http.get(
|
|
Uri.parse('${ApiConfig.baseUrl}${ApiConfig.configuration}/$category'),
|
|
headers: await _headers(),
|
|
);
|
|
if (response.statusCode != 200) {
|
|
throw Exception(
|
|
(jsonDecode(response.body) as Map)['message'] ?? 'Erreur chargement configuration',
|
|
);
|
|
}
|
|
final data = jsonDecode(response.body);
|
|
final map = data['data'] as Map<String, dynamic>? ?? {};
|
|
return map.map((k, v) => MapEntry(k, ConfigValueItem.fromJson(v as Map<String, dynamic>)));
|
|
}
|
|
|
|
/// PATCH /api/v1/configuration/bulk
|
|
static Future<void> updateBulk(Map<String, dynamic> body) async {
|
|
final response = await http.patch(
|
|
Uri.parse('${ApiConfig.baseUrl}${ApiConfig.configurationBulk}'),
|
|
headers: await _headers(),
|
|
body: jsonEncode(body),
|
|
);
|
|
if (response.statusCode != 200) {
|
|
final err = jsonDecode(response.body) as Map;
|
|
throw Exception(err['message'] ?? 'Erreur lors de la sauvegarde');
|
|
}
|
|
}
|
|
|
|
/// POST /api/v1/configuration/test-smtp
|
|
static Future<String> testSmtp(String testEmail) async {
|
|
final response = await http.post(
|
|
Uri.parse('${ApiConfig.baseUrl}${ApiConfig.configurationTestSmtp}'),
|
|
headers: await _headers(),
|
|
body: jsonEncode({'testEmail': testEmail}),
|
|
);
|
|
final data = jsonDecode(response.body) as Map;
|
|
if (response.statusCode == 200 && data['success'] == true) {
|
|
return data['message'] as String? ?? 'Test SMTP réussi.';
|
|
}
|
|
throw Exception(data['error'] ?? data['message'] ?? 'Échec du test SMTP');
|
|
}
|
|
|
|
/// POST /api/v1/configuration/setup/complete (après première config)
|
|
static Future<void> completeSetup() async {
|
|
final response = await http.post(
|
|
Uri.parse('${ApiConfig.baseUrl}${ApiConfig.configurationSetupComplete}'),
|
|
headers: await _headers(),
|
|
);
|
|
if (response.statusCode != 200) {
|
|
final err = jsonDecode(response.body) as Map;
|
|
throw Exception(err['message'] ?? 'Erreur finalisation configuration');
|
|
}
|
|
}
|
|
}
|