Files
web-menu-react-version/src/pages/checkout/components/AddressSummary.tsx

160 lines
4.7 KiB
TypeScript

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, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { useAppDispatch, useAppSelector } from "redux/hooks";
import styles from "../../address/address.module.css";
import { OrderType } from "pages/checkout/hooks/types.ts";
interface LocationData {
lat: number;
lng: number;
address: string;
}
export const AddressSummary = () => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const { location } = useAppSelector(selectCart);
const [isMapBottomSheetOpen, setIsMapBottomSheetOpen] = useState(false);
const { orderType } = useAppSelector(selectCart);
const [userLocation, setUserLocation] = useState<LocationData | null>(null);
const handleLocationSave = useCallback(
(locationString: string) => {
try {
const locationData = JSON.parse(locationString) as LocationData;
dispatch(updateLocation(locationData));
} catch (error) {
console.error("Failed to parse location data:", error);
}
},
[dispatch],
);
const handleMapBottomSheetOpen = useCallback(() => {
setIsMapBottomSheetOpen(true);
}, []);
const handleMapBottomSheetClose = useCallback(() => {
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(
() => {
if (location) {
return JSON.stringify(location);
}
if (userLocation) {
return JSON.stringify(userLocation);
}
return "";
},
[location, userLocation],
);
const shouldRender = useMemo(
() => orderType === OrderType.Delivery,
[orderType],
);
if (!shouldRender) {
return null;
}
return (
<>
<Card
title={t("address.locationDetails")}
extra={
<Button
type="primary"
size="small"
onClick={handleMapBottomSheetOpen}
style={{
boxShadow: "none",
}}
>
{location
? t("address.changeLocation")
: t("address.selectLocation")}
</Button>
}
className={styles.addressCard}
>
{!location ? (
<div className={styles.noLocationContainer}>
<ProText type="secondary">
{t("address.noLocationSelected")}
</ProText>
<br />
<ProText type="secondary" className={styles.smallTextStyle}>
{t("address.clickEditToSelect")}
</ProText>
</div>
) : (
<div className={styles.mapContainer}>
<GoogleMap
readOnly={true}
initialLocation={location}
height="160px"
/>
</div>
)}
</Card>
<MapBottomSheet
isOpen={isMapBottomSheetOpen}
onClose={handleMapBottomSheetClose}
initialValue={initialValue}
onSave={handleLocationSave}
initialLocation={location || userLocation || undefined}
/>
</>
);
};