256 lines
8.3 KiB
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(),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
} |