Merged in fix/SW-946-map-center (pull request #954)
fix(946) Center from town name instead of calculate center Approved-by: Niclas Edenvin
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { notFound } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
import { getLocations } from "@/lib/trpc/memoizedRequests"
|
import { getCityCoordinates, getLocations } from "@/lib/trpc/memoizedRequests"
|
||||||
|
|
||||||
import { getHotelPins } from "@/components/HotelReservation/HotelCardDialogListing/utils"
|
import { getHotelPins } from "@/components/HotelReservation/HotelCardDialogListing/utils"
|
||||||
import SelectHotelMap from "@/components/HotelReservation/SelectHotel/SelectHotelMap"
|
import SelectHotelMap from "@/components/HotelReservation/SelectHotel/SelectHotelMap"
|
||||||
@@ -58,6 +58,7 @@ export default async function SelectHotelMapPage({
|
|||||||
|
|
||||||
const hotelPins = getHotelPins(hotels)
|
const hotelPins = getHotelPins(hotels)
|
||||||
const filterList = getFiltersFromHotels(hotels)
|
const filterList = getFiltersFromHotels(hotels)
|
||||||
|
const cityCoordinates = await getCityCoordinates({ city: city.name })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MapModal>
|
<MapModal>
|
||||||
@@ -67,6 +68,7 @@ export default async function SelectHotelMapPage({
|
|||||||
mapId={googleMapId}
|
mapId={googleMapId}
|
||||||
hotels={hotels}
|
hotels={hotels}
|
||||||
filterList={filterList}
|
filterList={filterList}
|
||||||
|
cityCoordinates={cityCoordinates}
|
||||||
/>
|
/>
|
||||||
</MapModal>
|
</MapModal>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -60,13 +60,20 @@ export default function Sidebar({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMouseEnter(poiName: string) {
|
function handleMouseEnter(poiName: string | undefined) {
|
||||||
|
if (!poiName) return
|
||||||
|
|
||||||
if (!isClicking) {
|
if (!isClicking) {
|
||||||
onActivePoiChange(poiName)
|
onActivePoiChange(poiName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePoiClick(poiName: string, poiCoordinates: Coordinates) {
|
function handlePoiClick(
|
||||||
|
poiName: string | undefined,
|
||||||
|
poiCoordinates: Coordinates
|
||||||
|
) {
|
||||||
|
if (!poiName || !poiCoordinates) return
|
||||||
|
|
||||||
setIsClicking(true)
|
setIsClicking(true)
|
||||||
toggleFullScreenSidebar()
|
toggleFullScreenSidebar()
|
||||||
onActivePoiChange(poiName)
|
onActivePoiChange(poiName)
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ export default function DynamicMap({
|
|||||||
activePoi={activePoi}
|
activePoi={activePoi}
|
||||||
hotelName={hotelName}
|
hotelName={hotelName}
|
||||||
pointsOfInterest={pointsOfInterest}
|
pointsOfInterest={pointsOfInterest}
|
||||||
onActivePoiChange={setActivePoi}
|
onActivePoiChange={(poi) => setActivePoi(poi ?? null)}
|
||||||
coordinates={coordinates}
|
coordinates={coordinates}
|
||||||
/>
|
/>
|
||||||
<InteractiveMap
|
<InteractiveMap
|
||||||
@@ -121,7 +121,7 @@ export default function DynamicMap({
|
|||||||
coordinates={coordinates}
|
coordinates={coordinates}
|
||||||
pointsOfInterest={pointsOfInterest}
|
pointsOfInterest={pointsOfInterest}
|
||||||
activePoi={activePoi}
|
activePoi={activePoi}
|
||||||
onActivePoiChange={setActivePoi}
|
onActivePoiChange={(poi) => setActivePoi(poi ?? null)}
|
||||||
mapId={mapId}
|
mapId={mapId}
|
||||||
/>
|
/>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { useMediaQuery } from "usehooks-ts"
|
|||||||
|
|
||||||
import { selectHotel } from "@/constants/routes/hotelReservation"
|
import { selectHotel } from "@/constants/routes/hotelReservation"
|
||||||
|
|
||||||
import { ArrowUpIcon, CloseIcon, CloseLargeIcon } from "@/components/Icons"
|
import { CloseIcon, CloseLargeIcon } from "@/components/Icons"
|
||||||
import InteractiveMap from "@/components/Maps/InteractiveMap"
|
import InteractiveMap from "@/components/Maps/InteractiveMap"
|
||||||
import { BackToTopButton } from "@/components/TempDesignSystem/BackToTopButton"
|
import { BackToTopButton } from "@/components/TempDesignSystem/BackToTopButton"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
@@ -15,7 +15,6 @@ import useLang from "@/hooks/useLang"
|
|||||||
|
|
||||||
import FilterAndSortModal from "../FilterAndSortModal"
|
import FilterAndSortModal from "../FilterAndSortModal"
|
||||||
import HotelListing from "./HotelListing"
|
import HotelListing from "./HotelListing"
|
||||||
import { getCentralCoordinates } from "./utils"
|
|
||||||
|
|
||||||
import styles from "./selectHotelMap.module.css"
|
import styles from "./selectHotelMap.module.css"
|
||||||
|
|
||||||
@@ -27,6 +26,7 @@ export default function SelectHotelMap({
|
|||||||
mapId,
|
mapId,
|
||||||
hotels,
|
hotels,
|
||||||
filterList,
|
filterList,
|
||||||
|
cityCoordinates,
|
||||||
}: SelectHotelMapProps) {
|
}: SelectHotelMapProps) {
|
||||||
const searchParams = useSearchParams()
|
const searchParams = useSearchParams()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -36,15 +36,13 @@ export default function SelectHotelMap({
|
|||||||
const [activeHotelPin, setActiveHotelPin] = useState<string | null>(null)
|
const [activeHotelPin, setActiveHotelPin] = useState<string | null>(null)
|
||||||
const [showBackToTop, setShowBackToTop] = useState<boolean>(false)
|
const [showBackToTop, setShowBackToTop] = useState<boolean>(false)
|
||||||
|
|
||||||
const centralCoordinates = getCentralCoordinates(hotelPins)
|
|
||||||
|
|
||||||
const coordinates = isAboveMobile
|
|
||||||
? centralCoordinates
|
|
||||||
: { ...centralCoordinates, lat: centralCoordinates.lat - 0.006 }
|
|
||||||
|
|
||||||
const selectHotelParams = new URLSearchParams(searchParams.toString())
|
const selectHotelParams = new URLSearchParams(searchParams.toString())
|
||||||
const selectedHotel = selectHotelParams.get("selectedHotel")
|
const selectedHotel = selectHotelParams.get("selectedHotel")
|
||||||
|
|
||||||
|
const coordinates = isAboveMobile
|
||||||
|
? cityCoordinates
|
||||||
|
: { ...cityCoordinates, lat: cityCoordinates.lat - 0.006 }
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedHotel) {
|
if (selectedHotel) {
|
||||||
setActiveHotelPin(selectedHotel)
|
setActiveHotelPin(selectedHotel)
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
import { HotelPin } from "@/types/components/hotelReservation/selectHotel/map"
|
|
||||||
|
|
||||||
export function getCentralCoordinates(hotels: HotelPin[]) {
|
|
||||||
const centralCoordinates = hotels.reduce(
|
|
||||||
(acc, pin) => {
|
|
||||||
acc.lat += pin.coordinates.lat
|
|
||||||
acc.lng += pin.coordinates.lng
|
|
||||||
return acc
|
|
||||||
},
|
|
||||||
{ lat: 0, lng: 0 }
|
|
||||||
)
|
|
||||||
|
|
||||||
centralCoordinates.lat /= hotels.length
|
|
||||||
centralCoordinates.lng /= hotels.length
|
|
||||||
|
|
||||||
return centralCoordinates
|
|
||||||
}
|
|
||||||
@@ -35,9 +35,9 @@ export default function HotelMapContent({
|
|||||||
position={poi.coordinates}
|
position={poi.coordinates}
|
||||||
anchorPoint={AdvancedMarkerAnchorPoint.CENTER}
|
anchorPoint={AdvancedMarkerAnchorPoint.CENTER}
|
||||||
zIndex={activePoi === poi.name ? 2 : 0}
|
zIndex={activePoi === poi.name ? 2 : 0}
|
||||||
onMouseEnter={() => onActivePoiChange?.(poi.name)}
|
onMouseEnter={() => onActivePoiChange?.(poi.name ?? null)}
|
||||||
onMouseLeave={() => onActivePoiChange?.(null)}
|
onMouseLeave={() => onActivePoiChange?.(null)}
|
||||||
onClick={() => toggleActivePoi(poi.name)}
|
onClick={() => toggleActivePoi(poi.name ?? "")}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className={`${styles.poi} ${activePoi === poi.name ? styles.active : ""}`}
|
className={`${styles.poi} ${activePoi === poi.name ? styles.active : ""}`}
|
||||||
|
|||||||
@@ -158,3 +158,9 @@ export const getBookingConfirmation = cache(
|
|||||||
return serverClient().booking.confirmation({ confirmationNumber })
|
return serverClient().booking.confirmation({ confirmationNumber })
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const getCityCoordinates = cache(
|
||||||
|
async function getMemoizedCityCoordinates(input: { city: string }) {
|
||||||
|
return serverClient().hotel.map.city(input)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|||||||
@@ -74,3 +74,6 @@ export const getRoomPackagesInputSchema = z.object({
|
|||||||
children: z.number().optional().default(0),
|
children: z.number().optional().default(0),
|
||||||
packageCodes: z.array(z.string()).optional().default([]),
|
packageCodes: z.array(z.string()).optional().default([]),
|
||||||
})
|
})
|
||||||
|
export const getCityCoordinatesInputSchema = z.object({
|
||||||
|
city: z.string(),
|
||||||
|
})
|
||||||
|
|||||||
@@ -200,14 +200,14 @@ const rewardNightSchema = z.object({
|
|||||||
|
|
||||||
export const pointOfInterestSchema = z
|
export const pointOfInterestSchema = z
|
||||||
.object({
|
.object({
|
||||||
name: z.string(),
|
name: z.string().optional(),
|
||||||
distance: z.number(),
|
distance: z.number().optional(),
|
||||||
category: z.object({
|
category: z.object({
|
||||||
name: z.string(),
|
name: z.string().optional(),
|
||||||
group: z.string(),
|
group: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
location: locationSchema,
|
location: locationSchema.optional(),
|
||||||
isHighlighted: z.boolean(),
|
isHighlighted: z.boolean().optional(),
|
||||||
})
|
})
|
||||||
.transform((poi) => ({
|
.transform((poi) => ({
|
||||||
name: poi.name,
|
name: poi.name,
|
||||||
@@ -215,8 +215,8 @@ export const pointOfInterestSchema = z
|
|||||||
categoryName: poi.category.name,
|
categoryName: poi.category.name,
|
||||||
group: getPoiGroupByCategoryName(poi.category.name),
|
group: getPoiGroupByCategoryName(poi.category.name),
|
||||||
coordinates: {
|
coordinates: {
|
||||||
lat: poi.location.latitude,
|
lat: poi.location?.latitude ?? 0,
|
||||||
lng: poi.location.longitude,
|
lng: poi.location?.longitude ?? 0,
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@@ -463,7 +463,9 @@ export const getHotelDataSchema = z.object({
|
|||||||
parking: z.array(parkingSchema),
|
parking: z.array(parkingSchema),
|
||||||
pointsOfInterest: z
|
pointsOfInterest: z
|
||||||
.array(pointOfInterestSchema)
|
.array(pointOfInterestSchema)
|
||||||
.transform((pois) => pois.sort((a, b) => a.distance - b.distance)),
|
.transform((pois) =>
|
||||||
|
pois.sort((a, b) => (a.distance ?? 0) - (b.distance ?? 0))
|
||||||
|
),
|
||||||
ratings: ratingsSchema,
|
ratings: ratingsSchema,
|
||||||
rewardNight: rewardNightSchema,
|
rewardNight: rewardNightSchema,
|
||||||
restaurantImages: facilitySchema.optional(),
|
restaurantImages: facilitySchema.optional(),
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import {
|
|||||||
import { getVerifiedUser, parsedUser } from "../user/query"
|
import { getVerifiedUser, parsedUser } from "../user/query"
|
||||||
import {
|
import {
|
||||||
getBreakfastPackageInputSchema,
|
getBreakfastPackageInputSchema,
|
||||||
|
getCityCoordinatesInputSchema,
|
||||||
getHotelDataInputSchema,
|
getHotelDataInputSchema,
|
||||||
getHotelsAvailabilityInputSchema,
|
getHotelsAvailabilityInputSchema,
|
||||||
getRatesInputSchema,
|
getRatesInputSchema,
|
||||||
@@ -1081,4 +1082,19 @@ export const hotelQueryRouter = router({
|
|||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
map: router({
|
||||||
|
city: serviceProcedure
|
||||||
|
.input(getCityCoordinatesInputSchema)
|
||||||
|
.query(async function ({ input }) {
|
||||||
|
const apiKey = process.env.GOOGLE_STATIC_MAP_KEY
|
||||||
|
const { city } = input
|
||||||
|
const url = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(city)}&key=${apiKey}`
|
||||||
|
|
||||||
|
const response = await fetch(url)
|
||||||
|
const data = await response.json()
|
||||||
|
const { lat, lng } = data.results[0].geometry.location
|
||||||
|
|
||||||
|
return { lat, lng }
|
||||||
|
}),
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -12,13 +12,14 @@ import {
|
|||||||
type Countries,
|
type Countries,
|
||||||
} from "./output"
|
} from "./output"
|
||||||
|
|
||||||
import type { Lang } from "@/constants/languages"
|
|
||||||
import type { Endpoint } from "@/lib/api/endpoints"
|
|
||||||
import type { RequestOptionsWithOutBody } from "@/types/fetch"
|
import type { RequestOptionsWithOutBody } from "@/types/fetch"
|
||||||
import { PointOfInterestGroupEnum } from "@/types/hotel"
|
import { PointOfInterestGroupEnum } from "@/types/hotel"
|
||||||
import { HotelLocation } from "@/types/trpc/routers/hotel/locations"
|
import { HotelLocation } from "@/types/trpc/routers/hotel/locations"
|
||||||
|
import type { Lang } from "@/constants/languages"
|
||||||
|
import type { Endpoint } from "@/lib/api/endpoints"
|
||||||
|
|
||||||
export function getPoiGroupByCategoryName(category: string) {
|
export function getPoiGroupByCategoryName(category: string | undefined) {
|
||||||
|
if (!category) return PointOfInterestGroupEnum.LOCATION
|
||||||
switch (category) {
|
switch (category) {
|
||||||
case "Airport":
|
case "Airport":
|
||||||
case "Bus terminal":
|
case "Bus terminal":
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export interface SelectHotelMapProps {
|
|||||||
mapId: string
|
mapId: string
|
||||||
hotels: HotelData[]
|
hotels: HotelData[]
|
||||||
filterList: CategorizedFilters
|
filterList: CategorizedFilters
|
||||||
|
cityCoordinates: Coordinates
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImageSizes = z.infer<typeof imageSizesSchema>
|
type ImageSizes = z.infer<typeof imageSizesSchema>
|
||||||
|
|||||||
Reference in New Issue
Block a user