Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
43 lines
1.5 KiB
TypeScript
43 lines
1.5 KiB
TypeScript
export interface MapCoordinates {
|
|
lat: number
|
|
lng: number
|
|
}
|
|
|
|
const isLatitude = (value: number) => Number.isFinite(value) && value >= -90 && value <= 90
|
|
const isLongitude = (value: number) => Number.isFinite(value) && value >= -180 && value <= 180
|
|
|
|
export function hasMapCoordinates(lat: number | null | undefined, lng: number | null | undefined) {
|
|
return typeof lat === 'number' && typeof lng === 'number' && isLatitude(lat) && isLongitude(lng)
|
|
}
|
|
|
|
export function toMapCoordinates(lat: number | null | undefined, lng: number | null | undefined): MapCoordinates | null {
|
|
if (typeof lat !== 'number' || typeof lng !== 'number' || !hasMapCoordinates(lat, lng)) return null
|
|
|
|
return { lat, lng }
|
|
}
|
|
|
|
function coordinatePair({ lat, lng }: MapCoordinates) {
|
|
return `${lat},${lng}`
|
|
}
|
|
|
|
/** Opens the event pin in Neshan when the visitor's location is unavailable. */
|
|
export function getNeshanPlaceUrl(destination: MapCoordinates) {
|
|
const url = new URL('https://nshn.ir/')
|
|
|
|
url.searchParams.set('lat', String(destination.lat))
|
|
url.searchParams.set('lng', String(destination.lng))
|
|
|
|
return url.toString()
|
|
}
|
|
|
|
/** Opens driving directions in Neshan from a known origin to an event destination. */
|
|
export function getNeshanDirectionsUrl(origin: MapCoordinates, destination: MapCoordinates) {
|
|
const url = new URL('https://nshn.ir/maps')
|
|
|
|
url.searchParams.set('origin', coordinatePair(origin))
|
|
url.searchParams.set('destination', coordinatePair(destination))
|
|
url.searchParams.set('type', 'drive')
|
|
|
|
return url.toString()
|
|
}
|