// Fixed overflow: added height constraint & scroll handling import 'package:wanisclient/config/custom_text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/authentification_provider.dart'; import '../providers/public_provider.dart'; import '../utils/colors.dart'; class CityDialog extends StatefulWidget { const CityDialog({super.key}); @override State createState() => _CityDialogState(); } class _CityDialogState extends State with SingleTickerProviderStateMixin { final _form_key = GlobalKey(); final _last_name_ctrl = TextEditingController(); final _first_name_ctrl = TextEditingController(); final _email_ctrl = TextEditingController(); DateTime? _birth_date; String? _selected_gender; String? _selected_city; late final AnimationController _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 300)); late final Animation _scale = CurvedAnimation(parent: _controller, curve: Curves.easeOutBack); @override void initState() { super.initState(); _controller.forward(); WidgetsBinding.instance.addPostFrameCallback((_) async { await context.read().fetchtunisiancity(); }); } @override void dispose() { _last_name_ctrl.dispose(); _first_name_ctrl.dispose(); _email_ctrl.dispose(); _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final public = context.watch(); final auth = context.watch(); final cities = public.cityNames; final theme = Theme.of(context); final is_dark = theme.brightness == Brightness.dark; final bg = is_dark ? const Color(0xFF1E1E1E) : Colors.white; InputDecoration _dec(String hint) => InputDecoration( hintText: hint, filled: true, fillColor: is_dark ? const Color(0xFF2B2B2B) : const Color(0xFFF4F4F4), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), ); Widget _label(String txt, {bool required = false}) => RichText( text: TextSpan( text: txt, style: theme.textTheme.bodyMedium ?.copyWith(fontWeight: FontWeight.w600), children: required ? [ const TextSpan( text: ' *', style: TextStyle(color: Colors.red)) ] : [], ), ); return WillPopScope( onWillPop: () async => false, child: ScaleTransition( scale: _scale, child: Dialog( insetPadding: const EdgeInsets.symmetric(horizontal: 32, vertical: 24), backgroundColor: bg, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), elevation: 8, child: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.85, minWidth: MediaQuery.of(context).size.width * 0.7, ), child: Form( key: _form_key, child: Column( mainAxisSize: MainAxisSize.max, children: [ // accent bar Container( height: 6, decoration: const BoxDecoration( color: AppColors.primaryColor, borderRadius: BorderRadius.vertical(top: Radius.circular(20))), ), // scrollable content Expanded( child: SingleChildScrollView( padding: const EdgeInsets.symmetric( horizontal: 24, vertical: 24), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row(children: [ const Icon(Icons.person_pin_circle, color: AppColors.primaryColor), const SizedBox(width: 8), Txt( text: 'Mandatory', style: theme.textTheme.titleMedium ?.copyWith(fontWeight: FontWeight.w600)) ]), const SizedBox(height: 16), _label('Name', required: true), const SizedBox(height: 6), TextFormField( controller: _last_name_ctrl, decoration: _dec('Enter your name'), validator: (v) => (v == null || v.trim().isEmpty) ? 'Required field' : null, ), const SizedBox(height: 14), _label('First name', required: true), const SizedBox(height: 6), TextFormField( controller: _first_name_ctrl, decoration: _dec('Enter your first name'), validator: (v) => (v == null || v.trim().isEmpty) ? 'Required field' : null, ), const SizedBox(height: 14), _label('City', required: true), const SizedBox(height: 6), cities.isEmpty ? const CupertinoActivityIndicator() : DropdownButtonFormField( value: _selected_city, isExpanded: true, decoration: _dec('City list'), items: cities .map((c) => DropdownMenuItem( value: c, child: Txt(text: c))) .toList(), onChanged: (v) => setState(() => _selected_city = v), validator: (v) => v == null ? 'Field required' : null, ), const SizedBox(height: 30), Row(children: [ const Icon(Icons.settings_suggest, color: AppColors.primaryColor), const SizedBox(width: 8), Txt( text: 'Option', style: theme.textTheme.titleMedium ?.copyWith(fontWeight: FontWeight.w600)) ]), const SizedBox(height: 16), _label('E-mail address'), const SizedBox(height: 6), TextFormField( controller: _email_ctrl, keyboardType: TextInputType.emailAddress, decoration: _dec('exemple@mail.com')), const SizedBox(height: 14), _label('Gender'), const SizedBox(height: 6), DropdownButtonFormField( value: _selected_gender, decoration: _dec('MALE / FEMALE'), items: const [ DropdownMenuItem( value: 'MALE', child: Txt(text: 'MALE')), DropdownMenuItem( value: 'FEMALE', child: Txt(text: 'FEMALE')) ], onChanged: (v) => setState(() => _selected_gender = v)), const SizedBox(height: 14), _label('Date of birth'), const SizedBox(height: 6), InkWell( onTap: () async { final now = DateTime.now(); final picked = await showDatePicker( context: context, initialDate: DateTime(now.year - 18), firstDate: DateTime(1900), lastDate: now); if (picked != null) setState(() => _birth_date = picked); }, child: InputDecorator( decoration: _dec('Select a date'), child: Text(_birth_date == null ? '' : '${_birth_date!.day}/${_birth_date!.month}/${_birth_date!.year}'))), const SizedBox(height: 24), SizedBox( width: double.infinity, height: 48, child: ElevatedButton( onPressed: () async { if (!_form_key.currentState!.validate()) return; final data = { 'name': "${_first_name_ctrl.text.trim()} ${_last_name_ctrl.text.trim()}", 'city': _selected_city, if (_email_ctrl.text.trim().isNotEmpty) 'email': _email_ctrl.text.trim(), if (_selected_gender != null) 'gender': _selected_gender, if (_birth_date != null) 'birthdate': _birth_date!.toIso8601String(), }; await auth.updateProfile(data); if (mounted) Navigator.pop(context); }, style: ElevatedButton.styleFrom( padding: EdgeInsets.zero, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(25))), child: Ink( decoration: BoxDecoration( gradient: LinearGradient(colors: [ AppColors.primaryColor, AppColors.primaryColor.withOpacity(.8) ]), borderRadius: BorderRadius.circular(25)), child: Center( child: Txt( text: 'Save', style: theme.textTheme.labelLarge ?.copyWith( color: Colors.white, fontWeight: FontWeight.w600))), ), ), ), ], ), ), ), ], ), ), ), ), ), ); } }