environment_monitoring_app/lib/screens/settings/submission_preferences_settings.dart

256 lines
8.3 KiB
Dart

// lib/screens/settings/submission_preferences_settings.dart
import 'package:flutter/material.dart';
import 'package:environment_monitoring_app/services/user_preferences_service.dart';
class _ModuleSettings {
bool isApiEnabled;
bool isFtpEnabled;
List<Map<String, dynamic>> apiConfigs;
List<Map<String, dynamic>> ftpConfigs;
_ModuleSettings({
this.isApiEnabled = true,
this.isFtpEnabled = true,
required this.apiConfigs,
required this.ftpConfigs,
});
}
class SubmissionPreferencesSettingsScreen extends StatefulWidget {
const SubmissionPreferencesSettingsScreen({super.key});
@override
State<SubmissionPreferencesSettingsScreen> createState() =>
_SubmissionPreferencesSettingsScreenState();
}
class _SubmissionPreferencesSettingsScreenState
extends State<SubmissionPreferencesSettingsScreen> {
final UserPreferencesService _preferencesService = UserPreferencesService();
bool _isLoadingSettings = true;
bool _isSaving = false;
final Map<String, _ModuleSettings> _moduleSettings = {};
final List<Map<String, String>> _configurableModules = [
{'key': 'marine_tarball', 'name': 'Marine Tarball'},
{'key': 'marine_in_situ', 'name': 'Marine In-Situ'},
{'key': 'marine_investigative', 'name': 'Marine Investigative'},
{'key': 'marine_report', 'name': 'Marine Report'},
{'key': 'river_in_situ', 'name': 'River In-Situ'},
{'key': 'river_triennial', 'name': 'River Triennial'},
{'key': 'river_investigative', 'name': 'River Investigative'},
{'key': 'air_installation', 'name': 'Air Installation'},
{'key': 'air_collection', 'name': 'Air Collection'},
];
@override
void initState() {
super.initState();
_loadAllModuleSettings();
}
Future<void> _loadAllModuleSettings() async {
setState(() => _isLoadingSettings = true);
for (var module in _configurableModules) {
final moduleKey = module['key']!;
final prefs = await _preferencesService.getModulePreference(moduleKey);
final apiConfigsWithPrefs =
await _preferencesService.getAllApiConfigsWithModulePreferences(moduleKey);
final ftpConfigsWithPrefs =
await _preferencesService.getAllFtpConfigsWithModulePreferences(moduleKey);
_moduleSettings[moduleKey] = _ModuleSettings(
isApiEnabled: prefs?['is_api_enabled'] ?? true, // Fallback to true if null
isFtpEnabled: prefs?['is_ftp_enabled'] ?? true, // Fallback to true if null
apiConfigs: apiConfigsWithPrefs,
ftpConfigs: ftpConfigsWithPrefs,
);
}
if (mounted) {
setState(() => _isLoadingSettings = false);
}
}
Future<void> _saveAllModuleSettings() async {
setState(() => _isSaving = true);
try {
for (var module in _configurableModules) {
final moduleKey = module['key']!;
final settings = _moduleSettings[moduleKey]!;
await _preferencesService.saveModulePreference(
moduleName: moduleKey,
isApiEnabled: settings.isApiEnabled,
isFtpEnabled: settings.isFtpEnabled,
);
await _preferencesService.saveApiLinksForModule(
moduleKey, settings.apiConfigs);
await _preferencesService.saveFtpLinksForModule(
moduleKey, settings.ftpConfigs);
}
_showSnackBar('Submission preferences saved successfully.', isError: false);
} catch (e) {
_showSnackBar('Failed to save settings: $e', isError: true);
} finally {
if (mounted) {
setState(() => _isSaving = false);
}
}
}
void _showSnackBar(String message, {bool isError = false}) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor:
isError ? Theme.of(context).colorScheme.error : Colors.green,
),
);
}
}
Widget _buildSectionHeader(BuildContext context, String title) {
return Padding(
padding: const EdgeInsets.fromLTRB(8.0, 24.0, 8.0, 16.0),
child: Text(
title,
style: Theme.of(context)
.textTheme
.headlineSmall
?.copyWith(fontWeight: FontWeight.bold),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Submission Preferences"),
actions: [
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: _isSaving
? const Center(
child: SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(color: Colors.white)))
: IconButton(
icon: const Icon(Icons.save),
onPressed:
_isLoadingSettings ? null : _saveAllModuleSettings,
tooltip: 'Save Submission Preferences',
),
)
],
),
body: _isLoadingSettings
? const Center(
child: Padding(
padding: EdgeInsets.all(16.0),
child: CircularProgressIndicator()))
: ListView(
padding: const EdgeInsets.all(16.0),
children: [
_buildSectionHeader(context, "Module Settings"),
Card(
margin: EdgeInsets.zero,
child: ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: _configurableModules.length,
itemBuilder: (context, index) {
final module = _configurableModules[index];
final settings = _moduleSettings[module['key']];
if (settings == null) return const SizedBox.shrink();
return _buildModulePreferenceTile(
module['name']!, module['key']!, settings);
},
),
),
],
),
);
}
Widget _buildModulePreferenceTile(
String title, String moduleKey, _ModuleSettings settings) {
return ExpansionTile(
title: Text(title, style: const TextStyle(fontWeight: FontWeight.bold)),
initiallyExpanded: false, // Start collapsed
children: [
SwitchListTile(
title: const Text('Enable API Submission'),
value: settings.isApiEnabled,
onChanged: (value) => setState(() => settings.isApiEnabled = value),
),
if (settings.isApiEnabled)
_buildDestinationList(
'API Destinations', settings.apiConfigs, 'api_config_id'),
const Divider(),
SwitchListTile(
title: const Text('Enable FTP Submission'),
value: settings.isFtpEnabled,
onChanged: (value) => setState(() => settings.isFtpEnabled = value),
),
if (settings.isFtpEnabled)
_buildDestinationList(
'FTP Destinations', settings.ftpConfigs, 'ftp_config_id'),
],
);
}
Widget _buildDestinationList(
String title, List<Map<String, dynamic>> configs, String idKey) {
if (configs.isEmpty) {
return const ListTile(
dense: true,
title:
Center(child: Text('No destinations configured. Sync to fetch.')),
);
}
return Padding(
padding: const EdgeInsets.fromLTRB(16.0, 8.0, 16.0, 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 16.0, bottom: 8.0),
child: Text(title, style: Theme.of(context).textTheme.titleMedium),
),
...configs.map((config) {
bool isFtp = config.containsKey('ftp_module');
String subtitleText;
if (isFtp) {
subtitleText =
'Module: ${config['ftp_module'] ?? 'N/A'} | Host: ${config['ftp_host'] ?? 'N/A'}';
} else {
subtitleText = config['api_url'] ?? 'No URL';
}
return CheckboxListTile(
title: Text(config['config_name'] ?? 'Unnamed'),
subtitle:
Text(subtitleText, style: const TextStyle(fontSize: 12)),
value: config['is_enabled'] ?? false,
onChanged: (bool? value) {
setState(() {
config['is_enabled'] = value ?? false;
});
},
dense: true,
);
}).toList(),
],
),
);
}
}