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:
Pontus Dreij
2024-11-22 07:19:13 +00:00
12 changed files with 63 additions and 44 deletions

View File

@@ -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>
) )

View File

@@ -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)

View File

@@ -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>

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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 : ""}`}

View File

@@ -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)
}
)

View File

@@ -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(),
})

View File

@@ -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(),

View File

@@ -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 }
}),
}),
}) })

View File

@@ -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":

View File

@@ -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>