Files
MarcWieland 411ede36ef init
2026-07-26 23:58:12 +02:00

507 lines
16 KiB
Dart

import 'package:flutter/material.dart';
import '../services/database_service.dart';
import '../theme/app_theme.dart';
import '../widgets/system_status_dialog.dart';
class MoreScreen extends StatefulWidget {
const MoreScreen({super.key});
@override
State<MoreScreen> createState() => _MoreScreenState();
}
class _MoreScreenState extends State<MoreScreen> {
bool _notificationsEnabled = true;
SystemStatusResult? _statusResult;
bool _isCheckingStatus = true;
@override
void initState() {
super.initState();
_checkStatus();
}
Future<void> _checkStatus() async {
final status = await DatabaseService.testConnection();
if (!mounted) return;
setState(() {
_statusResult = status;
_isCheckingStatus = false;
});
}
void _openSystemStatusDetails() async {
setState(() {
_isCheckingStatus = true;
});
final status = await DatabaseService.testConnection();
if (!mounted) return;
setState(() {
_statusResult = status;
_isCheckingStatus = false;
});
showDialog(
context: context,
builder: (context) => SystemStatusDialog(status: status),
);
}
@override
Widget build(BuildContext context) {
final isConnected = _statusResult?.isConnected ?? DatabaseService.isInitialized;
return Scaffold(
backgroundColor: AppTheme.backgroundLight,
body: Column(
children: [
// Dark Navy Top Header Bar (matches Mockup Mehr_Page.png)
Container(
color: AppTheme.primaryDark,
child: SafeArea(
bottom: false,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
child: Row(
children: [
IconButton(
icon: const Icon(Icons.menu, color: Colors.white),
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Menü geöffnet')),
);
},
),
const Expanded(
child: Text(
'Mehr',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
IconButton(
icon: const CircleAvatar(
radius: 14,
backgroundColor: Colors.white,
child: Icon(Icons.person, color: AppTheme.primaryDark, size: 18),
),
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Profil geöffnet')),
);
},
),
],
),
),
),
),
// Scrollable Settings Content Body
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Profile Header Card
_buildProfileCard(context),
const SizedBox(height: 16),
// Systemstatus Card (Interactive Supabase Connection Status)
_buildSystemStatusCard(context, isConnected),
const SizedBox(height: 20),
// Gruppe: Allgemein
_buildSectionTitle('Gruppe: Allgemein'),
const SizedBox(height: 8),
Card(
child: Column(
children: [
_buildSwitchTile(
icon: Icons.notifications_outlined,
title: 'Benachrichtigungen',
value: _notificationsEnabled,
onChanged: (val) {
setState(() {
_notificationsEnabled = val;
});
},
),
const Divider(height: 1, color: AppTheme.cardBorder),
_buildValueTile(
icon: Icons.language_outlined,
title: 'App-Sprache',
value: 'Deutsch',
onTap: () {},
),
const Divider(height: 1, color: AppTheme.cardBorder),
_buildTile(
icon: Icons.shield_outlined,
title: 'Sicherheit & Datenschutz',
onTap: () {},
),
],
),
),
const SizedBox(height: 20),
// Gruppe: Verwaltung
_buildSectionTitle('Gruppe: Verwaltung'),
const SizedBox(height: 8),
Card(
child: Column(
children: [
_buildTile(
icon: Icons.event_available_outlined,
title: 'Urlaub & Abwesenheit',
badgeText: 'HR',
onTap: () {},
),
const Divider(height: 1, color: AppTheme.cardBorder),
_buildTile(
icon: Icons.build_outlined,
title: 'Meine Werkzeug-Ausstattung',
onTap: () {},
),
],
),
),
const SizedBox(height: 20),
// Gruppe: App-Info
_buildSectionTitle('Gruppe: App-Info'),
const SizedBox(height: 8),
Card(
child: Column(
children: [
_buildTile(
icon: Icons.info_outline,
title: 'Impressum',
onTap: () {},
),
const Divider(height: 1, color: AppTheme.cardBorder),
_buildTile(
icon: Icons.article_outlined,
title: 'Datenschutz',
onTap: () {},
),
const Divider(height: 1, color: AppTheme.cardBorder),
_buildTile(
icon: Icons.star_outline,
title: 'Feedback zur App',
onTap: () {},
),
],
),
),
const SizedBox(height: 24),
// Logout Button
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Abgemeldet')),
);
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFDC2626),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 14),
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: const Text(
'Abmelden',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(height: 16),
],
),
),
),
],
),
);
}
Widget _buildProfileCard(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Row(
children: [
CircleAvatar(
radius: 26,
backgroundColor: AppTheme.primaryBlue,
child: const Icon(
Icons.person,
color: Colors.white,
size: 30,
),
),
const SizedBox(width: 14),
const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Max Müller',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.bold,
color: AppTheme.textPrimary,
),
),
SizedBox(height: 2),
Text(
'Monteur / ID: M-01023',
style: TextStyle(
fontSize: 13,
color: AppTheme.textSecondary,
),
),
],
),
],
),
const SizedBox(height: 14),
OutlinedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Profil bearbeiten')),
);
},
style: OutlinedButton.styleFrom(
foregroundColor: AppTheme.textPrimary,
side: const BorderSide(color: AppTheme.cardBorder),
minimumSize: const Size(double.infinity, 40),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
child: const Text(
'Profil bearbeiten',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
),
],
),
),
);
}
Widget _buildSystemStatusCard(BuildContext context, bool isConnected) {
final statusText = _isCheckingStatus
? 'Verbindung wird geprüft...'
: (isConnected ? 'Verbunden: Supabase' : 'Offline / Mock-Modus');
final statusColor = _isCheckingStatus
? Colors.orange[700]
: (isConnected ? Colors.green[800] : Colors.red[800]);
final dotColor = _isCheckingStatus
? Colors.orange
: (isConnected ? Colors.green[600] : Colors.red);
return Card(
child: InkWell(
onTap: _openSystemStatusDetails,
borderRadius: BorderRadius.circular(16),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Systemstatus',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: AppTheme.textPrimary,
),
),
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: AppTheme.lightBlueBg,
shape: BoxShape.circle,
),
child: _isCheckingStatus
? const SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2, color: AppTheme.primaryBlue),
)
: const Icon(
Icons.bolt,
color: AppTheme.primaryBlue,
size: 20,
),
),
],
),
const SizedBox(height: 8),
Row(
children: [
Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: dotColor,
shape: BoxShape.circle,
),
),
const SizedBox(width: 8),
Text(
statusText,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: statusColor,
),
),
],
),
const SizedBox(height: 4),
Text(
_statusResult != null && _statusResult!.latencyMs > 0
? 'Latenz: ${_statusResult!.latencyMs} ms • supabase.marc-wieland.de'
: 'Tippen für erweiterte Verbindungsdetails',
style: const TextStyle(
fontSize: 12,
color: AppTheme.textSecondary,
),
),
],
),
),
),
);
}
Widget _buildSectionTitle(String title) {
return Text(
title,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: AppTheme.textPrimary,
),
);
}
Widget _buildTile({
required IconData icon,
required String title,
String? badgeText,
required VoidCallback onTap,
}) {
return ListTile(
leading: Icon(icon, color: AppTheme.primaryBlue, size: 22),
title: Text(
title,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: AppTheme.textPrimary,
),
),
trailing: badgeText != null
? Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
decoration: BoxDecoration(
color: AppTheme.lightBlueBg,
borderRadius: BorderRadius.circular(6),
border: Border.all(color: AppTheme.primaryBlue.withAlpha(50)),
),
child: Text(
'↔ $badgeText',
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: AppTheme.primaryBlue,
),
),
)
: null,
onTap: onTap,
);
}
Widget _buildValueTile({
required IconData icon,
required String title,
required String value,
required VoidCallback onTap,
}) {
return ListTile(
leading: Icon(icon, color: AppTheme.primaryBlue, size: 22),
title: Text(
title,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: AppTheme.textPrimary,
),
),
trailing: Text(
value,
style: const TextStyle(
fontSize: 13,
color: AppTheme.textSecondary,
),
),
onTap: onTap,
);
}
Widget _buildSwitchTile({
required IconData icon,
required String title,
required bool value,
required ValueChanged<bool> onChanged,
}) {
return ListTile(
leading: Icon(icon, color: AppTheme.primaryBlue, size: 22),
title: Text(
title,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: AppTheme.textPrimary,
),
),
trailing: Switch.adaptive(
value: value,
activeThumbColor: AppTheme.primaryBlue,
onChanged: onChanged,
),
);
}
}