import 'package:flutter/material.dart';
import '../../../core/ai/ai_settings_store.dart';
class AiSettingsDialog extends StatefulWidget {
const AiSettingsDialog({super.key});
@override
State<AiSettingsDialog> createState() => _AiSettingsDialogState();
}
class _AiSettingsDialogState extends State<AiSettingsDialog> {
late bool enabled;
late AiProvider provider;
late final TextEditingController openAiModel;
late final TextEditingController geminiModel;
late final TextEditingController proxyUrl;
bool saving = false;
@override
void initState() {
super.initState();
final settings = AiSettingsStore.instance.settings;
enabled = settings.enabled;
provider = settings.provider;
openAiModel = TextEditingController(text: settings.openAiModel);
geminiModel = TextEditingController(text: settings.geminiModel);
proxyUrl = TextEditingController(text: settings.proxyUrl);
}
@override
void dispose() {
openAiModel.dispose();
geminiModel.dispose();
proxyUrl.dispose();
super.dispose();
}
Future<void> save() async {
final model = provider == AiProvider.openAi
? openAiModel.text.trim()
: geminiModel.text.trim();
if (enabled && model.isEmpty) {
_message('Bitte ein Modell eintragen.');
return;
}
if (enabled && proxyUrl.text.trim().isEmpty) {
_message('Bitte die sichere Server-/Proxy-URL eintragen.');
return;
}
setState(() => saving = true);
await AiSettingsStore.instance.save(
AiSettings(
enabled: enabled,
provider: provider,
openAiModel: openAiModel.text.trim(),
geminiModel: geminiModel.text.trim(),
proxyUrl: proxyUrl.text.trim(),
),
);
if (mounted) Navigator.pop(context);
}
void _message(String text) =>
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(text)));
@override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text('KI-Unterstützung'),
content: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 560),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SwitchListTile(
contentPadding: EdgeInsets.zero,
value: enabled,
onChanged: (value) => setState(() => enabled = value),
title: const Text(
'KI-Assistent aktivieren',
style: TextStyle(fontWeight: FontWeight.w700),
),
subtitle: const Text(
'Vorschläge müssen vor dem Speichern geprüft werden.',
),
),
const SizedBox(height: 12),
DropdownButtonFormField<AiProvider>(
initialValue: provider,
decoration: const InputDecoration(
labelText: 'Anbieter',
border: OutlineInputBorder(),
),
items: AiProvider.values
.map(
(value) => DropdownMenuItem(
value: value,
child: Text(value.label),
),
)
.toList(),
onChanged: (value) {
if (value == null) return;
setState(() => provider = value);
},
),
const SizedBox(height: 12),
TextField(
controller: provider == AiProvider.openAi
? openAiModel
: geminiModel,
decoration: const InputDecoration(
labelText: 'Modell',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 12),
TextField(
controller: proxyUrl,
keyboardType: TextInputType.url,
onChanged: (_) => setState(() {}),
decoration: const InputDecoration(
labelText: 'Sichere Server-/Proxy-URL',
hintText: 'https://api.meine-firma.de',
prefixIcon: Icon(Icons.dns_outlined),
border: OutlineInputBorder(),
),
),
const SizedBox(height: 10),
Text(
'Provider-Schlüssel bleiben ausschließlich auf dem Server und werden nie in der App gespeichert.',
style: Theme.of(context).textTheme.bodySmall,
),
const SizedBox(height: 14),
const Text(
'MACHWEIS sendet nur die eingegebenen Baustellennotizen sowie Kunde und Baustelle. KI-Ergebnisse werden nie automatisch unterschrieben oder abgeschlossen.',
),
],
),
),
),
actions: [
TextButton(
onPressed: saving ? null : () => Navigator.pop(context),
child: const Text('Abbrechen'),
),
FilledButton(
onPressed: saving ? null : save,
child: Text(saving ? 'Speichert …' : 'Speichern'),
),
],
);
}
}
