import 'package:flutter/material.dart'; import '../colors/app_colors.dart'; import '../colors/app_gradients.dart'; import '../main.dart' show supabase; import '../strings/address_strings.dart'; import '../strings/common_strings.dart'; import '../widgets/tap_bounce.dart'; import 'geocoding_service.dart'; /// Mostra o formulário de morada num modal bottom sheet, no mesmo estilo /// já usado para o formulário de adicionar criança. Devolve `true` se a /// morada foi guardada com sucesso. Future showAddressEditSheet( BuildContext context, { String? initialAddress, }) { return showModalBottomSheet( context: context, isScrollControlled: true, showDragHandle: true, backgroundColor: AppColors.pinkBackground, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(24)), ), builder: (ctx) => AddressEditSheet(initialAddress: initialAddress), ); } class AddressEditSheet extends StatefulWidget { const AddressEditSheet({super.key, this.initialAddress}); final String? initialAddress; @override State createState() => _AddressEditSheetState(); } class _AddressEditSheetState extends State { late final _addressController = TextEditingController( text: widget.initialAddress ?? '', ); bool _saving = false; String? _errorText; @override void dispose() { _addressController.dispose(); super.dispose(); } Future _save() async { final address = _addressController.text.trim(); if (address.isEmpty) { setState(() => _errorText = AddressStrings.addressRequired); return; } setState(() { _saving = true; _errorText = null; }); final coords = await GeocodingService.geocodeAddress(address); if (!mounted) return; if (coords == null) { setState(() { _saving = false; _errorText = AddressStrings.geocodeFailed; }); return; } final uid = supabase.auth.currentUser?.id; if (uid == null) { setState(() => _saving = false); return; } try { await supabase.from('profiles').upsert({ 'id': uid, 'address': address, 'address_lat': coords.lat, 'address_lon': coords.lon, }); if (!mounted) return; Navigator.of(context).pop(true); } catch (e) { if (!mounted) return; setState(() { _saving = false; _errorText = AddressStrings.saveError(e); }); } } @override Widget build(BuildContext context) { final bottomInset = MediaQuery.viewInsetsOf(context).bottom; return SafeArea( child: Padding( padding: EdgeInsets.fromLTRB(18, 6, 18, 18 + bottomInset), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text( AddressStrings.title, textAlign: TextAlign.center, style: TextStyle( fontSize: 18, fontWeight: FontWeight.w900, color: AppColors.pink, ), ), const SizedBox(height: 12), Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.82), borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.black.withValues(alpha: 0.08)), ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ TextField( controller: _addressController, enabled: !_saving, textInputAction: TextInputAction.done, textCapitalization: TextCapitalization.sentences, onSubmitted: (_) => _save(), decoration: InputDecoration( labelText: AddressStrings.label, hintText: AddressStrings.hint, errorText: _errorText, ), ), const SizedBox(height: 10), Text( AddressStrings.privacyDisclaimer, style: TextStyle( fontSize: 11.5, fontWeight: FontWeight.w600, color: Colors.black.withValues(alpha: 0.5), height: 1.35, ), ), ], ), ), const SizedBox(height: 14), Row( children: [ Expanded( child: SizedBox( height: 44, child: TextButton( onPressed: _saving ? null : () => Navigator.of(context).pop(false), child: const Text(CommonStrings.cancel), ), ), ), const SizedBox(width: 10), Expanded( child: TapBounce( child: ClipRRect( borderRadius: BorderRadius.circular(999), child: DecoratedBox( decoration: const BoxDecoration( gradient: kGreenButtonGradient, ), child: SizedBox( height: 44, child: FilledButton( style: FilledButton.styleFrom( backgroundColor: Colors.transparent, foregroundColor: Colors.white, shape: const StadiumBorder(), textStyle: const TextStyle( fontWeight: FontWeight.w900, ), ), onPressed: _saving ? null : _save, child: _saving ? const SizedBox( width: 18, height: 18, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : const Text(AddressStrings.save), ), ), ), ), ), ), ], ), ], ), ), ); } }