import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../../core/l10n/app_strings.dart'; import '../../../core/providers/auth_provider.dart'; import '../../../core/providers/locale_provider.dart'; import '../../../core/router/app_router.dart'; import '../../../core/theme/app_theme.dart'; import '../../../models/tenant.dart'; import '../../shared/tenant_team_screen.dart'; import '../connections/lab_connections_screen.dart'; class LabSettingsScreen extends ConsumerWidget { const LabSettingsScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final auth = ref.watch(authProvider); final s = ref.watch(stringsProvider); final profile = auth.profile; final membership = auth.activeTenant; final tenant = membership?.tenant; final canEdit = membership?.isAdmin ?? false; return Scaffold( appBar: AppBar(title: Text(s.settings)), body: ListView( padding: const EdgeInsets.all(16), children: [ // User card _SectionHeader(title: s.userInfo), _UserCard(profile: profile), const SizedBox(height: 20), // Lab info _SectionHeader( title: s.labInfo, action: canEdit ? IconButton( icon: const Icon(Icons.edit_outlined, size: 18, color: AppColors.accent), tooltip: s.edit, onPressed: () => _showEditSheet(context, ref, tenant, s), ) : null, ), _InfoCard(children: [ _InfoTile( icon: Icons.science_outlined, label: s.labName, value: tenant?.companyName ?? '-', ), _InfoTile( icon: Icons.payments_outlined, label: s.currency, value: tenant?.defaultCurrency ?? 'TRY', ), _InfoTileBadge( icon: Icons.circle_outlined, label: s.status, value: tenant?.status == 'active' ? s.active : (tenant?.status ?? '-'), badgeColor: AppColors.success, badgeBg: AppColors.successBg, ), _InfoTile( icon: Icons.star_outline, label: s.role, value: _roleLabel(membership?.role, s), ), ]), const SizedBox(height: 20), // Connections if (membership?.showConnections ?? false) ...[ _SectionHeader(title: s.connections), _InfoCard(children: [ _NavTile( icon: Icons.link_rounded, iconColor: AppColors.inProgress, iconBg: AppColors.inProgressBg, title: s.clinicConnections, subtitle: s.clinicConnectionsSub, onTap: () => Navigator.push( context, MaterialPageRoute( builder: (_) => const LabConnectionsScreen()), ), ), ]), const SizedBox(height: 20), ], // Other memberships if (auth.memberships.length > 1) ...[ _SectionHeader(title: s.otherMemberships), _InfoCard(children: [ for (final m in auth.memberships.where((m) => m.id != membership?.id)) _NavTile( icon: Icons.switch_account_outlined, iconColor: AppColors.inProgress, iconBg: AppColors.inProgressBg, title: m.tenant.companyName, subtitle: _tenantKindLabel(m.tenant.kind, s), onTap: () { ref.read(authProvider.notifier).setActiveTenant(m); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(s.tenantSelected(m.tenant.companyName))), ); }, ), ]), const SizedBox(height: 20), ], // Team management + Reports if (membership?.canManageUsers ?? false) ...[ _SectionHeader(title: s.management), _InfoCard(children: [ _NavTile( icon: Icons.group_outlined, iconColor: AppColors.inProgress, iconBg: AppColors.inProgressBg, title: s.team, subtitle: s.teamSub, onTap: () => Navigator.push( context, MaterialPageRoute( builder: (_) => const TenantTeamScreen()), ), ), _NavTile( icon: Icons.discount_outlined, iconColor: AppColors.success, iconBg: AppColors.successBg, title: s.discounts, subtitle: s.discountsSub, onTap: () => context.push(routeLabDiscounts), ), _NavTile( icon: Icons.bar_chart_rounded, iconColor: AppColors.accent, iconBg: AppColors.inProgressBg, title: s.reports, subtitle: s.reportsSub, onTap: () => context.push(routeLabReports), ), _NavTile( icon: Icons.auto_awesome_outlined, iconColor: const Color(0xFF7C3AED), iconBg: const Color(0xFFF3E8FF), title: s.aiAssistant, subtitle: s.aiAssistantSub, onTap: () => context.push(routeLabAi), ), ]), const SizedBox(height: 20), ], // Preferences (language) _SectionHeader(title: s.preferences), _InfoCard(children: [ _NavTile( icon: Icons.language_outlined, iconColor: AppColors.accent, iconBg: AppColors.inProgressBg, title: s.appLanguage, subtitle: _currentLanguageLabel(ref.watch(localeProvider).languageCode, s), onTap: () => _showLanguagePicker(context, ref, s), ), ]), const SizedBox(height: 20), // Sign out _SignOutCard(ref: ref, s: s), const SizedBox(height: 32), const Center( child: Text('DLS — Dental Lab System', style: TextStyle(fontSize: 12, color: AppColors.textMuted)), ), const SizedBox(height: 8), ], ), ); } void _showEditSheet(BuildContext context, WidgetRef ref, Tenant? tenant, AppStrings s) { if (tenant == null) return; showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (_) => _EditTenantSheet( tenant: tenant, s: s, onSave: (name, currency) async { await ref.read(authProvider.notifier).updateTenantInfo( tenantId: tenant.id, companyName: name, defaultCurrency: currency, ); }, ), ); } void _showLanguagePicker(BuildContext context, WidgetRef ref, AppStrings s) { showModalBottomSheet( context: context, backgroundColor: Colors.transparent, builder: (_) => _LanguagePickerSheet(s: s, ref: ref), ); } static String _tenantKindLabel(TenantKind? kind, AppStrings s) => switch (kind) { TenantKind.clinic => s.tenantKindClinic, TenantKind.lab => s.tenantKindLab, null => '-', }; static String _currentLanguageLabel(String code, AppStrings s) => switch (code) { 'en' => s.languageEnglish, 'ru' => s.languageRussian, 'ar' => s.languageArabic, 'de' => s.languageGerman, _ => s.languageTurkish, }; static String _roleLabel(TenantRole? role, AppStrings s) => switch (role) { TenantRole.owner => s.roleOwner, TenantRole.admin => s.roleAdmin, TenantRole.technician => s.roleTechnician, TenantRole.delivery => s.roleDelivery, TenantRole.finance => s.roleFinance, TenantRole.doctor => s.roleDoctor, TenantRole.member => s.roleMember, null => '-', }; } // ── Language picker sheet ───────────────────────────────────────────────────── class _LanguagePickerSheet extends ConsumerWidget { const _LanguagePickerSheet({required this.s, required this.ref}); final AppStrings s; final WidgetRef ref; @override Widget build(BuildContext context, WidgetRef _) { final currentLocale = ref.watch(localeProvider); final options = [ ('tr', '🇹🇷', s.languageTurkish), ('en', '🇬🇧', s.languageEnglish), ('ru', '🇷🇺', s.languageRussian), ('ar', '🇸🇦', s.languageArabic), ('de', '🇩🇪', s.languageGerman), ]; return Container( decoration: const BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Container( width: 40, height: 4, decoration: BoxDecoration( color: AppColors.border, borderRadius: BorderRadius.circular(2), ), ), ), const SizedBox(height: 16), Text( s.languageSelection, style: const TextStyle( fontSize: 17, fontWeight: FontWeight.w700, color: AppColors.textPrimary, ), ), const SizedBox(height: 12), for (final (code, flag, label) in options) ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 4), leading: Text(flag, style: const TextStyle(fontSize: 24)), title: Text( label, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.w500, color: AppColors.textPrimary, ), ), trailing: currentLocale.languageCode == code ? const Icon(Icons.check_circle_rounded, color: AppColors.accent) : null, onTap: () { ref.read(localeProvider.notifier).setLocale(Locale(code)); ref.read(authProvider.notifier).updateLanguage(code); Navigator.pop(context); }, ), SizedBox(height: MediaQuery.paddingOf(context).bottom + 4), ], ), ); } } // ── Edit sheet ──────────────────────────────────────────────────────────────── class _EditTenantSheet extends StatefulWidget { const _EditTenantSheet({ required this.tenant, required this.s, required this.onSave, }); final Tenant tenant; final AppStrings s; final Future Function(String companyName, String currency) onSave; @override State<_EditTenantSheet> createState() => _EditTenantSheetState(); } class _EditTenantSheetState extends State<_EditTenantSheet> { late final TextEditingController _nameController; late String _selectedCurrency; bool _saving = false; static const _currencies = [ ('TRY', '₺', 'Türk Lirası'), ('USD', '\$', 'US Dollar'), ('EUR', '€', 'Euro'), ('GBP', '£', 'British Pound'), ('AED', 'د.إ', 'UAE Dirham'), ]; @override void initState() { super.initState(); _nameController = TextEditingController(text: widget.tenant.companyName); _selectedCurrency = widget.tenant.defaultCurrency; } @override void dispose() { _nameController.dispose(); super.dispose(); } Future _submit() async { final name = _nameController.text.trim(); if (name.isEmpty) return; setState(() => _saving = true); final navigator = Navigator.of(context); final messenger = ScaffoldMessenger.of(context); try { await widget.onSave(name, _selectedCurrency); navigator.pop(); } catch (e) { messenger.showSnackBar( SnackBar(content: Text('${widget.s.errorPrefix}: $e'))); } finally { if (mounted) setState(() => _saving = false); } } @override Widget build(BuildContext context) { final s = widget.s; return Padding( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: Container( decoration: const BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Container( width: 40, height: 4, decoration: BoxDecoration( color: AppColors.border, borderRadius: BorderRadius.circular(2)), ), ), const SizedBox(height: 16), Text(s.editLabInfo, style: const TextStyle( fontSize: 17, fontWeight: FontWeight.w700, color: AppColors.textPrimary)), const SizedBox(height: 16), TextFormField( controller: _nameController, decoration: InputDecoration( labelText: s.labName, hintText: s.labNameHint, ), textCapitalization: TextCapitalization.words, ), const SizedBox(height: 14), Text(s.currency, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: AppColors.textSecondary)), const SizedBox(height: 8), DropdownButtonFormField( value: _selectedCurrency, decoration: InputDecoration( contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: AppColors.border)), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: AppColors.border)), ), items: [ for (final (code, symbol, name) in _currencies) DropdownMenuItem( value: code, child: Text('$symbol $name ($code)', style: const TextStyle(fontSize: 14)), ), ], onChanged: (v) { if (v != null) setState(() => _selectedCurrency = v); }, ), const SizedBox(height: 20), if (_saving) const Center( child: CircularProgressIndicator(color: AppColors.accent)) else FilledButton( onPressed: _submit, style: FilledButton.styleFrom( minimumSize: const Size(double.infinity, 48)), child: Text(s.save), ), SizedBox(height: MediaQuery.paddingOf(context).bottom + 4), ], ), ), ); } } // ── Reusable UI pieces ──────────────────────────────────────────────────────── class _UserCard extends StatelessWidget { const _UserCard({required this.profile}); final dynamic profile; @override Widget build(BuildContext context) { final displayName = (profile?.displayName?.isNotEmpty == true) ? profile!.displayName as String : 'Kullanıcı'; final initial = (profile?.displayName?.isNotEmpty == true ? (profile!.displayName as String)[0] : (profile?.email as String?)?[0] ?? '?') .toUpperCase(); return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(16), border: Border.all(color: AppColors.border), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.05), blurRadius: 12, offset: const Offset(0, 4)) ], ), child: Row( children: [ Container( width: 56, height: 56, decoration: BoxDecoration( color: AppColors.inProgressBg, borderRadius: BorderRadius.circular(14)), child: Center( child: Text(initial, style: const TextStyle( fontSize: 22, fontWeight: FontWeight.w700, color: AppColors.inProgress)), ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(displayName, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.textPrimary)), const SizedBox(height: 2), Text(profile?.email as String? ?? '', style: const TextStyle( fontSize: 13, color: AppColors.textSecondary)), ], ), ), ], ), ); } } class _SectionHeader extends StatelessWidget { const _SectionHeader({required this.title, this.action}); final String title; final Widget? action; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(bottom: 8), child: Row( children: [ Expanded( child: Text( title, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: AppColors.accent, letterSpacing: 0.3), ), ), if (action != null) action!, ], ), ); } } class _InfoCard extends StatelessWidget { const _InfoCard({required this.children}); final List children; @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(16), border: Border.all(color: AppColors.border), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.05), blurRadius: 12, offset: const Offset(0, 4)) ], ), child: Column( children: [ for (int i = 0; i < children.length; i++) ...[ children[i], if (i < children.length - 1) const Divider( height: 1, indent: 16, endIndent: 16, color: AppColors.border), ], ], ), ); } } class _InfoTile extends StatelessWidget { const _InfoTile( {required this.icon, required this.label, required this.value}); final IconData icon; final String label; final String value; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( children: [ Icon(icon, size: 18, color: AppColors.textSecondary), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: const TextStyle( fontSize: 11, color: AppColors.textMuted)), const SizedBox(height: 2), Text(value, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.textPrimary)), ], ), ), ], ), ); } } class _InfoTileBadge extends StatelessWidget { const _InfoTileBadge({ required this.icon, required this.label, required this.value, required this.badgeColor, required this.badgeBg, }); final IconData icon; final String label; final String value; final Color badgeColor; final Color badgeBg; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( children: [ Icon(icon, size: 18, color: AppColors.textSecondary), const SizedBox(width: 12), Expanded( child: Text(label, style: const TextStyle( fontSize: 11, color: AppColors.textMuted)), ), Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: badgeBg, borderRadius: BorderRadius.circular(8), ), child: Text(value, style: TextStyle( color: badgeColor, fontSize: 12, fontWeight: FontWeight.w600)), ), ], ), ); } } class _NavTile extends StatelessWidget { const _NavTile({ required this.icon, required this.iconColor, required this.iconBg, required this.title, required this.onTap, this.subtitle, }); final IconData icon; final Color iconColor; final Color iconBg; final String title; final String? subtitle; final VoidCallback onTap; @override Widget build(BuildContext context) { return ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 2), leading: Container( width: 36, height: 36, decoration: BoxDecoration( color: iconBg, borderRadius: BorderRadius.circular(9)), child: Icon(icon, color: iconColor, size: 18), ), title: Text(title, style: const TextStyle( fontWeight: FontWeight.w600, color: AppColors.textPrimary)), subtitle: subtitle != null ? Text(subtitle!, style: const TextStyle(color: AppColors.textSecondary)) : null, trailing: const Icon(Icons.chevron_right, color: AppColors.textSecondary), onTap: onTap, ); } } class _SignOutCard extends StatelessWidget { const _SignOutCard({required this.ref, required this.s}); final WidgetRef ref; final AppStrings s; @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(16), border: Border.all(color: AppColors.cancelledBg), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.05), blurRadius: 12, offset: const Offset(0, 4)) ], ), child: ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 2), leading: Container( width: 36, height: 36, decoration: BoxDecoration( color: AppColors.cancelledBg, borderRadius: BorderRadius.circular(9)), child: const Icon(Icons.logout, color: AppColors.cancelled, size: 18), ), title: Text(s.signOut, style: const TextStyle( color: AppColors.cancelled, fontWeight: FontWeight.w600)), onTap: () async { final confirmed = await showDialog( context: context, builder: (ctx) => AlertDialog( title: Text(s.signOutTitle), content: Text(s.signOutConfirm), actions: [ TextButton( onPressed: () => Navigator.pop(ctx, false), child: Text(s.cancel)), FilledButton( onPressed: () => Navigator.pop(ctx, true), style: FilledButton.styleFrom( backgroundColor: AppColors.cancelled), child: Text(s.signOut), ), ], ), ); if (confirmed == true) { await ref.read(authProvider.notifier).signOut(); } }, ), ); } }