import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import '../../../../core/utils/responsive_utils.dart'; import '../../../../shared/widgets/app_card.dart'; import '../../../../shared/widgets/app_dropdown.dart'; import '../../../../shared/widgets/app_form_toggle_field.dart'; import '../../../../shared/widgets/app_searchable_dropdown.dart'; import '../../../../shared/widgets/page_header.dart'; import '../../domain/entities/app_settings.dart'; class SettingsPageLayout extends StatelessWidget { const SettingsPageLayout({ super.key, required this.title, this.subtitle, required this.child, this.actions, }); final String title; final String? subtitle; final Widget child; final List? actions; @override Widget build(BuildContext context) { final theme = Theme.of(context); return Material( color: theme.colorScheme.surface, child: SingleChildScrollView( padding: const EdgeInsets.all(24), child: Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 900), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ IconButton( icon: const Icon(Icons.arrow_back), tooltip: 'Back to Settings', onPressed: () => context.go('/settings'), ), Expanded( child: PageHeader( title: title, subtitle: subtitle, actions: actions, ), ), ], ), child, ], ), ), ), ), ); } } class SettingsFormCard extends StatelessWidget { const SettingsFormCard({ super.key, required this.title, required this.children, this.subtitle, }); final String title; final String? subtitle; final List children; @override Widget build(BuildContext context) { return AppCard( child: Padding( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: Theme.of(context).textTheme.titleMedium), if (subtitle != null) ...[ const SizedBox(height: 4), Text( subtitle!, style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ], const SizedBox(height: 20), ...children, ], ), ), ); } } class SettingsSwitchTile extends StatelessWidget { const SettingsSwitchTile({ super.key, required this.title, required this.value, required this.onChanged, this.subtitle, }); final String title; final String? subtitle; final bool value; final ValueChanged onChanged; @override Widget build(BuildContext context) { return AppFormToggleField( label: title, subtitle: subtitle, value: value, onChanged: onChanged, ); } } class SettingsDropdownField extends StatelessWidget { const SettingsDropdownField({ super.key, required this.label, required this.value, required this.items, required this.itemLabel, required this.onChanged, }); final String label; final T value; final List items; final String Function(T) itemLabel; final ValueChanged onChanged; @override Widget build(BuildContext context) { return AppSearchableDropdown( label: label, value: value, searchHint: 'Search ${label.toLowerCase()}...', options: items .map( (item) => AppDropdownOption( value: item, label: itemLabel(item), ), ) .toList(), onChanged: onChanged, ); } } class SettingsSectionTile extends StatelessWidget { const SettingsSectionTile({ super.key, required this.title, required this.subtitle, required this.icon, required this.onTap, this.badge, this.enabled = true, }); final String title; final String subtitle; final IconData icon; final VoidCallback onTap; final String? badge; final bool enabled; @override Widget build(BuildContext context) { final theme = Theme.of(context); return AppCard( clipBehavior: Clip.antiAlias, onTap: enabled ? onTap : null, enableHover: enabled, child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( width: 44, height: 44, decoration: BoxDecoration( color: theme.colorScheme.primary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Icon(icon, color: theme.colorScheme.primary), ), const Spacer(), Icon( enabled ? Icons.chevron_right : Icons.lock_outline, color: theme.colorScheme.onSurfaceVariant, ), ], ), const SizedBox(height: 16), Row( children: [ Expanded( child: Text( title, style: theme.textTheme.titleSmall, maxLines: 1, overflow: TextOverflow.ellipsis, ), ), if (badge != null) ...[ const SizedBox(width: 8), Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 2, ), decoration: BoxDecoration( color: theme.colorScheme.secondaryContainer, borderRadius: BorderRadius.circular(8), ), child: Text( badge!, style: theme.textTheme.labelSmall, ), ), ], ], ), const SizedBox(height: 6), Expanded( child: Text( subtitle, maxLines: 2, overflow: TextOverflow.ellipsis, style: theme.textTheme.bodySmall?.copyWith( color: theme.colorScheme.onSurfaceVariant, ), ), ), ], ), ), ); } } class SettingsSectionGrid extends StatelessWidget { const SettingsSectionGrid({ super.key, required this.sections, required this.onSectionTap, this.enabled = true, this.badge, }); final List sections; final void Function(SettingsSection section) onSectionTap; final bool enabled; final String? badge; int _crossAxisCount(BuildContext context) { if (context.isMobile) return 1; if (context.isTablet) return 2; return 3; } @override Widget build(BuildContext context) { return GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: sections.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: _crossAxisCount(context), crossAxisSpacing: 16, mainAxisSpacing: 16, mainAxisExtent: 168, ), itemBuilder: (context, index) { final section = sections[index]; return SettingsSectionTile( title: section.title, subtitle: section.subtitle, icon: section.icon, badge: badge, enabled: enabled, onTap: () => onSectionTap(section), ); }, ); } }