add: order tracking page

This commit is contained in:
Mahyar Khanbolooki
2025-08-08 20:44:29 +03:30
parent 95a21b84ab
commit 0e67d02b5a
4 changed files with 264 additions and 12 deletions
+14 -10
View File
@@ -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<CustomMapProps, 'onZoomChange' | 'onClick'> & {
center: [number, number];
setMapRef: (map: L.Map) => void;
@@ -84,6 +85,7 @@ const CustomMap: React.FC<CustomMapProps> = ({
onPositionSelect,
onZoomChange,
onClick,
markerActive = true
}) => {
const [selectedPosition, setSelectedPosition] = useState<[number, number] | null>(null);
const [mapInstance, setMapInstance] = useState<L.Map | null>(null);
@@ -120,7 +122,9 @@ const CustomMap: React.FC<CustomMapProps> = ({
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<CustomMapProps> = ({
// 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<CustomMapProps> = ({
`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<CustomMapProps> = ({
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) {
+20
View File
@@ -0,0 +1,20 @@
import { motion } from 'framer-motion'
import React from 'react'
type Props = {
percentage: number | string
}
function AnimatedBar({ percentage }: Props) {
return (
<span className='relative w-full h-1 place-self-center bg-border rounded-full'>
<motion.span
animate={{ width: [0, `${percentage}%`] }}
className='absolute top-0 left-0 w-[10%] h-1 bg-primary rounded-full'
>
</motion.span>
</span>
)
}
export default AnimatedBar