diff --git a/src/app/[name]/(Dialogs)/order/track/[id]/page.tsx b/src/app/[name]/(Dialogs)/order/track/[id]/page.tsx new file mode 100644 index 0000000..5acfafc --- /dev/null +++ b/src/app/[name]/(Dialogs)/order/track/[id]/page.tsx @@ -0,0 +1,228 @@ +'use client'; + +import { useParams, useRouter, useSearchParams } from 'next/navigation'; +import React, { useState, useEffect } from 'react'; +import dynamic from 'next/dynamic'; +import AnimatedBottomSheet from '@/components/bottomsheet/AnimatedBottomSheet'; +import Button from '@/components/button/PrimaryButton'; +import { Skeleton } from '@/components/ui/skeleton'; +import { MarkerData } from '@/app/[name]/(Profile)/profile/address/new/page'; +import { HandPlatter, Package } from 'lucide-react'; +import { motion } from 'framer-motion'; +import AnimatedBar from '@/components/utils/AnimatedBar'; +import { Clock } from 'iconsax-react'; +import BlurredOverlayContainer from '@/components/overlays/BlurredOverlayContainer'; +import clsx from 'clsx'; + +const CustomMap = dynamic( + () => import('@/components/map/CustomMap'), + { ssr: false } // Leaflet requires browser APIs +); + + +function OrderTrackingPage() { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { id } = useParams(); + const params = useSearchParams(); + // const [selectedPosition, setSelectedPosition] = useState<[number, number] | null>(null); + // const [selectedAddress, setSelectedAddress] = useState(null); + const [markers, setMarkers] = useState([]); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [mapCenter, setMapCenter] = useState<[number, number]>([Number(params?.get('lon')) || 35.6892, Number(params?.get('lon')) || 51.3890]); + const [bottomSheet1State, setBottomSheet1State] = useState(false); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [cancelModalVisibility, setCancelModalVisibility] = useState(false); + const router = useRouter(); + + // Example initial position (Tehran) + const initialPosition = React.useMemo<[number, number]>(() => [35.6892, 51.3890], []); + + useEffect(() => { + // Initialize markers on the client side + const initializeMarkers = async () => { + // Dynamic import of Leaflet on the client side + const L = (await import('leaflet')).default; + + setMarkers([ + { + position: initialPosition, + title: 'Restaurant Location', + icon: new L.Icon({ + iconUrl: '/icons/restaurant-marker.png', + iconSize: [25, 41], + iconAnchor: [12, 41], + popupAnchor: [1, -34], + }) + } + ]); + }; + + initializeMarkers(); + }, [initialPosition]); + + + const handleZoomChange = (zoom: number) => { + console.log('Zoom level:', zoom); + }; + + const handleMapClick = (e: L.LeafletMouseEvent) => { + console.log('Map clicked at:', e.latlng); + }; + + const toggleBottomSheet1 = () => { + setBottomSheet1State((prev) => !prev); + } + + const toggleCancelModal = async (e?: React.MouseEvent) => { + e?.preventDefault(); + e?.stopPropagation(); + setCancelModalVisibility((state) => !state); + } + + const onCancelOrder = (e: React.MouseEvent | null) => { + if (!e) return; + + }; + + return ( +
+ +
+ +
+ +
+
+ +
+ + +
+
+ + +
+
+
+

ارسال توسط پیک رستوران

+
+
+ +
+
+ +
+
+
+ +
+
+ + +
+
+ + + +
+
+
+ + + +
+
+
+ + {/* Logout Modal */} +
+
+ +
+ +
+ +

+ لفو سفارش +

+

+ آیا از درخواست خود اطمینان دارید؟ +

+
+ + +
+
+
+
+
+
+ ); +} + +export default OrderTrackingPage; \ No newline at end of file diff --git a/src/app/[name]/(Profile)/profile/address/new/page.tsx b/src/app/[name]/(Profile)/profile/address/new/page.tsx index c60b88c..455db99 100644 --- a/src/app/[name]/(Profile)/profile/address/new/page.tsx +++ b/src/app/[name]/(Profile)/profile/address/new/page.tsx @@ -186,7 +186,7 @@ function OrderTrackingPage() { @@ -250,7 +250,7 @@ function OrderTrackingPage() { diff --git a/src/components/map/CustomMap.tsx b/src/components/map/CustomMap.tsx index d25e23b..9ffdcc7 100644 --- a/src/components/map/CustomMap.tsx +++ b/src/components/map/CustomMap.tsx @@ -20,6 +20,7 @@ interface CustomMapProps { onPositionSelect?: (position: [number, number]) => void; onZoomChange?: (zoom: number) => void; onClick?: (event: L.LeafletMouseEvent) => void; + markerActive?: boolean } // Component to handle map events and position updates @@ -27,7 +28,7 @@ function MapEvents({ onZoomChange, onClick, center, - setMapRef + setMapRef, }: Pick & { center: [number, number]; setMapRef: (map: L.Map) => void; @@ -84,6 +85,7 @@ const CustomMap: React.FC = ({ onPositionSelect, onZoomChange, onClick, + markerActive = true }) => { const [selectedPosition, setSelectedPosition] = useState<[number, number] | null>(null); const [mapInstance, setMapInstance] = useState(null); @@ -120,7 +122,9 @@ const CustomMap: React.FC = ({ const handleMapClick = (e: L.LeafletMouseEvent) => { const newPosition: [number, number] = [e.latlng.lat, e.latlng.lng]; - setSelectedPosition(newPosition); + if (markerActive) { + setSelectedPosition(newPosition); + } onPositionSelect?.(newPosition); onClick?.(e); }; @@ -146,7 +150,7 @@ const CustomMap: React.FC = ({ // Iran's bounding box coordinates (roughly) const viewbox = '44.0,25.0,63.0,40.0'; // [min lon, min lat, max lon, max lat] const response = await fetch( - `https://nominatim.openstreetmap.org/search?` + + `https://nominatim.openstreetmap.org/search?` + `format=json&` + `q=${encodeURIComponent(value)}&` + `countrycodes=ir&` + // Prioritize Iran @@ -155,11 +159,11 @@ const CustomMap: React.FC = ({ `limit=10&` + // Limit results to 10 `namedetails=1&` + // Get native names `accept-language=fa` // Request Persian results - , { - headers: { - 'Accept-Language': 'fa,en;q=0.9' // Prefer Persian, fallback to English - } - }); + , { + headers: { + 'Accept-Language': 'fa,en;q=0.9' // Prefer Persian, fallback to English + } + }); interface SearchResult { place_id: string; display_name: string; @@ -179,8 +183,8 @@ const CustomMap: React.FC = ({ title: /* item.namedetails?.['name:fa'] || item.namedetails?.name || item.namedetails?.['alt_name:fa'] || - item.namedetails?.alt_name || */ - item.display_name, + item.namedetails?.alt_name || */ + item.display_name, position: [parseFloat(item.lat), parseFloat(item.lon)] as [number, number] }))); } catch (error) { diff --git a/src/components/utils/AnimatedBar.tsx b/src/components/utils/AnimatedBar.tsx new file mode 100644 index 0000000..44a453d --- /dev/null +++ b/src/components/utils/AnimatedBar.tsx @@ -0,0 +1,20 @@ +import { motion } from 'framer-motion' +import React from 'react' + +type Props = { + percentage: number | string +} + +function AnimatedBar({ percentage }: Props) { + return ( + + + + + ) +} + +export default AnimatedBar \ No newline at end of file