fix location restaurant + show service area in new address

This commit is contained in:
hamid zarghami
2025-12-21 10:13:16 +03:30
parent 668172e8ee
commit 4c5e65d71e
4 changed files with 82 additions and 28 deletions
@@ -94,8 +94,8 @@ export const SummarySection = ({ cartModal, onToggleCartModal, deliveryType }: S
description: description || '', description: description || '',
deliveryMethodId: storeDeliveryType, deliveryMethodId: storeDeliveryType,
paymentMethodId: paymentType, paymentMethodId: paymentType,
...(selectedAddressId && !isDeliveryCar && { addressId: selectedAddressId }), ...(isCourierDelivery && selectedAddressId && { addressId: selectedAddressId }),
...(carAddress && { carAddress }), ...(isDeliveryCar && carAddress && { carAddress }),
}; };
saveAllMethod(saveAllMethodData, { saveAllMethod(saveAllMethodData, {
@@ -113,7 +113,7 @@ export const SummarySection = ({ cartModal, onToggleCartModal, deliveryType }: S
if (paymentType && paymentType !== '0') { if (paymentType && paymentType !== '0') {
orderData.paymentMethodId = paymentType; orderData.paymentMethodId = paymentType;
} }
if (selectedAddressId && !isDeliveryCar) { if (isCourierDelivery && selectedAddressId) {
orderData.addressId = selectedAddressId; orderData.addressId = selectedAddressId;
} }
if (tableNumber > 0) { if (tableNumber > 0) {
@@ -71,13 +71,18 @@ function OrderDetailInex() {
} }
}, [cartItems?.data?.paymentMethodId, setPaymentType, setIsSelectedPayment]); }, [cartItems?.data?.paymentMethodId, setPaymentType, setIsSelectedPayment]);
const selectedDeliveryMethod = useMemo(() => {
if (!shipmentMethod?.data || !deliveryType) return null;
return shipmentMethod.data.find((item) => item.id === deliveryType);
}, [shipmentMethod?.data, deliveryType]);
useEffect(() => { useEffect(() => {
if (cartItems?.data?.addressId) { if (cartItems?.data?.addressId && selectedDeliveryMethod?.method === 'deliveryCourier') {
const addressId = cartItems.data.addressId; const addressId = cartItems.data.addressId;
setIsSelectedAddress(true); setIsSelectedAddress(true);
setSelectedAddressId(addressId ?? null); setSelectedAddressId(addressId ?? null);
} }
}, [cartItems?.data?.addressId, setIsSelectedAddress, setSelectedAddressId]); }, [cartItems?.data?.addressId, setIsSelectedAddress, setSelectedAddressId, selectedDeliveryMethod]);
useEffect(() => { useEffect(() => {
if (cartItems?.data?.coupon?.couponCode && cartItems.data.couponDiscount > 0) { if (cartItems?.data?.coupon?.couponCode && cartItems.data.couponDiscount > 0) {
@@ -85,11 +90,6 @@ function OrderDetailInex() {
} }
}, [cartItems?.data?.coupon?.couponCode, cartItems?.data?.couponDiscount]); }, [cartItems?.data?.coupon?.couponCode, cartItems?.data?.couponDiscount]);
const selectedDeliveryMethod = useMemo(() => {
if (!shipmentMethod?.data || !deliveryType) return null;
return shipmentMethod.data.find((item) => item.id === deliveryType);
}, [shipmentMethod?.data, deliveryType]);
return ( return (
<div className='h-full bg-inherit flex flex-col gap-5'> <div className='h-full bg-inherit flex flex-col gap-5'>
<CheckoutHeader /> <CheckoutHeader />
@@ -11,6 +11,7 @@ import { AddressDetailsModal } from './components/AddressDetailsModal';
import { useAddressForm } from './hooks/useAddressForm'; import { useAddressForm } from './hooks/useAddressForm';
import { fetchAddressFromCoordinates } from './utils/fetchAddress'; import { fetchAddressFromCoordinates } from './utils/fetchAddress';
import { useGetAddressById } from '../hooks/useAddressData'; import { useGetAddressById } from '../hooks/useAddressData';
import { useGetAbout } from '@/app/[name]/(Main)/about/hooks/useAboutData';
const CustomMap = dynamic( const CustomMap = dynamic(
() => import('@/components/map/CustomMap'), () => import('@/components/map/CustomMap'),
@@ -24,6 +25,7 @@ function OrderTrackingPage() {
const editMode = !!id; const editMode = !!id;
const { data: addressResponse, isLoading: isLoadingAddress } = useGetAddressById(id); const { data: addressResponse, isLoading: isLoadingAddress } = useGetAddressById(id);
const { data: aboutData } = useGetAbout();
const address = addressResponse?.data; const address = addressResponse?.data;
const user = useAuthStore((state) => state.user); const user = useAuthStore((state) => state.user);
const [selectedPosition, setSelectedPosition] = useState<[number, number] | null>(null); const [selectedPosition, setSelectedPosition] = useState<[number, number] | null>(null);
@@ -31,17 +33,12 @@ function OrderTrackingPage() {
const [markers, setMarkers] = useState<MarkerData[]>([]); const [markers, setMarkers] = useState<MarkerData[]>([]);
const [initialPositionSet, setInitialPositionSet] = useState(false); const [initialPositionSet, setInitialPositionSet] = useState(false);
const getInitialMapCenter = (): [number, number] => { const restaurant = aboutData?.data;
if (editMode && address) {
return [address.latitude, address.longitude];
}
return [
Number(params?.get('lat')) || 35.6892,
Number(params?.get('lon')) || 51.3890
];
};
const [mapCenter, setMapCenter] = useState<[number, number]>(getInitialMapCenter()); const [mapCenter, setMapCenter] = useState<[number, number]>(() => [
Number(params?.get('lat')) || 35.6892,
Number(params?.get('lon')) || 51.3890
]);
const { state: confirmModal, toggle: toggleConfirmModal, set: setConfirmModal } = useToggle(); const { state: confirmModal, toggle: toggleConfirmModal, set: setConfirmModal } = useToggle();
const { state: detailsModal, toggle: _toggleDetailsModal, set: setDetailsModal } = useToggle(); const { state: detailsModal, toggle: _toggleDetailsModal, set: setDetailsModal } = useToggle();
@@ -53,10 +50,17 @@ function OrderTrackingPage() {
addressData: address || null, addressData: address || null,
}); });
useEffect(() => {
if (editMode && address) {
setMapCenter([address.latitude, address.longitude]);
} else if (restaurant?.latitude && restaurant?.longitude) {
setMapCenter([restaurant.latitude, restaurant.longitude]);
}
}, [editMode, address, restaurant]);
useEffect(() => { useEffect(() => {
if (editMode && address && !initialPositionSet) { if (editMode && address && !initialPositionSet) {
const position: [number, number] = [address.latitude, address.longitude]; const position: [number, number] = [address.latitude, address.longitude];
setMapCenter(position);
setSelectedPosition(position); setSelectedPosition(position);
setInitialPositionSet(true); setInitialPositionSet(true);
@@ -69,6 +73,7 @@ function OrderTrackingPage() {
} }
}, [editMode, address, initialPositionSet, setDetailsModal]); }, [editMode, address, initialPositionSet, setDetailsModal]);
useEffect(() => { useEffect(() => {
const initializeMarkers = async () => { const initializeMarkers = async () => {
const L = (await import('leaflet')).default; const L = (await import('leaflet')).default;
@@ -79,9 +84,16 @@ function OrderTrackingPage() {
</div> </div>
`; `;
setMarkers([ const restaurantPosition: [number, number] | null =
{ restaurant?.latitude && restaurant?.longitude
position: mapCenter, ? [restaurant.latitude, restaurant.longitude]
: null;
const markersToSet: MarkerData[] = [];
if (restaurantPosition) {
markersToSet.push({
position: restaurantPosition,
title: 'موقعیت رستوران', title: 'موقعیت رستوران',
icon: L.divIcon({ icon: L.divIcon({
html: iconHtml, html: iconHtml,
@@ -90,12 +102,14 @@ function OrderTrackingPage() {
iconAnchor: [20, 40], iconAnchor: [20, 40],
popupAnchor: [0, -40], popupAnchor: [0, -40],
}) })
} });
]); }
setMarkers(markersToSet);
}; };
initializeMarkers(); initializeMarkers();
}, [mapCenter]); }, [restaurant]);
const handlePositionSelect = (position: [number, number]) => { const handlePositionSelect = (position: [number, number]) => {
setSelectedPosition((prev) => { setSelectedPosition((prev) => {
@@ -150,6 +164,14 @@ function OrderTrackingPage() {
); );
} }
if (!restaurant) {
return null
}
const hasServiceArea = restaurant?.serviceArea &&
restaurant.serviceArea.coordinates &&
restaurant.serviceArea.coordinates.length > 0;
return ( return (
<div className="fixed inset-0 bg-gray-50"> <div className="fixed inset-0 bg-gray-50">
<div className="absolute inset-0"> <div className="absolute inset-0">
@@ -157,12 +179,23 @@ function OrderTrackingPage() {
initialPosition={mapCenter} initialPosition={mapCenter}
zoom={14} zoom={14}
markers={markers} markers={markers}
serviceArea={restaurant?.serviceArea || null}
onPositionSelect={handlePositionSelect} onPositionSelect={handlePositionSelect}
onZoomChange={handleZoomChange} onZoomChange={handleZoomChange}
onClick={handleMapClick} onClick={handleMapClick}
/> />
</div> </div>
{hasServiceArea && (
<div className="absolute top-4 left-4 right-4 z-[1000] max-w-sm">
<div className="bg-blue-50/90 border border-blue-200 rounded-lg p-3 shadow-sm">
<p className="text-xs text-blue-800">
محدوده سرویسدهی روی نقشه با رنگ آبی مشخص شده است
</p>
</div>
</div>
)}
<div className="absolute bottom-0 left-0 right-0 z-[1000]"> <div className="absolute bottom-0 left-0 right-0 z-[1000]">
<div className='relative w-full h-full'> <div className='relative w-full h-full'>
<ConfirmPositionModal <ConfirmPositionModal
+22 -1
View File
@@ -1,7 +1,7 @@
'use client'; 'use client';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { MapContainer, TileLayer, Marker, Popup, useMap, useMapEvents } from 'react-leaflet'; import { MapContainer, TileLayer, Marker, Popup, useMap, useMapEvents, Polygon } from 'react-leaflet';
import L from 'leaflet'; import L from 'leaflet';
import { Skeleton } from '@/components/ui/skeleton'; import { Skeleton } from '@/components/ui/skeleton';
import 'leaflet/dist/leaflet.css'; import 'leaflet/dist/leaflet.css';
@@ -9,6 +9,11 @@ import './CustomMap.css';
import { ActiveSearchbox } from '../input/ActiveSearchbox'; import { ActiveSearchbox } from '../input/ActiveSearchbox';
// Define types for our props // Define types for our props
interface ServiceArea {
type: "Polygon";
coordinates: number[][][];
}
interface CustomMapProps { interface CustomMapProps {
initialPosition: [number, number]; initialPosition: [number, number];
zoom?: number; zoom?: number;
@@ -17,6 +22,7 @@ interface CustomMapProps {
title: string; title: string;
icon?: L.Icon | L.DivIcon; icon?: L.Icon | L.DivIcon;
}>; }>;
serviceArea?: ServiceArea | null;
onPositionSelect?: (position: [number, number]) => void; onPositionSelect?: (position: [number, number]) => void;
onZoomChange?: (zoom: number) => void; onZoomChange?: (zoom: number) => void;
onClick?: (event: L.LeafletMouseEvent) => void; onClick?: (event: L.LeafletMouseEvent) => void;
@@ -102,6 +108,7 @@ const CustomMap: React.FC<CustomMapProps> = ({
initialPosition, initialPosition,
zoom = 13, zoom = 13,
markers = [], markers = [],
serviceArea,
onPositionSelect, onPositionSelect,
onZoomChange, onZoomChange,
onClick, onClick,
@@ -293,6 +300,20 @@ const CustomMap: React.FC<CustomMapProps> = ({
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/> />
{/* Service Area Polygon */}
{serviceArea && serviceArea.coordinates && serviceArea.coordinates.length > 0 && (
<Polygon
positions={serviceArea.coordinates[0].map(coord => [coord[1], coord[0]] as [number, number])}
pathOptions={{
color: '#3b82f6',
fillColor: '#3b82f6',
fillOpacity: 0.2,
weight: 2,
interactive: false,
}}
/>
)}
{/* Custom markers */} {/* Custom markers */}
{markers.map((marker, index) => ( {markers.map((marker, index) => (
<MarkerWithAutoOpen <MarkerWithAutoOpen