refactor: Projektstruktur in app/ und backend/ aufgeteilt

This commit is contained in:
2026-03-24 15:06:44 +01:00
parent 5f5d5995c5
commit 2673ef658d
449 changed files with 28551 additions and 167 deletions

225
app/lib/settings_view.dart Normal file
View File

@@ -0,0 +1,225 @@
import 'package:flutter/material.dart';
import 'l10n/app_localizations.dart';
import 'app_state.dart';
/// Supported languages with their display names and flag emojis
class LanguageOption {
final String code;
final String name;
final String flagEmoji;
const LanguageOption({
required this.code,
required this.name,
required this.flagEmoji,
});
}
class SettingsView extends StatefulWidget {
const SettingsView({super.key});
@override
State<SettingsView> createState() => _SettingsViewState();
}
class _SettingsViewState extends State<SettingsView> {
late String _selectedLanguageCode;
final AppState _appState = AppState();
@override
void initState() {
super.initState();
_selectedLanguageCode = _appState.languageCode;
}
void _onLanguageSelected(String languageCode) async {
setState(() {
_selectedLanguageCode = languageCode;
});
// Save language preference
await _appState.setLanguage(languageCode);
// Show confirmation snackbar
_showLanguageChangedSnackBar(languageCode);
}
void _showLanguageChangedSnackBar(String languageCode) {
final l10n = AppLocalizations.of(context);
// Get the language name from the corresponding localization
String languageName;
String flagEmoji;
switch (languageCode) {
case 'de':
languageName = 'Deutsch';
flagEmoji = '🇩🇪';
break;
case 'en':
languageName = 'English';
flagEmoji = '🇬🇧';
break;
case 'es':
languageName = 'Español';
flagEmoji = '🇪🇸';
break;
case 'fr':
languageName = 'Français';
flagEmoji = '🇫🇷';
break;
case 'pl':
languageName = 'Polski';
flagEmoji = '🇵🇱';
break;
case 'ru':
languageName = 'Русский';
flagEmoji = '🇷🇺';
break;
case 'tr':
languageName = 'Türkçe';
flagEmoji = '🇹🇷';
break;
case 'et':
languageName = 'Eesti';
flagEmoji = '🇪🇪';
break;
case 'lv':
languageName = 'Latviešu';
flagEmoji = '🇱🇻';
break;
case 'lt':
languageName = 'Lietuvių';
flagEmoji = '🇱🇹';
break;
default:
languageName = languageCode;
flagEmoji = '🌐';
}
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'${l10n.languageChanged}: $flagEmoji $languageName',
),
duration: const Duration(seconds: 2),
backgroundColor: Colors.green,
),
);
}
/// Get all available language options with their localized names
List<LanguageOption> _getLanguageOptions() {
return [
const LanguageOption(code: 'de', name: 'Deutsch', flagEmoji: '🇩🇪'),
const LanguageOption(code: 'en', name: 'English', flagEmoji: '🇬🇧'),
const LanguageOption(code: 'es', name: 'Español', flagEmoji: '🇪🇸'),
const LanguageOption(code: 'fr', name: 'Français', flagEmoji: '🇫🇷'),
const LanguageOption(code: 'pl', name: 'Polski', flagEmoji: '🇵🇱'),
const LanguageOption(code: 'ru', name: 'Русский', flagEmoji: '🇷🇺'),
const LanguageOption(code: 'tr', name: 'Türkçe', flagEmoji: '🇹🇷'),
const LanguageOption(code: 'et', name: 'Eesti', flagEmoji: '🇪🇪'),
const LanguageOption(code: 'lv', name: 'Latviešu', flagEmoji: '🇱🇻'),
const LanguageOption(code: 'lt', name: 'Lietuvių', flagEmoji: '🇱🇹'),
];
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context);
final languageOptions = _getLanguageOptions();
return Scaffold(
appBar: AppBar(
title: Text(l10n.settings),
backgroundColor: Colors.deepPurple[100],
),
body: ListView(
children: [
// Language Selection Section
Padding(
padding: const EdgeInsets.fromLTRB(16, 24, 16, 8),
child: Text(
l10n.language.toUpperCase(),
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Colors.grey,
letterSpacing: 1.2,
),
),
),
const Divider(height: 1),
// Language List
...languageOptions.map((language) {
final isSelected = language.code == _selectedLanguageCode;
return Column(
children: [
ListTile(
leading: Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(20),
),
child: Center(
child: Text(
language.flagEmoji,
style: const TextStyle(fontSize: 24),
),
),
),
title: Text(
language.name,
style: TextStyle(
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
color: isSelected ? Colors.deepPurple : Colors.black87,
),
),
trailing: isSelected
? const Icon(
Icons.check_circle,
color: Colors.deepPurple,
)
: const Icon(
Icons.circle_outlined,
color: Colors.grey,
),
onTap: () => _onLanguageSelected(language.code),
selected: isSelected,
selectedTileColor: Colors.deepPurple.withValues(alpha: 0.05),
),
const Divider(height: 1, indent: 72),
],
);
}),
// App Info Section
Padding(
padding: const EdgeInsets.fromLTRB(16, 32, 16, 8),
child: Text(
l10n.appInfo,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Colors.grey,
letterSpacing: 1.2,
),
),
),
const Divider(height: 1),
ListTile(
leading: Icon(
Icons.info_outline,
color: Colors.grey[600],
),
title: Text(l10n.version),
subtitle: const Text('0.9.2'),
),
const Divider(height: 1, indent: 72),
],
),
);
}
}