import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import '../../../app/theme.dart';
import '../../../core/ai/ai_settings_store.dart';
import '../../../core/auth/auth_store.dart';
import '../../../core/auth/industry_profiles.dart';
import '../../../core/sync/master_data_sync_card.dart';
import '../data/company_store.dart';
import '../../employees/presentation/employees_screen.dart';
import '../../employees/data/employee_store.dart';
import 'ai_settings_dialog.dart';
class ProfileScreen extends StatelessWidget {
const ProfileScreen({super.key, this.authStore});
final AuthStore? authStore;
Future<void> logout(BuildContext context, AuthStore auth) async {
final confirmed = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Abmelden?'),
content: const Text(
'Die Anmeldung wird sicher von diesem Gerät entfernt. Lokal gespeicherte Stammdaten bleiben erhalten.',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('Abbrechen'),
),
FilledButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('Abmelden'),
),
],
),
);
if (confirmed == true) await auth.logout();
}
Future<void> editCompany(BuildContext context) async {
final value = await showDialog<CompanyProfile>(
context: context,
builder: (_) =>
_CompanyEditDialog(initial: CompanyStore.instance.profile),
);
if (value != null && context.mounted) {
try {
await CompanyStore.instance.save(value);
} on Object {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'Die Firmendaten konnten nicht gespeichert werden. Bitte versuche es erneut.',
),
),
);
}
}
}
}
@override
Widget build(BuildContext context) => ListenableBuilder(
listenable: CompanyStore.instance,
builder: (context, _) {
final company = CompanyStore.instance.profile;
final auth = authStore ?? AuthStore.instance;
final canManageCompany =
auth.session == null ||
auth.session!.role == 'owner' ||
auth.session!.role == 'office';
final mobileAuth =
!kIsWeb &&
(defaultTargetPlatform == TargetPlatform.iOS ||
defaultTargetPlatform == TargetPlatform.android);
return SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 760),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Firma & Profil',
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 8),
Text(
auth.session == null
? 'Lokale Unternehmensdaten'
: 'Angemeldet als ${auth.session!.email}',
style: Theme.of(context).textTheme.bodyLarge,
),
],
),
),
FilledButton.icon(
onPressed: canManageCompany
? () => editCompany(context)
: null,
icon: const Icon(Icons.edit_outlined),
label: const Text('Bearbeiten'),
),
],
),
const SizedBox(height: 28),
Card(
child: Column(
children: [
ListTile(
contentPadding: const EdgeInsets.all(20),
leading: const CircleAvatar(
backgroundColor: AppColors.forest,
child: Icon(
Icons.business_rounded,
color: Colors.white,
),
),
title: Text(
company.name.isEmpty
? 'Firmendaten noch nicht hinterlegt'
: company.name,
style: const TextStyle(fontWeight: FontWeight.w800),
),
subtitle: Text(
company.owner.isEmpty
? 'Kein Ansprechpartner hinterlegt'
: company.owner,
),
),
const Divider(height: 1),
_InfoTile(
icon: Icons.mail_outline_rounded,
title: 'Kontakt',
value: [
company.email,
company.phone,
].where((value) => value.isNotEmpty).join(' · '),
),
const Divider(height: 1),
_InfoTile(
icon: Icons.location_on_outlined,
title: 'Firmenanschrift',
value: company.address,
),
const Divider(height: 1),
_InfoTile(
icon: Icons.receipt_long_outlined,
title: 'Steuernummer',
value: company.taxNumber,
),
const Divider(height: 1),
_InfoTile(
icon: Icons.notes_rounded,
title: 'Berichtshinweis',
value: company.reportFooter,
),
],
),
),
if (auth.session != null) ...[
const SizedBox(height: 20),
Card(
child: ListTile(
onTap: canManageCompany
? () => _editIndustryProfiles(context, auth)
: null,
contentPadding: const EdgeInsets.all(20),
leading: const Icon(
Icons.category_outlined,
color: AppColors.green,
),
title: const Text(
'Branchenprofile',
style: TextStyle(fontWeight: FontWeight.w700),
),
subtitle: Text(
auth.session!.industryProfiles.isEmpty
? 'Keine Branchenprofile hinterlegt.'
: auth.session!.industryProfiles
.map((code) {
for (final item in industryProfileOptions) {
if (item.code == code) return item.label;
}
return code;
})
.join(' · '),
),
),
),
],
const SizedBox(height: 20),
if (!kIsWeb) ...[
const MasterDataSyncCard(),
const SizedBox(height: 20),
],
ListenableBuilder(
listenable: EmployeeStore.instance,
builder: (context, _) => Card(
child: ListTile(
onTap: () => Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (_) => const EmployeesScreen(),
),
),
contentPadding: const EdgeInsets.all(20),
leading: const Icon(
Icons.groups_outlined,
color: AppColors.green,
),
title: const Text(
'Mitarbeiter & Rollen',
style: TextStyle(fontWeight: FontWeight.w700),
),
subtitle: Text(
'${EmployeeStore.instance.activeEmployees.length} aktive Mitarbeiter',
),
trailing: const Icon(Icons.chevron_right_rounded),
),
),
),
const SizedBox(height: 20),
ListenableBuilder(
listenable: AiSettingsStore.instance,
builder: (context, _) {
final settings = AiSettingsStore.instance.settings;
return Card(
child: ListTile(
onTap: () => showDialog<void>(
context: context,
builder: (_) => const AiSettingsDialog(),
),
contentPadding: const EdgeInsets.all(20),
leading: const Icon(
Icons.auto_awesome_outlined,
color: AppColors.green,
),
title: const Text(
'KI-Unterstützung',
style: TextStyle(fontWeight: FontWeight.w700),
),
subtitle: Text(
settings.enabled
? '${settings.provider.label} · ${settings.activeModel}${settings.usesProxy ? ' · Proxy' : ''}'
: 'Deaktiviert · OpenAI oder Google Gemini einrichten',
),
trailing: const Icon(Icons.chevron_right_rounded),
),
);
},
),
const SizedBox(height: 20),
const Card(
child: ListTile(
contentPadding: EdgeInsets.all(20),
leading: Icon(
Icons.offline_bolt_outlined,
color: AppColors.green,
),
title: Text(
'Offline bereit',
style: TextStyle(fontWeight: FontWeight.w700),
),
subtitle: Text(
'Firmendaten, Kunden, Aufträge und Nachweise werden lokal gespeichert.',
),
),
),
if (mobileAuth && auth.isSignedIn) ...[
const SizedBox(height: 20),
Card(
child: ListTile(
onTap: () => logout(context, auth),
contentPadding: const EdgeInsets.all(20),
leading: const Icon(
Icons.logout_rounded,
color: Colors.red,
),
title: const Text(
'Abmelden',
style: TextStyle(fontWeight: FontWeight.w700),
),
subtitle: const Text(
'Anmeldedaten sicher von diesem Gerät entfernen',
),
),
),
],
],
),
),
),
);
},
);
Future<void> _editIndustryProfiles(
BuildContext context,
AuthStore auth,
) async {
final selected = {...auth.session!.industryProfiles};
final result = await showDialog<List<String>>(
context: context,
builder: (_) => StatefulBuilder(
builder: (context, setState) => AlertDialog(
title: const Text('Branchenprofile bearbeiten'),
content: SingleChildScrollView(
child: Column(
children: industryProfileOptions
.map(
(item) => CheckboxListTile(
value: selected.contains(item.code),
title: Text(item.label),
onChanged: (value) => setState(
() => value == true
? selected.add(item.code)
: selected.remove(item.code),
),
),
)
.toList(),
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Abbrechen'),
),
FilledButton(
onPressed: selected.isEmpty
? null
: () => Navigator.pop(context, selected.toList()),
child: const Text('Speichern'),
),
],
),
),
);
if (result != null) await auth.updateIndustryProfiles(result);
}
}
class _CompanyEditDialog extends StatefulWidget {
const _CompanyEditDialog({required this.initial});
final CompanyProfile initial;
@override
State<_CompanyEditDialog> createState() => _CompanyEditDialogState();
}
class _CompanyEditDialogState extends State<_CompanyEditDialog> {
late String name;
late String owner;
late String email;
late String phone;
late String address;
late String taxNumber;
late String footer;
@override
void initState() {
super.initState();
name = widget.initial.name;
owner = widget.initial.owner;
email = widget.initial.email;
phone = widget.initial.phone;
address = widget.initial.address;
taxNumber = widget.initial.taxNumber;
footer = widget.initial.reportFooter;
}
CompanyProfile get _value => CompanyProfile(
name: name.trim(),
owner: owner.trim(),
email: email.trim(),
phone: phone.trim(),
address: address.trim(),
taxNumber: taxNumber.trim(),
reportFooter: footer.trim(),
);
Widget _field(
String value,
String label,
IconData icon,
ValueChanged<String> onChanged, {
int lines = 1,
}) => TextFormField(
initialValue: value,
minLines: lines,
maxLines: lines,
onChanged: onChanged,
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(icon),
alignLabelWithHint: lines > 1,
border: const OutlineInputBorder(),
),
);
@override
Widget build(BuildContext context) => AlertDialog(
title: const Text('Firmendaten bearbeiten'),
content: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 560),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_field(name, 'Firmenname', Icons.business_outlined, (value) {
setState(() => name = value);
}),
const SizedBox(height: 12),
_field(
owner,
'Inhaber / Ansprechpartner',
Icons.person_outline_rounded,
(value) => owner = value,
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: _field(
email,
'E-Mail',
Icons.mail_outline_rounded,
(value) => email = value,
),
),
const SizedBox(width: 12),
Expanded(
child: _field(
phone,
'Telefon',
Icons.phone_outlined,
(value) => phone = value,
),
),
],
),
const SizedBox(height: 12),
_field(
address,
'Firmenanschrift',
Icons.location_on_outlined,
(value) => address = value,
lines: 2,
),
const SizedBox(height: 12),
_field(
taxNumber,
'Steuernummer (optional)',
Icons.receipt_long_outlined,
(value) => taxNumber = value,
),
const SizedBox(height: 12),
_field(
footer,
'Hinweis auf Berichten',
Icons.notes_rounded,
(value) => footer = value,
lines: 2,
),
],
),
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Abbrechen'),
),
FilledButton(
onPressed: name.trim().isEmpty
? null
: () => Navigator.pop(context, _value),
child: const Text('Speichern'),
),
],
);
}
class _InfoTile extends StatelessWidget {
const _InfoTile({
required this.icon,
required this.title,
required this.value,
});
final IconData icon;
final String title;
final String value;
@override
Widget build(BuildContext context) => ListTile(
leading: Icon(icon),
title: Text(title),
subtitle: Text(value.isEmpty ? 'Noch nicht hinterlegt' : value),
);
}
