diff --git a/src/components/CustomBottomSheet/GoogleMap.tsx b/src/components/CustomBottomSheet/GoogleMap.tsx index 9c20edd..033bfc2 100644 --- a/src/components/CustomBottomSheet/GoogleMap.tsx +++ b/src/components/CustomBottomSheet/GoogleMap.tsx @@ -85,25 +85,85 @@ function MapComponent({ }); markerRef.current = initialMarker; + // Geocode the initial location if address is not provided + if (!initialLocation.address && onLocationSelect) { + const geocoder = new google.maps.Geocoder(); + geocoder.geocode( + { + location: { + lat: initialLocation.lat, + lng: initialLocation.lng, + }, + }, + (results, status) => { + if (status === "OK" && results && results[0]) { + const address = results[0].formatted_address; + console.log( + "Initial location geocoded - calling onLocationSelect:", + { + lat: initialLocation.lat, + lng: initialLocation.lng, + address, + }, + ); + onLocationSelect( + initialLocation.lat, + initialLocation.lng, + address, + ); + } else { + console.log("Geocoding failed on initial location:", status); + // Fallback: use coordinates as address if geocoding fails + const fallbackAddress = `Location: ${initialLocation.lat.toFixed(6)}, ${initialLocation.lng.toFixed(6)}`; + console.log( + "Using fallback address for initial location:", + fallbackAddress, + ); + onLocationSelect( + initialLocation.lat, + initialLocation.lng, + fallbackAddress, + ); + } + }, + ); + } else if (initialLocation.address && onLocationSelect) { + // If address is already provided, just call onLocationSelect + onLocationSelect( + initialLocation.lat, + initialLocation.lng, + initialLocation.address, + ); + } + // Add drag end listener to the initial marker initialMarker.addListener("dragend", () => { const position = initialMarker.getPosition(); if (position) { const lat = position.lat(); const lng = position.lng(); - + // Get address from coordinates const geocoder = new google.maps.Geocoder(); geocoder.geocode({ location: { lat, lng } }, (results, status) => { if (status === "OK" && results && results[0]) { const address = results[0].formatted_address; - console.log('Initial marker drag - calling onLocationSelect:', { lat, lng, address }); + console.log( + "Initial marker drag - calling onLocationSelect:", + { lat, lng, address }, + ); onLocationSelect?.(lat, lng, address); } else { - console.log('Geocoding failed on initial marker drag:', status); + console.log( + "Geocoding failed on initial marker drag:", + status, + ); // Fallback: use coordinates as address if geocoding fails const fallbackAddress = `Location: ${lat.toFixed(6)}, ${lng.toFixed(6)}`; - console.log('Using fallback address for initial marker drag:', fallbackAddress); + console.log( + "Using fallback address for initial marker drag:", + fallbackAddress, + ); onLocationSelect?.(lat, lng, fallbackAddress); } }); diff --git a/src/components/CustomBottomSheet/MapBottomSheet.tsx b/src/components/CustomBottomSheet/MapBottomSheet.tsx index 59df802..fdd4806 100644 --- a/src/components/CustomBottomSheet/MapBottomSheet.tsx +++ b/src/components/CustomBottomSheet/MapBottomSheet.tsx @@ -11,6 +11,7 @@ interface MapBottomSheetProps { onClose: () => void; initialValue: string; onSave: (value: string) => void; + initialLocation?: { lat: number; lng: number; address?: string }; } interface LocationData { @@ -24,6 +25,7 @@ export function MapBottomSheet({ onClose, initialValue, onSave, + initialLocation, }: MapBottomSheetProps) { const { t } = useTranslation(); const [value, setValue] = useState(initialValue); @@ -35,8 +37,15 @@ export function MapBottomSheet({ useEffect(() => { setValue(initialValue); - // Try to parse initialValue as JSON to set selectedLocation - if (initialValue) { + // Priority: initialLocation > parsed initialValue + if (initialLocation) { + setSelectedLocation({ + lat: initialLocation.lat, + lng: initialLocation.lng, + address: initialLocation.address || "", + }); + } else if (initialValue) { + // Try to parse initialValue as JSON to set selectedLocation try { const parsed = JSON.parse(initialValue); if (parsed.lat && parsed.lng && parsed.address) { @@ -47,7 +56,7 @@ export function MapBottomSheet({ setSelectedLocation(null); } } - }, [initialValue]); + }, [initialValue, initialLocation]); const handleLocationSelect = (lat: number, lng: number, address: string) => { console.log('Location selected:', { lat, lng, address }); @@ -99,7 +108,11 @@ export function MapBottomSheet({ initialAddress={selectedLocation?.address || ""} /> ) : ( - + )} diff --git a/src/pages/checkout/components/AddressSummary.tsx b/src/pages/checkout/components/AddressSummary.tsx index 7030cf7..65b4460 100644 --- a/src/pages/checkout/components/AddressSummary.tsx +++ b/src/pages/checkout/components/AddressSummary.tsx @@ -1,9 +1,9 @@ -import { Button, Card } from "antd"; +import { Button, Card, message } from "antd"; import { GoogleMap } from "components/CustomBottomSheet/GoogleMap"; import { MapBottomSheet } from "components/CustomBottomSheet/MapBottomSheet"; import ProText from "components/ProText"; import { selectCart, updateLocation } from "features/order/orderSlice"; -import { useCallback, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { useAppDispatch, useAppSelector } from "redux/hooks"; import styles from "../../address/address.module.css"; @@ -20,7 +20,8 @@ export const AddressSummary = () => { const dispatch = useAppDispatch(); const { location } = useAppSelector(selectCart); const [isMapBottomSheetOpen, setIsMapBottomSheetOpen] = useState(false); - const { orderType } = useAppSelector(selectCart); // Default to delivery for now + const { orderType } = useAppSelector(selectCart); + const [userLocation, setUserLocation] = useState(null); const handleLocationSave = useCallback( (locationString: string) => { @@ -42,9 +43,58 @@ export const AddressSummary = () => { setIsMapBottomSheetOpen(false); }, []); + // Request user location when delivery order type is selected and no location exists + useEffect(() => { + if (orderType === OrderType.Delivery && !location && !userLocation) { + if ("geolocation" in navigator) { + navigator.geolocation.getCurrentPosition( + (position) => { + const lat = position.coords.latitude; + const lng = position.coords.longitude; + + // Set location with coordinates first, address will be geocoded by the map + const locationData: LocationData = { + lat, + lng, + address: "", // Will be filled by GoogleMap when it geocodes + }; + setUserLocation(locationData); + // Automatically set as default location + dispatch(updateLocation(locationData)); + }, + (error) => { + console.error("Error getting user location:", error); + message.warning( + t("address.locationPermissionDenied") || + "Location access denied. Please select location manually.", + ); + }, + { + enableHighAccuracy: true, + timeout: 10000, + maximumAge: 0, + }, + ); + } else { + message.warning( + t("address.geolocationNotSupported") || + "Geolocation is not supported by your browser", + ); + } + } + }, [orderType, location, userLocation, dispatch, t]); + const initialValue = useMemo( - () => (location ? JSON.stringify(location) : ""), - [location], + () => { + if (location) { + return JSON.stringify(location); + } + if (userLocation) { + return JSON.stringify(userLocation); + } + return ""; + }, + [location, userLocation], ); const shouldRender = useMemo( @@ -102,6 +152,7 @@ export const AddressSummary = () => { onClose={handleMapBottomSheetClose} initialValue={initialValue} onSave={handleLocationSave} + initialLocation={location || userLocation || undefined} /> );