import 'dart:async'; import 'dart:convert'; import 'dart:developer' as dev; import 'package:wanisclient/config/AppSnackbar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:geolocator/geolocator.dart'; import 'package:http/http.dart' as http; import 'package:latlong2/latlong.dart'; import 'package:provider/provider.dart'; import 'package:uuid/uuid.dart'; import '../config/constants/app_constant.dart'; import '../config/enum/ride_type.dart'; import '../providers/language_provider.dart'; import '../providers/ride_providers.dart'; import '../utils/colors.dart'; import 'map_screen.dart'; //STEP 2: Replace your CustomLocationInput widget with this: class CustomLocationInput extends StatefulWidget { final TextEditingController controller; final String hint; final Widget? iconstart; final bool showcardicon; final bool showcurrentlocationicon; final bool showclearicon; final bool isreadonly; final bool isFirst; final bool isLast; final bool disabled; final VoidCallback? onLocationClear; final Function(LatLng, String)? onLocationSelected; final VoidCallback? onFocus; const CustomLocationInput({ Key? key, required this.controller, required this.hint, this.iconstart, this.showcardicon = false, this.showcurrentlocationicon = false, this.showclearicon = true, this.isreadonly = false, this.isFirst = false, this.isLast = false, this.disabled = false, this.onLocationClear, this.onLocationSelected, this.onFocus, }) : super(key: key); @override State createState() => _CustomLocationInputState(); } class _CustomLocationInputState extends State { List> _searchResults = []; bool _showResults = false; Timer? _timer; final FocusNode _focusNode = FocusNode(); @override void initState() { super.initState(); // Listen to focus changes _focusNode.addListener(() { if (_focusNode.hasFocus && !widget.disabled) { widget.onFocus?.call(); } }); } @override void dispose() { _timer?.cancel(); _focusNode.dispose(); super.dispose(); } void _searchPlaces(String query) async { if (widget.disabled) return; if (query.length < 3) { setState(() { _searchResults = []; _showResults = false; }); return; } // Cancel previous timer _timer?.cancel(); // Wait 500ms before searching (debouncing) _timer = Timer(const Duration(milliseconds: 500), () async { final provider = context.read(); final results = await provider.searchPlaces(query); setState(() { _searchResults = results; _showResults = results.isNotEmpty; }); }); } void _selectPlace(Map place) async { if (widget.disabled) return; final provider = context.read(); final coordinates = await provider.getPlaceCoordinates(place['place_id']); if (coordinates != null) { widget.controller.text = place['description']; widget.onLocationSelected?.call(coordinates, place['description']); } setState(() { _showResults = false; }); } @override Widget build(BuildContext context) { return Column( children: [ Container( margin: const EdgeInsets.symmetric(vertical: 4.0), decoration: BoxDecoration( color: widget.disabled ? Colors.grey.shade200 : Colors.white, borderRadius: BorderRadius.circular(12.0), border: Border.all( color: widget.disabled ? Colors.grey.shade400 : Colors.grey.shade300, ), boxShadow: widget.disabled ? [] : [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 4.0, offset: const Offset(0, 2), ), ], ), child: Row( children: [ if (widget.iconstart != null) ...[ Padding( padding: const EdgeInsets.all(12.0), child: widget.disabled ? Opacity( opacity: 0.5, child: widget.iconstart, ) : widget.iconstart, ), ], Expanded( child: TextField( controller: widget.controller, focusNode: _focusNode, enabled: !widget.disabled, readOnly: widget.isreadonly || widget.disabled, style: TextStyle( color: widget.disabled ? Colors.grey.shade600 : Colors.black, ), decoration: InputDecoration( hintText: widget.hint, hintStyle: TextStyle( color: widget.disabled ? Colors.grey.shade500 : Colors.grey, ), border: InputBorder.none, contentPadding: const EdgeInsets.symmetric( vertical: 16.0, horizontal: 12.0, ), ), onChanged: _searchPlaces, onTap: () { // THIS IS THE KEY FIX - Call onFocus on tap as well if (!widget.disabled) { widget.onFocus?.call(); } }, ), ), if (widget.showclearicon && widget.controller.text.isNotEmpty && !widget.disabled) ...[ IconButton( onPressed: () { widget.controller.clear(); widget.onLocationClear?.call(); setState(() { _showResults = false; }); }, icon: const Icon(Icons.clear, color: Colors.grey), ), ], ], ), ), // Search results dropdown if (_showResults && !widget.disabled) Container( margin: const EdgeInsets.only(top: 4), decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(8), boxShadow: const [ BoxShadow( color: Colors.black26, blurRadius: 4, offset: Offset(0, 2), ), ], ), child: ListView.builder( shrinkWrap: true, itemCount: _searchResults.length, itemBuilder: (context, index) { final place = _searchResults[index]; return ListTile( leading: const Icon(Icons.location_on), title: Text(place['description']), onTap: () => _selectPlace(place), ); }, ), ), ], ); } }